Skip to content

Commit 2a6ba18

Browse files
Refactor arrow modules, update otel support
Signed-off-by: Ryan <ryan.roberts@btp.works>
1 parent 748474e commit 2a6ba18

File tree

24 files changed

+2143
-1933
lines changed

24 files changed

+2143
-1933
lines changed

Cargo.lock

Lines changed: 268 additions & 171 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ mockito = "1.1"
104104
newtype-derive-2018 = "0.2.1"
105105
oauth2 = "4.4"
106106
opa = { git = "https://github.com/chronicleworks/opa-rs", rev = "9fa2fbce" }
107-
opentelemetry = { version = "^0.21" }
107+
opentelemetry = { version = "0.22" }
108108
owo-colors = "3.5.0"
109109
parking_lot = "0.12.0"
110110
percent-encoding = "2.1.0"
@@ -149,7 +149,7 @@ toml = "0.7.3"
149149
tracing = "^0.1.35"
150150
tracing-elastic-apm = "^3.2.3"
151151
tracing-log = "^0.1.3"
152-
tracing-opentelemetry = "^0.22"
152+
tracing-opentelemetry = "0.23"
153153
tracing-subscriber = { version = "^0.3.15", features = [
154154
"default",
155155
"registry",

crates/api/src/chronicle_graphql/cursor_project.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@ use async_graphql::{
22
connection::{Edge, EmptyFields},
33
OutputType,
44
};
5-
use diesel::{
6-
prelude::*,
7-
r2d2::{ConnectionManager, PooledConnection},
8-
};
9-
10-
type Conn = PooledConnection<ConnectionManager<PgConnection>>;
115

126
pub fn project_to_nodes<T, I>(
137
rx: I,

crates/api/src/chronicle_graphql/mod.rs

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use async_graphql::{
2-
extensions::OpenTelemetry,
32
http::{playground_source, GraphQLPlaygroundConfig, ALL_WEBSOCKET_PROTOCOLS},
43
scalar, Context, Enum, Error, ErrorExtensions, ObjectType, Schema, ServerError, SimpleObject,
54
Subscription, SubscriptionType,
@@ -24,7 +23,7 @@ use diesel::{
2423
r2d2::{ConnectionManager, Pool, PooledConnection},
2524
PgConnection, Queryable,
2625
};
27-
use futures::{Future, Stream};
26+
use futures::Stream;
2827
use lazy_static::lazy_static;
2928
use poem::{
3029
get, handler,
@@ -629,18 +628,16 @@ where
629628
{
630629
type Output = poem::Response;
631630

632-
fn call(&self, req: poem::Request) -> impl Future<Output = poem::Result<Self::Output>> {
633-
async move {
634-
let checked_claims = check_claims(&self.secconf, &req).await?;
635-
self.respond(req, |api_req| {
636-
if let Some(claims) = checked_claims {
637-
api_req.0.data(claims)
638-
} else {
639-
api_req.0
640-
}
641-
})
642-
.await
643-
}
631+
async fn call(&self, req: poem::Request) -> poem::Result<Self::Output> {
632+
let checked_claims = check_claims(&self.secconf, &req).await?;
633+
self.respond(req, |api_req| {
634+
if let Some(claims) = checked_claims {
635+
api_req.0.data(claims)
636+
} else {
637+
api_req.0
638+
}
639+
})
640+
.await
644641
}
645642
}
646643

@@ -683,21 +680,19 @@ where
683680
{
684681
type Output = poem::Response;
685682

686-
fn call(&self, req: poem::Request) -> impl Future<Output = poem::Result<Self::Output>> {
687-
async move {
688-
let checked_claims = check_claims(&self.secconf, &req).await?;
689-
self.respond(
690-
req,
691-
if let Some(claims) = checked_claims {
692-
let mut data = async_graphql::Data::default();
693-
data.insert(claims);
694-
data
695-
} else {
696-
async_graphql::Data::default()
697-
},
698-
)
699-
.await
700-
}
683+
async fn call(&self, req: poem::Request) -> poem::Result<Self::Output> {
684+
let checked_claims = check_claims(&self.secconf, &req).await?;
685+
self.respond(
686+
req,
687+
if let Some(claims) = checked_claims {
688+
let mut data = async_graphql::Data::default();
689+
data.insert(claims);
690+
data
691+
} else {
692+
async_graphql::Data::default()
693+
},
694+
)
695+
.await
701696
}
702697
}
703698

@@ -858,15 +853,13 @@ impl IriEndpoint {
858853
impl Endpoint for IriEndpoint {
859854
type Output = poem::Response;
860855

861-
fn call(&self, req: poem::Request) -> impl Future<Output = poem::Result<Self::Output>> {
862-
async move {
863-
let checked_claims = if let Some(secconf) = &self.secconf {
864-
check_claims(secconf, &req).await?
865-
} else {
866-
None
867-
};
868-
self.respond(req, checked_claims.as_ref()).await
869-
}
856+
async fn call(&self, req: poem::Request) -> poem::Result<Self::Output> {
857+
let checked_claims = if let Some(secconf) = &self.secconf {
858+
check_claims(secconf, &req).await?
859+
} else {
860+
None
861+
};
862+
self.respond(req, checked_claims.as_ref()).await
870863
}
871864
}
872865

@@ -875,11 +868,9 @@ struct LdContextEndpoint;
875868
impl Endpoint for LdContextEndpoint {
876869
type Output = poem::Response;
877870

878-
fn call(&self, _req: poem::Request) -> impl Future<Output = poem::Result<Self::Output>> {
879-
async move {
880-
let context: &serde_json::Value = &common::context::PROV;
881-
Ok(IntoResponse::into_response(poem::web::Json(context)))
882-
}
871+
async fn call(&self, _req: poem::Request) -> poem::Result<Self::Output> {
872+
let context: &serde_json::Value = &common::context::PROV;
873+
Ok(IntoResponse::into_response(poem::web::Json(context)))
883874
}
884875
}
885876

@@ -1014,7 +1005,8 @@ where
10141005
.id_claims
10151006
.map(|id_claims| AuthFromJwt { id_claims, allow_anonymous: sec.allow_anonymous });
10161007
let mut schema = Schema::build(self.query, self.mutation, Subscription)
1017-
.extension(OpenTelemetry::new(opentelemetry::global::tracer("chronicle-api-gql")))
1008+
//TODO: update
1009+
// .extension(OpenTelemetry::new(opentelemetry::global::tracer("chronicle-api-gql")))
10181010
.extension(OpaCheck { claim_parser: claim_parser.clone() });
10191011
if let Some(claim_parser) = &claim_parser {
10201012
schema = schema.extension(claim_parser.clone());

crates/api/src/commands.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{path::PathBuf, sync::Arc};
44
use std::{path::PathBuf, sync::Arc};
55

66
use chrono::{DateTime, Utc};
7-
use futures::{AsyncRead, Future};
7+
use futures::AsyncRead;
88

99
use serde::{Deserialize, Serialize};
1010

crates/chronicle-arrow/src/lib.rs

Lines changed: 115 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use arrow_flight::{
1515
Ticket,
1616
};
1717

18-
use arrow_flight::{IpcMessage, SchemaAsIpc};
18+
use arrow_flight::{FlightEndpoint, IpcMessage, SchemaAsIpc};
1919

2020
use arrow_schema::ArrowError;
2121

@@ -31,12 +31,13 @@ use futures::{
3131
};
3232

3333
use meta::{DomainTypeMeta, Term};
34-
use operations::create_flight_info_for_type;
35-
use query::EntityAndReferences;
34+
use query::{
35+
activity_count_by_type, agent_count_by_type, entity_count_by_type, EntityAndReferences,
36+
};
3637
use r2d2::Pool;
3738
use serde::Serialize;
3839
use std::net::SocketAddr;
39-
use tokio::sync::Semaphore;
40+
use tokio::task::spawn_blocking;
4041

4142
use std::{sync::Arc, vec::Vec};
4243
use tonic::{transport::Server, Request, Response, Status, Streaming};
@@ -132,6 +133,101 @@ pub enum ChronicleArrowError {
132133
),
133134
}
134135

136+
#[instrument(skip(pool, term, domaintype))]
137+
pub async fn calculate_count_by_metadata_term(
138+
pool: &Pool<ConnectionManager<PgConnection>>,
139+
term: &Term,
140+
domaintype: Option<String>,
141+
) -> Result<i64, Status> {
142+
let pool = pool.clone();
143+
match term {
144+
Term::Entity =>
145+
spawn_blocking(move || {
146+
entity_count_by_type(
147+
&pool,
148+
domaintype.map(|x| x.to_string()).iter().map(|s| s.as_str()).collect(),
149+
)
150+
})
151+
.await,
152+
Term::Agent =>
153+
spawn_blocking(move || {
154+
agent_count_by_type(
155+
&pool,
156+
domaintype.map(|x| x.to_string()).iter().map(|s| s.as_str()).collect(),
157+
)
158+
})
159+
.await,
160+
Term::Activity =>
161+
spawn_blocking(move || {
162+
activity_count_by_type(
163+
&pool,
164+
domaintype.map(|x| x.to_string()).iter().map(|s| s.as_str()).collect(),
165+
)
166+
})
167+
.await,
168+
_ => Ok(Ok(0)),
169+
}
170+
.map_err(|e| Status::from_error(e.into()))
171+
.and_then(|res| res.map_err(|e| Status::from_error(e.into())))
172+
}
173+
174+
pub async fn create_flight_info_for_type(
175+
pool: Arc<Pool<ConnectionManager<PgConnection>>>,
176+
domain_items: Vec<impl TypeName + Send + Sync + 'static>,
177+
term: Term,
178+
record_batch_size: usize,
179+
) -> BoxStream<'static, Result<FlightInfo, Status>> {
180+
stream::iter(domain_items.into_iter().map(|item| Ok::<_, tonic::Status>(item)))
181+
.then(move |item| {
182+
let pool = pool.clone();
183+
async move {
184+
let item = item?; // Handle the Result from the iterator
185+
let descriptor_path = vec![term.to_string(), item.as_type_name()];
186+
let metadata =
187+
get_domain_type_meta_from_cache(&descriptor_path).ok_or_else(|| {
188+
Status::from_error(Box::new(ChronicleArrowError::MissingSchemaError))
189+
})?;
190+
191+
let count = calculate_count_by_metadata_term(
192+
&pool,
193+
&term,
194+
Some(item.as_type_name().to_string()),
195+
)
196+
.await?;
197+
198+
let tickets = (0..count)
199+
.step_by(record_batch_size as _)
200+
.map(|start| {
201+
let end = std::cmp::min(start as usize + record_batch_size, count as usize);
202+
203+
let ticket_metadata = ChronicleTicket::new(
204+
term,
205+
metadata.typ.as_ref().map(|x| x.as_domain_type_id()),
206+
start as _,
207+
(end - start as usize) as _,
208+
);
209+
Ticket::try_from(ticket_metadata)
210+
.map_err(|e| Status::from_error(Box::new(ChronicleArrowError::from(e))))
211+
})
212+
.collect::<Result<Vec<_>, _>>()?;
213+
214+
let mut flight_info = FlightInfo::new();
215+
216+
for ticket in tickets {
217+
flight_info =
218+
flight_info.with_endpoint(FlightEndpoint::new().with_ticket(ticket));
219+
}
220+
221+
Ok(flight_info
222+
.with_descriptor(FlightDescriptor::new_path(descriptor_path))
223+
.try_with_schema(&metadata.schema)
224+
.map_err(|e| Status::from_error(Box::new(ChronicleArrowError::from(e))))?
225+
.with_total_records(count))
226+
}
227+
})
228+
.boxed()
229+
}
230+
135231
#[derive(Clone)]
136232
pub struct FlightServiceImpl {
137233
domain: common::domain::ChronicleDomainDef,
@@ -336,12 +432,11 @@ impl FlightService for FlightServiceImpl {
336432
)
337433
.boxed()
338434
},
339-
_ => {
435+
_ =>
340436
return Err(Status::not_found(format!(
341437
"Definition not found for term: {:?}, type_name: {}",
342438
term, type_name
343-
)))
344-
},
439+
))),
345440
}
346441
.await;
347442

@@ -369,9 +464,8 @@ impl FlightService for FlightServiceImpl {
369464
let ipc_message_result = SchemaAsIpc::new(&schema.schema, &options).try_into();
370465
match ipc_message_result {
371466
Ok(IpcMessage(schema)) => Ok(Response::new(SchemaResult { schema })),
372-
Err(e) => {
373-
Err(Status::internal(format!("Failed to convert schema to IPC message: {}", e)))
374-
},
467+
Err(e) =>
468+
Err(Status::internal(format!("Failed to convert schema to IPC message: {}", e))),
375469
}
376470
}
377471

@@ -477,12 +571,8 @@ impl FlightService for FlightServiceImpl {
477571
Some(descriptor) => descriptor,
478572
None => return Err(Status::invalid_argument("Flight data has no descriptor")),
479573
},
480-
Some(Err(e)) => {
481-
return Err(Status::internal(format!(
482-
"Failed to get first item from stream: {}",
483-
e
484-
)))
485-
},
574+
Some(Err(e)) =>
575+
return Err(Status::internal(format!("Failed to get first item from stream: {}", e))),
486576
None => {
487577
return Err(Status::invalid_argument("Stream is empty"));
488578
},
@@ -613,8 +703,8 @@ mod tests {
613703
use crate::{
614704
meta::{cache_domain_schemas, get_domain_type_meta_from_cache, DomainTypeMeta},
615705
query::{
616-
ActedOnBehalfOfRef, ActivityAndReferences, AgentAndReferences, AgentAttributionRef,
617-
AssociationRef, DerivationRef, EntityAndReferences, EntityAttributionRef,
706+
ActedOnBehalfOfRef, ActivityAndReferences, ActivityAssociationRef, AgentAndReferences,
707+
AgentAttributionRef, DerivationRef, EntityAndReferences, EntityAttributionRef,
618708
},
619709
};
620710

@@ -693,16 +783,13 @@ roles:
693783
.iter()
694784
.map(|(name, typ)| {
695785
let value = match typ {
696-
PrimitiveType::String => {
697-
serde_json::Value::String(format!("{}-value", name))
698-
},
699-
PrimitiveType::Int => {
700-
serde_json::Value::Number(serde_json::Number::from(42))
701-
},
786+
PrimitiveType::String =>
787+
serde_json::Value::String(format!("{}-value", name)),
788+
PrimitiveType::Int =>
789+
serde_json::Value::Number(serde_json::Number::from(42)),
702790
PrimitiveType::Bool => serde_json::Value::Bool(true),
703-
PrimitiveType::JSON => {
704-
serde_json::Value::String(format!("{{\"{}\": \"example\"}}", name))
705-
},
791+
PrimitiveType::JSON =>
792+
serde_json::Value::String(format!("{{\"{}\": \"example\"}}", name)),
706793
};
707794
Attribute::new(name, value)
708795
})
@@ -797,7 +884,7 @@ roles:
797884
ended: Some(Utc.with_ymd_and_hms(2022, 1, 2, 0, 0, 0).unwrap()),
798885
generated: vec![format!("entity-{}", i), format!("entity-{}", i + 1)],
799886
was_informed_by: vec![format!("activity-{}", i), format!("activity-{}", i + 1)],
800-
was_associated_with: vec![AssociationRef {
887+
was_associated_with: vec![ActivityAssociationRef {
801888
responsible_agent: format!("agent-{}", i),
802889
responsible_role: Some("CERTIFIER".to_string()),
803890
delegate_agent: Some(format!("agent-{}", i + 1)),

0 commit comments

Comments
 (0)