Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Documentation, git workflow, and DockerFile for crystal library
Browse files Browse the repository at this point in the history
  • Loading branch information
iamvigneshwars committed Feb 20, 2024
1 parent 4e6c951 commit 09fe8b8
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- chimp_chomp
- chimp_controller
- compound_library
- crystal_library
- pin_packing
- soakdb_sync
- targeting
Expand Down
10 changes: 10 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ COPY chimp_chomp/Cargo.toml chimp_chomp/Cargo.toml
COPY chimp_controller/Cargo.toml chimp_controller/Cargo.toml
COPY chimp_protocol/Cargo.toml chimp_protocol/Cargo.toml
COPY compound_library/Cargo.toml compound_library/Cargo.toml
COPY crystal_library/Cargo.toml crystal_library/Cargo.toml
COPY graphql_endpoints/Cargo.toml graphql_endpoints/Cargo.toml
COPY graphql_event_broker/Cargo.toml graphql_event_broker/Cargo.toml
COPY opa_client/Cargo.toml opa_client/Cargo.toml
Expand All @@ -28,6 +29,8 @@ RUN mkdir chimp_chomp/src \
&& echo "fn main() {}" > chimp_controller/src/main.rs \
&& mkdir compound_library/src \
&& echo "fn main() {}" > compound_library/src/main.rs \
&& mkdir crystal_library/src \
&& echo "fn main() {}" > crystal_library/src/main.rs \
&& mkdir graphql_endpoints/src \
&& touch graphql_endpoints/src/lib.rs \
&& mkdir graphql_event_broker/src \
Expand All @@ -53,6 +56,7 @@ RUN touch chimp_chomp/src/main.rs \
&& touch chimp_protocol/src/lib.rs \
&& touch chimp_controller/src/main.rs \
&& touch compound_library/src/main.rs \
&& touch crystal_library/src/main.rs \
&& touch graphql_endpoints/src/lib.rs \
&& touch graphql_event_broker/src/lib.rs \
&& touch opa_client/src/lib.rs \
Expand Down Expand Up @@ -97,6 +101,12 @@ COPY --from=build /app/target/release/compound_library /compound_library

ENTRYPOINT ["/compound_library"]

FROM gcr.io/distroless/cc as crystal_library

COPY --from=build /app/target/release/crystal_library /crystal_library

ENTRYPOINT ["/crystal_library"]

FROM gcr.io/distroless/cc as soakdb_sync

COPY --from=build /app/target/release/soakdb_sync /soakdb_sync
Expand Down
3 changes: 3 additions & 0 deletions backend/crystal_library/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Crystal Library Service

This service keeps track of all the crystals used for expeiments at the Diamond Light Source.
8 changes: 8 additions & 0 deletions backend/crystal_library/src/entities/crystal_wells.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,26 @@ use sea_orm::{
};
use uuid::Uuid;

/// Represents a crystal within the database.
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, SimpleObject)]
#[sea_orm(table_name = "crystal_wells")]
#[graphql(name = "crystal_wells")]
pub struct Model {
/// ID of the plate on which the crystal is located.
#[sea_orm(primary_key, auto_increment = false)]
pub plate_id: Uuid,
/// The well on the plate which the crystal is located.
#[sea_orm(primary_key, auto_increment = false)]
pub well_number: i16,
/// The identifier of the operator which added this entry.
pub operator_id: String,
/// The date and time when the compound instance was added.
pub timestamp: DateTime<Utc>,
/// Project proposal number
pub proposal_number: i32,
}

#[allow(clippy::missing_docs_in_private_items)]
#[derive(Clone, Copy, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

