1+ use super :: error:: { self as ex_error, Result } ;
2+ use super :: models:: { AsyncQueryHandle , QueryContext , QueryResult , QueryResultStatus } ;
3+ use super :: running_queries:: { RunningQueries , RunningQueriesRegistry , RunningQuery } ;
4+ use super :: session:: UserSession ;
5+ use crate :: running_queries:: RunningQueryId ;
6+ use crate :: session:: { SESSION_INACTIVITY_EXPIRATION_SECONDS , to_unix} ;
7+ use crate :: tracing:: SpanTracer ;
8+ use crate :: utils:: { Config , MemPoolType } ;
19use bytes:: { Buf , Bytes } ;
10+ use core_history:: HistoryStore ;
11+ use core_history:: SlateDBHistoryStore ;
12+ use core_history:: { QueryRecordId , QueryResultError , QueryStatus } ;
13+ use core_metastore:: {
14+ Database , Metastore , Schema , SchemaIdent , SlateDBMetastore , TableIdent as MetastoreTableIdent ,
15+ Volume , VolumeType ,
16+ } ;
217use datafusion:: arrow:: array:: RecordBatch ;
318use datafusion:: arrow:: csv:: ReaderBuilder ;
419use datafusion:: arrow:: csv:: reader:: Format ;
@@ -13,29 +28,13 @@ use datafusion::execution::memory_pool::{
1328} ;
1429use datafusion:: execution:: runtime_env:: { RuntimeEnv , RuntimeEnvBuilder } ;
1530use datafusion_common:: TableReference ;
31+ use df_catalog:: catalog_list:: { DEFAULT_CATALOG , EmbucketCatalogList } ;
1632use snafu:: ResultExt ;
1733use std:: num:: NonZeroUsize ;
1834use std:: sync:: atomic:: Ordering ;
1935use std:: vec;
2036use std:: { collections:: HashMap , sync:: Arc } ;
2137use time:: { Duration as DateTimeDuration , OffsetDateTime } ;
22-
23- use super :: error:: { self as ex_error, Result } ;
24- use super :: models:: { AsyncQueryHandle , QueryContext , QueryResult , QueryResultStatus } ;
25- use super :: running_queries:: { RunningQueries , RunningQueriesRegistry , RunningQuery } ;
26- use super :: session:: UserSession ;
27- use crate :: running_queries:: RunningQueryId ;
28- use crate :: session:: { SESSION_INACTIVITY_EXPIRATION_SECONDS , to_unix} ;
29- use crate :: tracing:: SpanTracer ;
30- use crate :: utils:: { Config , MemPoolType } ;
31- use core_history:: HistoryStore ;
32- use core_history:: SlateDBHistoryStore ;
33- use core_history:: { QueryRecordId , QueryResultError , QueryStatus } ;
34- use core_metastore:: {
35- Database , Metastore , Schema , SchemaIdent , SlateDBMetastore , TableIdent as MetastoreTableIdent ,
36- Volume , VolumeType ,
37- } ;
38- use df_catalog:: catalog_list:: { DEFAULT_CATALOG , EmbucketCatalogList } ;
3938use tokio:: sync:: RwLock ;
4039use tokio:: sync:: oneshot;
4140use tokio:: time:: { Duration , timeout} ;
@@ -44,6 +43,8 @@ use uuid::Uuid;
4443
4544const DEFAULT_SCHEMA : & str = "public" ;
4645
46+ pub const TIMEOUT_SIGNAL_INTERVAL_SECONDS : u64 = 60 ;
47+
4748#[ async_trait:: async_trait]
4849pub trait ExecutionService : Send + Sync {
4950 async fn create_session ( & self , session_id : & str ) -> Result < Arc < UserSession > > ;
@@ -145,6 +146,8 @@ pub trait ExecutionService: Send + Sync {
145146 file_name : & str ,
146147 format : Format ,
147148 ) -> Result < usize > ;
149+
150+ async fn timeout_signal ( & self , interval : Duration , idle_timeout : Duration ) -> ( ) ;
148151}
149152
150153pub struct CoreExecutionService {
@@ -891,6 +894,37 @@ impl ExecutionService for CoreExecutionService {
891894
892895 Ok ( rows_loaded)
893896 }
897+
898+ async fn timeout_signal ( & self , interval : Duration , idle_timeout : Duration ) -> ( ) {
899+ let mut interval = tokio:: time:: interval ( interval) ;
900+ interval. tick ( ) . await ; // The first tick completes immediately; skip.
901+ let mut idle_since: Option < std:: time:: Instant > = None ;
902+ loop {
903+ interval. tick ( ) . await ;
904+ let sessions_empty = {
905+ let sessions = self . df_sessions . read ( ) . await ;
906+ sessions. is_empty ( )
907+ } ;
908+ let queries_empty = self . queries . count ( ) == 0 ;
909+ let idle_now = sessions_empty && queries_empty;
910+ match ( idle_now, idle_since) {
911+ ( true , None ) => {
912+ // just entered idle
913+ idle_since = Some ( std:: time:: Instant :: now ( ) ) ;
914+ }
915+ ( true , Some ( since) ) => {
916+ if since. elapsed ( ) >= idle_timeout {
917+ // stayed idle long enough
918+ return ;
919+ }
920+ }
921+ ( false , _) => {
922+ // became active again, reset the idle window
923+ idle_since = None ;
924+ }
925+ }
926+ }
927+ }
894928}
895929
896930//Test environment
0 commit comments