Skip to content

Commit

Permalink
Fix the Product request on entities
Browse files Browse the repository at this point in the history
  • Loading branch information
jmbrunskill committed Feb 19, 2024
1 parent 998083d commit ca54df7
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 5 deletions.
1 change: 1 addition & 0 deletions backend/graphql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ util = { path = "../util" }
graphql_configuration = { path = "configuration" }
graphql_drug_interactions = { path = "drug_interactions" }
graphql_core = { path = "core" }
graphql_v1_core = { path = "../graphql_v1/core" }
graphql_barcode = { path = "barcode" }
graphql_types = { path = "types" }
graphql_general = { path = "general" }
Expand Down
3 changes: 2 additions & 1 deletion backend/graphql/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ doctest = false
repository = { path = "../../repository" }
service = { path = "../../service" }
util = { path = "../../util" }
graphql_v1_core = { path = "../../graphql_v1/core" }

actix-web = { version = "4.0.1", default-features = false, features = ["macros", "cookies"] }
anymap = "0.12"
Expand All @@ -24,4 +25,4 @@ serde = "1.0.126"
serde_json = "1.0.66"
thiserror = "1.0.30"
tokio = { version = "1.29", features = ["macros" ] }
async-std = "1.12"
async-std = { version = "1", features = ["attributes", "tokio1"] }
7 changes: 7 additions & 0 deletions backend/graphql/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ pub mod simple_generic_errors;
pub mod standard_graphql_error;
pub mod test_helpers;

use graphql_v1_core::loader::LoaderRegistry as LoaderRegistryV1;

use std::sync::Arc;