Expand Down
1 change: 1 addition & 0 deletions backend/crystal_library/src/entities/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/// The crystal wells modules
pub mod crystal_wells;
7 changes: 7 additions & 0 deletions backend/crystal_library/src/graphql/crystal_wells_res.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ use sea_orm::{ActiveValue, ColumnTrait, DatabaseConnection, EntityTrait, QueryFi
use the_paginator::graphql::{CursorInput, ModelConnection};
use uuid::Uuid;

/// CrystalQuery is a type that represents all the queries for the crystals.
#[derive(Debug, Clone, Default)]
pub struct CrystalQuery;

/// CrystalMutation is a type that represents all the mutations for the crystals.
#[derive(Debug, Clone, Default)]
pub struct CrystalMutation;

#[Object]
impl CrystalQuery {
/// This function fetches all crystals related from the database.
async fn crystals(
&self,
ctx: &Context<'_>,
Expand All @@ -28,6 +31,7 @@ impl CrystalQuery {
.try_into_connection()?)
}

/// This function fetches a single crystal using the plate_id and well number.
async fn crystal(
&self,
ctx: &Context<'_>,
Expand All @@ -46,18 +50,21 @@ impl CrystalQuery {

#[Object]
impl CrystalMutation {
/// This function adds a crystal to the database
async fn add_crystal(
&self,
ctx: &Context<'_>,
plate_id: Uuid,
well_number: i16,
proposal_number: i32,
) -> async_graphql::Result<crystal_wells::Model> {
let operator_id =
subject_authorization!("xchemlab.crystal_library.write_crystal", ctx).await?;
let db = ctx.data::<DatabaseConnection>()?;
let crystal = crystal_wells::ActiveModel {
plate_id: ActiveValue::Set(plate_id),
well_number: ActiveValue::Set(well_number),
proposal_number: ActiveValue::Set(proposal_number),
operator_id: ActiveValue::Set(operator_id),
timestamp: ActiveValue::Set(Utc::now()),
};
Expand Down
6 changes: 6 additions & 0 deletions backend/crystal_library/src/graphql/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
/// The cyrstal wells resolver module
pub mod crystal_wells_res;

use async_graphql::{EmptySubscription, MergedObject, Schema, SchemaBuilder};
use crystal_wells_res::{CrystalMutation, CrystalQuery};

/// Combines all query resolvers into a single GraphQL `Query` type.
#[derive(Debug, Clone, MergedObject, Default)]
pub struct Query(CrystalQuery);

/// Combines all mutation resolvers into a single GraphQL `Query` type.
#[derive(Debug, Clone, MergedObject, Default)]
pub struct Mutation(CrystalMutation);

/// Type alias for the complete GraphQL schema.
pub type RootSchema = Schema<Query, Mutation, EmptySubscription>;

/// This function initializes the schema with default instances of `Query`,
/// `Mutation`, and `EmptySubscription`.
pub fn root_schema_builder() -> SchemaBuilder<Query, Mutation, EmptySubscription> {
Schema::build(Query::default(), Mutation::default(), EmptySubscription).enable_federation()
}
31 changes: 30 additions & 1 deletion backend/crystal_library/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
#![doc=include_str!("../README.md")]

/// This module defines the structure and schema of the database tables
/// through various entity structs.
mod entities;
/// This module sets up the GraphQL schema, including queries, mutations,
/// and subscriptions. It defines how data is queried and mutated through the API.
mod graphql;
/// This module is responsible for defining and applying database migrations.
mod migrator;

use async_graphql::extensions::Tracing;
Expand All @@ -18,30 +28,44 @@ use std::{
};
use url::Url;

/// A service for tracking crystals available in the XChem lab
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
#[allow(clippy::large_enum_variant)]
enum Cli {
/// Starts a webserver serving the GraphQL API
Serve(ServeArgs),
/// Prints the GraphQL API to stdout
Schema(SchemaArgs),
}

#[derive(Debug, Parser)]
#[allow(clippy::missing_docs_in_private_items)]
struct ServeArgs {
/// The port number to serve on
#[arg(short, long, default_value_t = 80)]
port: u16,
/// URL for the database
#[arg(long, env)]
database_url: Url,
/// URL for the OPA server
#[arg(long, env)]
opa_url: Url,
}

/// Arguments for the `schema` command
#[derive(Debug, Parser)]
struct SchemaArgs {
/// Specifies an optional path to the file to save the schema
#[arg(short, long)]
path: Option<PathBuf>,
}

/// Sets up the database connection and performs the migrations
/// The database name is set of compound_library if not provided
///
/// Returns a `Result` with a `DatabaseConnection` on success,
/// or a `TransactionError<DbErr>` if connecting to the database or running
/// migrations fails
async fn setup_database(
mut database_url: Url,
) -> Result<DatabaseConnection, TransactionError<DbErr>> {
Expand All @@ -54,8 +78,12 @@ async fn setup_database(
Ok(connection)
}

/// Sets up the router for handling GraphQL queries and subscriptions
/// Returns a `Router` configured with routes
fn setup_router(schema: RootSchema) -> Router {
/// The endpoint for handling GraphQL queries and mutations
const GRAPHQL_ENDPOINT: &str = "/";
/// The endpoint for establishing WebSocket connections for GraphQL subscriptions
const SUBSCRIPTION_ENDPOINT: &str = "/ws";

Router::new()
Expand All @@ -70,6 +98,7 @@ fn setup_router(schema: RootSchema) -> Router {
.route_service(SUBSCRIPTION_ENDPOINT, GraphQLSubscription::new(schema))
}

/// Starts a web server to handle HTTP requests as defined in the provided `router`
async fn serve(router: Router, port: u16) {
let socket_addr: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port));
println!("GraphiQL IDE: {}", socket_addr);
Expand Down
3 changes: 3 additions & 0 deletions backend/crystal_library/src/migrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ use axum::async_trait;
use sea_orm::{DbErr, DeriveMigrationName, Schema};
use sea_orm_migration::{MigrationTrait, MigratorTrait, SchemaManager};

/// Migrator for managing and applying database migrations.
pub struct Migrator;

/// This struct is used to define the very first migration that sets up
/// the initial database schema.
#[derive(DeriveMigrationName)]
struct Initial;

Expand Down

0 comments on commit 09fe8b8

Please sign in to comment.