1717 */
1818
1919use arrow_array:: RecordBatch ;
20- use arrow_flight:: encode:: FlightDataEncoderBuilder ;
2120use arrow_flight:: flight_service_server:: FlightServiceServer ;
2221use arrow_flight:: PollInfo ;
2322use arrow_schema:: ArrowError ;
2423
2524use datafusion:: common:: tree_node:: TreeNode ;
2625use serde_json:: json;
2726use std:: net:: SocketAddr ;
28- use std:: sync:: Arc ;
2927use std:: time:: Instant ;
3028use tonic:: codec:: CompressionEncoding ;
3129
@@ -34,34 +32,38 @@ use futures_util::{Future, TryFutureExt};
3432use tonic:: transport:: { Identity , Server , ServerTlsConfig } ;
3533use tonic_web:: GrpcWebLayer ;
3634
37- use crate :: event:: commit_schema;
3835use crate :: handlers:: http:: cluster:: get_ingestor_info;
39- use crate :: handlers:: http:: fetch_schema;
4036
37+ use crate :: handlers:: { CACHE_RESULTS_HEADER_KEY , CACHE_VIEW_HEADER_KEY , USER_ID_HEADER_KEY } ;
4138use crate :: metrics:: QUERY_EXECUTE_TIME ;
42- use crate :: option:: { Mode , CONFIG } ;
39+ use crate :: option:: CONFIG ;
4340
4441use crate :: handlers:: livetail:: cross_origin_config;
4542
46- use crate :: handlers:: http:: query:: { authorize_and_set_filter_tags, into_query} ;
43+ use crate :: handlers:: http:: query:: {
44+ authorize_and_set_filter_tags, into_query, put_results_in_cache, update_schema_when_distributed,
45+ } ;
4746use crate :: query:: { TableScanVisitor , QUERY_SESSION } ;
48- use crate :: storage :: object_storage :: commit_schema_to_storage ;
47+ use crate :: querycache :: QueryCacheManager ;
4948use crate :: utils:: arrow:: flight:: {
50- append_temporary_events, get_query_from_ticket, run_do_get_rpc, send_to_ingester,
49+ append_temporary_events, get_query_from_ticket, into_flight_data, run_do_get_rpc,
50+ send_to_ingester,
5151} ;
5252use arrow_flight:: {
5353 flight_service_server:: FlightService , Action , ActionType , Criteria , Empty , FlightData ,
5454 FlightDescriptor , FlightInfo , HandshakeRequest , HandshakeResponse , PutResult , SchemaAsIpc ,
5555 SchemaResult , Ticket ,
5656} ;
5757use arrow_ipc:: writer:: IpcWriteOptions ;
58- use futures:: { stream, TryStreamExt } ;
58+ use futures:: stream;
5959use tonic:: { Request , Response , Status , Streaming } ;
6060
6161use crate :: handlers:: livetail:: extract_session_key;
6262use crate :: metadata:: STREAM_INFO ;
6363use crate :: rbac:: Users ;
6464
65+ use super :: http:: query:: get_results_from_cache;
66+
6567#[ derive( Clone , Debug ) ]
6668pub struct AirServiceImpl { }
6769
@@ -130,7 +132,7 @@ impl FlightService for AirServiceImpl {
130132 async fn do_get ( & self , req : Request < Ticket > ) -> Result < Response < Self :: DoGetStream > , Status > {
131133 let key = extract_session_key ( req. metadata ( ) ) ?;
132134
133- let ticket = get_query_from_ticket ( req) ?;
135+ let ticket = get_query_from_ticket ( & req) ?;
134136
135137 log:: info!( "query requested to airplane: {:?}" , ticket) ;
136138
@@ -150,32 +152,57 @@ impl FlightService for AirServiceImpl {
150152 let mut visitor = TableScanVisitor :: default ( ) ;
151153 let _ = raw_logical_plan. visit ( & mut visitor) ;
152154
153- let tables = visitor. into_inner ( ) ;
154-
155- if CONFIG . parseable . mode == Mode :: Query {
156- // using http to get the schema. may update to use flight later
157- for table in tables {
158- if let Ok ( new_schema) = fetch_schema ( & table) . await {
159- // commit schema merges the schema internally and updates the schema in storage.
160- commit_schema_to_storage ( & table, new_schema. clone ( ) )
161- . await
162- . map_err ( |err| Status :: internal ( err. to_string ( ) ) ) ?;
163- commit_schema ( & table, Arc :: new ( new_schema) )
164- . map_err ( |err| Status :: internal ( err. to_string ( ) ) ) ?;
165- }
166- }
155+ let streams = visitor. into_inner ( ) ;
156+
157+ let query_cache_manager = QueryCacheManager :: global ( CONFIG . parseable . query_cache_size )
158+ . await
159+ . unwrap_or ( None ) ;
160+
161+ let cache_results = req
162+ . metadata ( )
163+ . get ( CACHE_RESULTS_HEADER_KEY )
164+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ; // I dont think we need to own this.
165+
166+ let show_cached = req
167+ . metadata ( )
168+ . get ( CACHE_VIEW_HEADER_KEY )
169+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ;
170+
171+ let user_id = req
172+ . metadata ( )
173+ . get ( USER_ID_HEADER_KEY )
174+ . and_then ( |value| value. to_str ( ) . ok ( ) ) ;
175+ let stream_name = streams
176+ . first ( )
177+ . ok_or_else ( || Status :: aborted ( "Malformed SQL Provided, Table Name Not Found" ) ) ?
178+ . to_owned ( ) ;
179+
180+ // send the cached results
181+ if let Ok ( cache_results) = get_results_from_cache (
182+ show_cached,
183+ query_cache_manager,
184+ & stream_name,
185+ user_id,
186+ & ticket. start_time ,
187+ & ticket. end_time ,
188+ & ticket. query ,
189+ ticket. send_null ,
190+ ticket. fields ,
191+ )
192+ . await
193+ {
194+ return cache_results. into_flight ( ) ;
167195 }
168196
197+ update_schema_when_distributed ( streams)
198+ . await
199+ . map_err ( |err| Status :: internal ( err. to_string ( ) ) ) ?;
200+
169201 // map payload to query
170202 let mut query = into_query ( & ticket, & session_state)
171203 . await
172204 . map_err ( |_| Status :: internal ( "Failed to parse query" ) ) ?;
173205
174- // if table name is not present it is a Malformed Query
175- let stream_name = query
176- . first_table_name ( )
177- . ok_or_else ( || Status :: invalid_argument ( "Malformed Query" ) ) ?;
178-
179206 let event =
180207 if send_to_ingester ( query. start . timestamp_millis ( ) , query. end . timestamp_millis ( ) ) {
181208 let sql = format ! ( "select * from {}" , & stream_name) ;
@@ -210,11 +237,23 @@ impl FlightService for AirServiceImpl {
210237 Status :: permission_denied ( "User Does not have permission to access this" )
211238 } ) ?;
212239 let time = Instant :: now ( ) ;
213- let ( results , _) = query
240+ let ( records , _) = query
214241 . execute ( stream_name. clone ( ) )
215242 . await
216243 . map_err ( |err| Status :: internal ( err. to_string ( ) ) ) ?;
217244
245+ put_results_in_cache (
246+ cache_results,
247+ user_id,
248+ query_cache_manager,
249+ & stream_name,
250+ & records,
251+ query. start . to_rfc3339 ( ) ,
252+ query. end . to_rfc3339 ( ) ,
253+ ticket. query ,
254+ )
255+ . await ;
256+
218257 /*
219258 * INFO: No returning the schema with the data.
220259 * kept it in case it needs to be sent in the future.
@@ -226,18 +265,7 @@ impl FlightService for AirServiceImpl {
226265 .collect::<Vec<_>>();
227266 let schema = Schema::try_merge(schemas).map_err(|err| Status::internal(err.to_string()))?;
228267 */
229- let input_stream = futures:: stream:: iter ( results. into_iter ( ) . map ( Ok ) ) ;
230- let write_options = IpcWriteOptions :: default ( )
231- . try_with_compression ( Some ( arrow_ipc:: CompressionType ( 1 ) ) )
232- . map_err ( |err| Status :: failed_precondition ( err. to_string ( ) ) ) ?;
233-
234- let flight_data_stream = FlightDataEncoderBuilder :: new ( )
235- . with_max_flight_data_size ( usize:: MAX )
236- . with_options ( write_options)
237- // .with_schema(schema.into())
238- . build ( input_stream) ;
239-
240- let flight_data_stream = flight_data_stream. map_err ( |err| Status :: unknown ( err. to_string ( ) ) ) ;
268+ let out = into_flight_data ( records) ;
241269
242270 if let Some ( event) = event {
243271 event. clear ( & stream_name) ;
@@ -248,9 +276,7 @@ impl FlightService for AirServiceImpl {
248276 . with_label_values ( & [ & format ! ( "flight-query-{}" , stream_name) ] )
249277 . observe ( time) ;
250278
251- Ok ( Response :: new (
252- Box :: pin ( flight_data_stream) as Self :: DoGetStream
253- ) )
279+ out
254280 }
255281
256282 async fn do_put (
0 commit comments