use actix_web::cookie::Cookie;
Expand Down Expand Up @@ -34,6 +36,7 @@ pub trait SelfRequest: Send + Sync {
pub trait ContextExt {
fn get_connection_manager(&self) -> &StorageConnectionManager;
fn get_loader<T: anymap::any::Any + Send + Sync>(&self) -> &T;
fn get_loader_v1<T: anymap::any::Any + Send + Sync>(&self) -> &T;
fn service_provider(&self) -> Arc<ServiceProvider>;
fn service_context(
&self,
Expand All @@ -55,6 +58,10 @@ impl<'a> ContextExt for Context<'a> {
self.data_unchecked::<Data<LoaderRegistry>>().get::<T>()
}

fn get_loader_v1<T: anymap::any::Any + Send + Sync>(&self) -> &T {
self.data_unchecked::<Data<LoaderRegistryV1>>().get::<T>()
}

fn service_provider(&self) -> Arc<ServiceProvider> {
self.data_unchecked::<Data<ServiceProvider>>()
.clone()
Expand Down
6 changes: 6 additions & 0 deletions backend/graphql/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use graphql_general::GeneralQueries;
use graphql_universal_codes::{UniversalCodesMutations, UniversalCodesQueries};
use graphql_universal_codes_v1::UniversalCodesV1Queries;
use graphql_user_account::{UserAccountMutations, UserAccountQueries};
use graphql_v1_core::loader::LoaderRegistry as LoaderRegistryV1;

use logger::{RequestLogger, ResponseLogger};
use repository::StorageConnectionManager;
Expand Down Expand Up @@ -76,6 +77,7 @@ pub fn schema_builder() -> Builder {
pub fn build_schema(
connection_manager: Data<StorageConnectionManager>,
loader_registry: Data<LoaderRegistry>,
loader_registry_v1: Data<LoaderRegistryV1>,
service_provider: Data<ServiceProvider>,
auth_data: Data<AuthData>,
settings_data: Data<Settings>,
Expand All @@ -86,6 +88,7 @@ pub fn build_schema(
let mut builder = schema_builder()
.data(connection_manager)
.data(loader_registry)
.data(loader_registry_v1)
.data(service_provider)
.data(auth_data)
.data(settings_data)
Expand Down Expand Up @@ -120,6 +123,7 @@ impl SelfRequest for SelfRequestImpl {
pub fn config(
connection_manager: Data<StorageConnectionManager>,
loader_registry: Data<LoaderRegistry>,
loader_registry_v1: Data<LoaderRegistryV1>,
service_provider: Data<ServiceProvider>,
auth_data: Data<AuthData>,
settings_data: Data<Settings>,
Expand All @@ -130,6 +134,7 @@ pub fn config(
schema: build_schema(
connection_manager.clone(),
loader_registry.clone(),
loader_registry_v1.clone(),
service_provider.clone(),
auth_data.clone(),
settings_data.clone(),
Expand All @@ -142,6 +147,7 @@ pub fn config(
let schema = build_schema(
connection_manager,
loader_registry,
loader_registry_v1,
service_provider,
auth_data,
settings_data,
Expand Down
1 change: 1 addition & 0 deletions backend/graphql_v1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ async-graphql = { version = "3.0.35", features = [
] }
async-graphql-actix-web = "3.0.35"
async-trait = "0.1.30"
tokio = { version = "1.29", features = ["macros"] }
log = "0.4.14"


6 changes: 6 additions & 0 deletions backend/graphql_v1/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ doctest = false

[dependencies]

dgraph = { path = "../../dgraph" }
service = { path = "../../service" }

actix-web = { version = "4.0.1", default-features = false, features = ["macros", "cookies"] }
anymap = "0.12"
async-graphql = { version = "3.0.35", features = ["dataloader", "chrono"] }
async-graphql-actix-web = "3.0.35"
async-trait = "0.1.30"
tokio = { version = "1.29", features = ["macros" ] }
async-std = { version = "1", features = ["attributes", "tokio1"] }
8 changes: 8 additions & 0 deletions backend/graphql_v1/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@ use std::sync::Arc;
use actix_web::web::Data;
use async_graphql::Context;

pub mod loader;

use loader::LoaderRegistry;
use service::service_provider::ServiceProvider;

#[allow(clippy::borrowed_box)]
// Sugar that helps make things neater and avoid errors that would only crop up at runtime.
pub trait ContextExt {
fn service_provider(&self) -> Arc<ServiceProvider>;
fn get_loader_v1<T: anymap::any::Any + Send + Sync>(&self) -> &T;
}

impl<'a> ContextExt for Context<'a> {
fn get_loader_v1<T: anymap::any::Any + Send + Sync>(&self) -> &T {
self.data_unchecked::<Data<LoaderRegistry>>().get::<T>()
}

fn service_provider(&self) -> Arc<ServiceProvider> {
self.data_unchecked::<Data<ServiceProvider>>()
.clone()
Expand Down
39 changes: 39 additions & 0 deletions backend/graphql_v1/core/src/loader/loader_registry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use actix_web::web::Data;
use anymap::{any::Any, Map};
use async_graphql::dataloader::DataLoader;

use service::service_provider::ServiceProvider;

use super::ProductLoader;

pub type LoaderMap = Map<AnyLoader>;
pub type AnyLoader = dyn Any + Send + Sync;

pub struct LoaderRegistry {
pub loaders: LoaderMap,
}

impl LoaderRegistry {
pub fn get<T: anymap::any::Any + Send + Sync>(&self) -> &T {
match self.loaders.get::<T>() {
Some(loader) => loader,
None => unreachable!("{} not found", std::any::type_name::<T>()),
}
}
}

pub async fn get_loaders_v1(service_provider: Data<ServiceProvider>) -> LoaderMap {
let mut loaders: LoaderMap = LoaderMap::new();

let dgraph_client = service_provider.dgraph_client();

let product_loader = DataLoader::new(
ProductLoader {
dgraph_client: dgraph_client.clone(),
},
async_std::task::spawn,
);
loaders.insert(product_loader);

loaders
}
5 changes: 5 additions & 0 deletions backend/graphql_v1/core/src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod loader_registry;
mod product;

pub use loader_registry::{get_loaders_v1, LoaderMap, LoaderRegistry};
pub use product::*;
49 changes: 49 additions & 0 deletions backend/graphql_v1/core/src/loader/product.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use async_graphql::dataloader::*;
use async_graphql::*;
use dgraph::{entity_with_parents_by_code, DgraphClient, Entity};
use std::collections::HashMap;

pub struct ProductLoader {
pub dgraph_client: DgraphClient,
}

#[async_trait::async_trait]
impl Loader<String> for ProductLoader {
type Value = Option<Entity>;
type Error = async_graphql::Error;

async fn load(
&self,
record_ids: &[String],
) -> Result<HashMap<String, Self::Value>, Self::Error> {
let mut result_map: HashMap<String, Option<Entity>> = HashMap::new();

for record_id in record_ids {
// Get the entity with all parents with the given record_id
let entity =
entity_with_parents_by_code(&self.dgraph_client, record_id.to_owned()).await?;
let product_entity = get_product_from_entity(entity);

result_map.insert(record_id.to_string(), product_entity);
}
Ok(result_map)
}
}

// Recursively get the product entity from the given entity
fn get_product_from_entity(entity: Option<Entity>) -> Option<Entity> {
println!("get_product_from_entity: {:?}", entity);

let entity = match entity {
Some(entity) => entity,
None => return None,
};
if entity.r#type == "Product" {
return Some(entity);
}

if entity.parents.len() > 0 {
return get_product_from_entity(Some(entity.parents[0].clone()));
}
None
}
12 changes: 11 additions & 1 deletion backend/graphql_v1/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use async_graphql::{EmptyMutation, EmptySubscription, MergedObject, SchemaBuilde
use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};
use graphql_universal_codes_v1::UniversalCodesV1Queries;

use graphql_v1_core::loader::LoaderRegistry;
use logger::{RequestLogger, ResponseLogger};
use repository::StorageConnectionManager;
use service::service_provider::ServiceProvider;
Expand All @@ -33,12 +34,14 @@ pub fn schema_builder() -> Builder {

pub fn build_schema(
connection_manager: Data<StorageConnectionManager>,
loader_registry: Data<LoaderRegistry>,
service_provider: Data<ServiceProvider>,
settings_data: Data<Settings>,
include_logger: bool,
) -> Schema {
let mut builder = schema_builder()
.data(connection_manager)
.data(loader_registry)
.data(service_provider)
.data(settings_data);

Expand All @@ -51,11 +54,18 @@ pub fn build_schema(

pub fn config(
connection_manager: Data<StorageConnectionManager>,
loader_registry: Data<LoaderRegistry>,
service_provider: Data<ServiceProvider>,
settings_data: Data<Settings>,
) -> impl FnOnce(&mut actix_web::web::ServiceConfig) {
|cfg| {
let schema = build_schema(connection_manager, service_provider, settings_data, true);
let schema = build_schema(
connection_manager,
loader_registry,
service_provider,
settings_data,
true,
);

cfg.app_data(Data::new(schema))
.service(
Expand Down
19 changes: 16 additions & 3 deletions backend/graphql_v1/universal_codes/src/types/entity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use async_graphql::dataloader::DataLoader;
use async_graphql::*;

use dgraph::Entity;

use graphql_v1_core::loader::ProductLoader;
use graphql_v1_core::ContextExt;

use crate::AlternativeNameType;
use crate::BarcodeType;

Expand Down Expand Up @@ -87,9 +92,17 @@ impl EntityType {
&self.alternative_names
}

pub async fn product(&self) -> Option<EntityType> {
// TODO: Probably a loader? Implement Product Lookup
None
pub async fn product(
&self,
ctx: &Context<'_>,
) -> Result<Option<EntityType>, async_graphql::Error> {
let loader = ctx.get_loader_v1::<DataLoader<ProductLoader>>();
let result = loader
.load_one(self.code.to_string())
.await?
.unwrap_or_default();

Ok(result.map(EntityType::from_domain))
}

pub async fn parents(&self) -> &Vec<EntityType> {
Expand Down
1 change: 1 addition & 0 deletions backend/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ maintainer-scripts = "debian/scripts"
graphql = { path = "../graphql" }
graphql_v1 = { path = "../graphql_v1" }
graphql_core = { path = "../graphql/core" }
graphql_v1_core = { path = "../graphql_v1/core" }
graphql_types = { path = "../graphql/types" }
dgraph = {path = "../dgraph"}
repository = { path = "../repository" }
Expand Down
9 changes: 9 additions & 0 deletions backend/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{

use self::middleware::{compress as compress_middleware, logger as logger_middleware};
use graphql_core::loader::{get_loaders, LoaderRegistry};
use graphql_v1_core::loader::get_loaders_v1;
use graphql_v1_core::loader::LoaderRegistry as LoaderRegistryV1;

use graphql::config as graphql_config;
use graphql_v1::config as graphql_v1_config;
Expand Down Expand Up @@ -69,6 +71,11 @@ async fn run_server(
let loaders = get_loaders(&connection_manager, service_provider_data.clone()).await;
let loader_registry_data = Data::new(LoaderRegistry { loaders });

let loaders_v1 = get_loaders_v1(service_provider_data.clone()).await;
let loader_registry_data_v1 = Data::new(LoaderRegistryV1 {
loaders: loaders_v1,
});

let settings_data = Data::new(config_settings.clone());

let restart_switch = Data::new(restart_switch);
Expand Down Expand Up @@ -140,13 +147,15 @@ async fn run_server(
.configure(graphql_config(
connection_manager_data_app.clone(),
loader_registry_data.clone(),
loader_registry_data_v1.clone(),
service_provider_data.clone(),
auth_data.clone(),
settings_data.clone(),
restart_switch.clone(),
))
.configure(graphql_v1_config(
connection_manager_data_app.clone(),
loader_registry_data_v1.clone(),
service_provider_data.clone(),
settings_data.clone(),
))
Expand Down
11 changes: 11 additions & 0 deletions backend/service/src/service_provider.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use dgraph::DgraphClient;
use repository::{RepositoryError, StorageConnection, StorageConnectionManager};

use crate::{
Expand Down Expand Up @@ -87,4 +88,14 @@ impl ServiceProvider {
pub fn connection(&self) -> Result<StorageConnection, RepositoryError> {
self.connection_manager.connection()
}

pub fn dgraph_client(&self) -> DgraphClient {
let url = format!(
"{}:{}/graphql",
self.settings.dgraph.host.clone(),
self.settings.dgraph.port
);

DgraphClient::new(&url)
}
}

0 comments on commit ca54df7

Please sign in to comment.