reactive_graph_dynamic_graph_impl/object/namespace/
metrics.rs

1use async_graphql::dynamic::Field;
2use async_graphql::dynamic::FieldFuture;
3use async_graphql::dynamic::FieldValue;
4use async_graphql::dynamic::Object;
5use async_graphql::dynamic::ResolverContext;
6use async_graphql::dynamic::TypeRef;
7use reactive_graph_type_system_api::ComponentManager;
8use reactive_graph_type_system_api::EntityTypeManager;
9use reactive_graph_type_system_api::FlowTypeManager;
10use reactive_graph_type_system_api::RelationTypeManager;
11use std::sync::Arc;
12
13const TYPE_METRICS: &str = "NamespaceMetrics";
14const ROOT_NAMESPACE: &str = "root";
15
16#[derive(Debug)]
17enum ResolvedNamespace {
18    Root,
19    Namespace(String),
20}
21
22impl From<Option<String>> for ResolvedNamespace {
23    fn from(value: Option<String>) -> Self {
24        match value {
25            None => ResolvedNamespace::Root,
26            Some(namespace) => {
27                if namespace.as_str() == ROOT_NAMESPACE {
28                    ResolvedNamespace::Root
29                } else {
30                    ResolvedNamespace::Namespace(namespace)
31                }
32            }
33        }
34    }
35}
36
37pub fn metrics_type_name() -> TypeRef {
38    TypeRef::named_nn(TYPE_METRICS)
39}
40
41pub fn metrics_object() -> Object {
42    Object::new(TYPE_METRICS)
43        .field(Field::new("components", TypeRef::named_nn(TypeRef::INT), move |ctx| {
44            let namespace = extract_namespace_from_parent_value(&ctx);
45            FieldFuture::new(async move {
46                let component_manager = ctx.data::<Arc<dyn ComponentManager + Send + Sync>>()?;
47                let count = match namespace {
48                    ResolvedNamespace::Root => component_manager.count(),
49                    ResolvedNamespace::Namespace(namespace) => component_manager.count_by_namespace(&namespace),
50                };
51                Ok(Some(FieldValue::value(count)))
52            })
53        }))
54        .field(Field::new("entityTypes", TypeRef::named_nn(TypeRef::INT), move |ctx| {
55            let namespace = extract_namespace_from_parent_value(&ctx);
56            FieldFuture::new(async move {
57                let entity_type_manager = ctx.data::<Arc<dyn EntityTypeManager + Send + Sync>>()?;
58                let count = match namespace {
59                    ResolvedNamespace::Root => entity_type_manager.count(),
60                    ResolvedNamespace::Namespace(namespace) => entity_type_manager.count_by_namespace(&namespace),
61                };
62                Ok(Some(FieldValue::value(count)))
63            })
64        }))
65        .field(Field::new("relationTypes", TypeRef::named_nn(TypeRef::INT), move |ctx| {
66            let namespace = extract_namespace_from_parent_value(&ctx);
67            FieldFuture::new(async move {
68                let relation_type_manager = ctx.data::<Arc<dyn RelationTypeManager + Send + Sync>>()?;
69                let count = match namespace {
70                    ResolvedNamespace::Root => relation_type_manager.count(),
71                    ResolvedNamespace::Namespace(namespace) => relation_type_manager.count_by_namespace(&namespace),
72                };
73                Ok(Some(FieldValue::value(count)))
74            })
75        }))
76        .field(Field::new("flowTypes", TypeRef::named_nn(TypeRef::INT), move |ctx| {
77            let namespace = extract_namespace_from_parent_value(&ctx);
78            FieldFuture::new(async move {
79                let flow_type_manager = ctx.data::<Arc<dyn FlowTypeManager + Send + Sync>>()?;
80                let count = match namespace {
81                    ResolvedNamespace::Root => flow_type_manager.count(),
82                    ResolvedNamespace::Namespace(namespace) => flow_type_manager.count_by_namespace(&namespace),
83                };
84                Ok(Some(FieldValue::value(count)))
85            })
86        }))
87}
88
89pub fn metrics_field(namespace: Option<String>) -> Field {
90    let namespace = namespace.clone().unwrap_or("root".to_string());
91    Field::new("_metrics", metrics_type_name(), move |_ctx| {
92        let namespace = namespace.clone();
93        FieldFuture::new(async move { Ok(Some(FieldValue::value(namespace))) })
94    })
95}
96
97fn extract_namespace_from_parent_value(ctx: &ResolverContext) -> ResolvedNamespace {
98    ctx.parent_value
99        .as_value()
100        .and_then(|v| v.clone().into_json().ok().and_then(|value| value.as_str().map(|s| s.to_owned())))
101        .into()
102}