@@ -15,7 +15,7 @@ use arrow_flight::{
15
15
Ticket ,
16
16
} ;
17
17
18
- use arrow_flight:: { IpcMessage , SchemaAsIpc } ;
18
+ use arrow_flight:: { FlightEndpoint , IpcMessage , SchemaAsIpc } ;
19
19
20
20
use arrow_schema:: ArrowError ;
21
21
@@ -31,12 +31,13 @@ use futures::{
31
31
} ;
32
32
33
33
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
+ } ;
36
37
use r2d2:: Pool ;
37
38
use serde:: Serialize ;
38
39
use std:: net:: SocketAddr ;
39
- use tokio:: sync :: Semaphore ;
40
+ use tokio:: task :: spawn_blocking ;
40
41
41
42
use std:: { sync:: Arc , vec:: Vec } ;
42
43
use tonic:: { transport:: Server , Request , Response , Status , Streaming } ;
@@ -132,6 +133,101 @@ pub enum ChronicleArrowError {
132
133
) ,
133
134
}
134
135
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
+
135
231
#[ derive( Clone ) ]
136
232
pub struct FlightServiceImpl {
137
233
domain : common:: domain:: ChronicleDomainDef ,
@@ -336,12 +432,11 @@ impl FlightService for FlightServiceImpl {
336
432
)
337
433
. boxed ( )
338
434
} ,
339
- _ => {
435
+ _ =>
340
436
return Err ( Status :: not_found ( format ! (
341
437
"Definition not found for term: {:?}, type_name: {}" ,
342
438
term, type_name
343
- ) ) )
344
- } ,
439
+ ) ) ) ,
345
440
}
346
441
. await ;
347
442
@@ -369,9 +464,8 @@ impl FlightService for FlightServiceImpl {
369
464
let ipc_message_result = SchemaAsIpc :: new ( & schema. schema , & options) . try_into ( ) ;
370
465
match ipc_message_result {
371
466
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) ) ) ,
375
469
}
376
470
}
377
471
@@ -477,12 +571,8 @@ impl FlightService for FlightServiceImpl {
477
571
Some ( descriptor) => descriptor,
478
572
None => return Err ( Status :: invalid_argument ( "Flight data has no descriptor" ) ) ,
479
573
} ,
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) ) ) ,
486
576
None => {
487
577
return Err ( Status :: invalid_argument ( "Stream is empty" ) ) ;
488
578
} ,
@@ -613,8 +703,8 @@ mod tests {
613
703
use crate :: {
614
704
meta:: { cache_domain_schemas, get_domain_type_meta_from_cache, DomainTypeMeta } ,
615
705
query:: {
616
- ActedOnBehalfOfRef , ActivityAndReferences , AgentAndReferences , AgentAttributionRef ,
617
- AssociationRef , DerivationRef , EntityAndReferences , EntityAttributionRef ,
706
+ ActedOnBehalfOfRef , ActivityAndReferences , ActivityAssociationRef , AgentAndReferences ,
707
+ AgentAttributionRef , DerivationRef , EntityAndReferences , EntityAttributionRef ,
618
708
} ,
619
709
} ;
620
710
@@ -693,16 +783,13 @@ roles:
693
783
. iter ( )
694
784
. map ( |( name, typ) | {
695
785
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 ) ) ,
702
790
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) ) ,
706
793
} ;
707
794
Attribute :: new ( name, value)
708
795
} )
@@ -797,7 +884,7 @@ roles:
797
884
ended : Some ( Utc . with_ymd_and_hms ( 2022 , 1 , 2 , 0 , 0 , 0 ) . unwrap ( ) ) ,
798
885
generated : vec ! [ format!( "entity-{}" , i) , format!( "entity-{}" , i + 1 ) ] ,
799
886
was_informed_by : vec ! [ format!( "activity-{}" , i) , format!( "activity-{}" , i + 1 ) ] ,
800
- was_associated_with : vec ! [ AssociationRef {
887
+ was_associated_with : vec ! [ ActivityAssociationRef {
801
888
responsible_agent: format!( "agent-{}" , i) ,
802
889
responsible_role: Some ( "CERTIFIER" . to_string( ) ) ,
803
890
delegate_agent: Some ( format!( "agent-{}" , i + 1 ) ) ,
0 commit comments