11use std:: {
22 collections:: BTreeMap ,
3+ fmt:: Debug ,
34 sync:: {
45 Arc ,
56 Weak ,
@@ -91,7 +92,10 @@ use parking_lot::{
9192 Mutex ,
9293 RwLock ,
9394} ;
94- use storage:: Storage ;
95+ use storage:: {
96+ Storage ,
97+ StorageUseCase ,
98+ } ;
9599use sync_types:: Timestamp ;
96100use usage_tracking:: {
97101 FunctionUsageStats ,
@@ -118,23 +122,35 @@ const MAX_ISOLATE_WORKERS: usize = 128;
118122const ACTIVE_CONCURRENCY_PERMITS_LOG_FREQUENCY : Duration = Duration :: from_secs ( 10 ) ;
119123
120124#[ async_trait]
121- pub trait StorageForInstance < RT : Runtime > : Clone + Send + Sync + ' static {
125+ pub trait StorageForInstance < RT : Runtime > : Debug + Clone + Send + Sync + ' static {
122126 /// Gets a storage impl for a instance. Agnostic to what kind of storage -
123127 /// local or s3, or how it was loaded (e.g. passed directly within backend,
124128 /// loaded from a transaction created in Funrun)
125129 async fn storage_for_instance (
126130 & self ,
127131 transaction : & mut Transaction < RT > ,
132+ use_case : StorageUseCase ,
128133 ) -> anyhow:: Result < Arc < dyn Storage > > ;
129134}
130135
136+ #[ derive( Clone , Debug ) ]
137+ pub struct InstanceStorage {
138+ pub files_storage : Arc < dyn Storage > ,
139+ pub modules_storage : Arc < dyn Storage > ,
140+ }
141+
131142#[ async_trait]
132- impl < RT : Runtime > StorageForInstance < RT > for Arc < dyn Storage > {
143+ impl < RT : Runtime > StorageForInstance < RT > for InstanceStorage {
133144 async fn storage_for_instance (
134145 & self ,
135146 _transaction : & mut Transaction < RT > ,
147+ use_case : StorageUseCase ,
136148 ) -> anyhow:: Result < Arc < dyn Storage > > {
137- Ok ( self . clone ( ) )
149+ match use_case {
150+ StorageUseCase :: Files => Ok ( self . files_storage . clone ( ) ) ,
151+ StorageUseCase :: Modules => Ok ( self . modules_storage . clone ( ) ) ,
152+ _ => anyhow:: bail!( "function runner storage does not support {use_case}" ) ,
153+ }
138154 }
139155}
140156
@@ -357,8 +373,15 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
357373 )
358374 . await ?;
359375 let mut transaction = transaction_ingredients. clone ( ) . try_into ( ) ?;
360- let storage = self . storage . storage_for_instance ( & mut transaction) . await ?;
376+ let storage = self
377+ . storage
378+ . storage_for_instance ( & mut transaction, StorageUseCase :: Files )
379+ . await ?;
361380 let file_storage = TransactionalFileStorage :: new ( self . rt . clone ( ) , storage, convex_origin) ;
381+ let modules_storage = self
382+ . storage
383+ . storage_for_instance ( & mut transaction, StorageUseCase :: Modules )
384+ . await ?;
362385
363386 let key_broker = KeyBroker :: new ( & instance_name, instance_secret) ?;
364387 let environment_data = EnvironmentData {
@@ -369,6 +392,7 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
369392 instance_name : instance_name. clone ( ) ,
370393 cache : self . module_cache . clone ( ) ,
371394 transaction_ingredients,
395+ modules_storage,
372396 } ) ,
373397 } ;
374398
@@ -434,7 +458,7 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
434458}
435459
436460pub struct InProcessFunctionRunner < RT : Runtime > {
437- server : FunctionRunnerCore < RT , Arc < dyn Storage > > ,
461+ server : FunctionRunnerCore < RT , InstanceStorage > ,
438462 persistence_reader : Arc < dyn PersistenceReader > ,
439463
440464 // Static information about the backend.
@@ -455,7 +479,7 @@ impl<RT: Runtime> InProcessFunctionRunner<RT> {
455479 convex_origin : ConvexOrigin ,
456480 rt : RT ,
457481 persistence_reader : Arc < dyn PersistenceReader > ,
458- storage : Arc < dyn Storage > ,
482+ storage : InstanceStorage ,
459483 database : Database < RT > ,
460484 fetch_client : Arc < dyn FetchClient > ,
461485 ) -> anyhow:: Result < Self > {
@@ -567,16 +591,19 @@ mod tests {
567591 } ;
568592 use model:: initialize_application_system_tables;
569593 use runtime:: testing:: TestRuntime ;
570- use storage:: {
571- LocalDirStorage ,
572- Storage ,
573- } ;
594+ use storage:: LocalDirStorage ;
574595
575- use crate :: server:: FunctionRunnerCore ;
596+ use crate :: server:: {
597+ FunctionRunnerCore ,
598+ InstanceStorage ,
599+ } ;
576600 #[ convex_macro:: test_runtime]
577601 async fn test_scheduler_workers_limit_requests ( rt : TestRuntime ) -> anyhow:: Result < ( ) > {
578602 initialize_v8 ( ) ;
579- let storage = Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) as Arc < dyn Storage > ;
603+ let storage = InstanceStorage {
604+ files_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
605+ modules_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
606+ } ;
580607 let function_runner_core = FunctionRunnerCore :: _new ( rt. clone ( ) , storage, 100 , 1 ) . await ?;
581608 let ( mut pause1, pause_client1) = PauseController :: new ( [ PAUSE_REQUEST ] ) ;
582609 let DbFixtures { db, .. } = DbFixtures :: new ( & rt) . await ?;
@@ -591,7 +618,7 @@ mod tests {
591618 let request2 = bogus_udf_request ( & db, client1, None , sender) . await ?;
592619 function_runner_core. send_request ( request2) ?;
593620 let response =
594- FunctionRunnerCore :: < TestRuntime , Arc < dyn Storage > > :: receive_response ( rx2) . await ?;
621+ FunctionRunnerCore :: < TestRuntime , InstanceStorage > :: receive_response ( rx2) . await ?;
595622 let err = response. unwrap_err ( ) ;
596623 assert ! ( err. is_rejected_before_execution( ) ) ;
597624 assert ! ( err. to_string( ) . contains( NO_AVAILABLE_WORKERS ) ) ;
@@ -603,7 +630,10 @@ mod tests {
603630 rt : TestRuntime ,
604631 ) -> anyhow:: Result < ( ) > {
605632 initialize_v8 ( ) ;
606- let storage = Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) as Arc < dyn Storage > ;
633+ let storage = InstanceStorage {
634+ files_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
635+ modules_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
636+ } ;
607637 let function_runner_core = FunctionRunnerCore :: _new ( rt. clone ( ) , storage, 50 , 2 ) . await ?;
608638 let ( mut pause1, pause_client1) = PauseController :: new ( [ PAUSE_REQUEST ] ) ;
609639 let DbFixtures { db, .. } = DbFixtures :: new ( & rt) . await ?;
@@ -619,14 +649,17 @@ mod tests {
619649 let client2 = "client2" ;
620650 let request2 = bogus_udf_request ( & db, client2, None , sender) . await ?;
621651 function_runner_core. send_request ( request2) ?;
622- FunctionRunnerCore :: < TestRuntime , Arc < dyn Storage > > :: receive_response ( rx2) . await ??;
652+ FunctionRunnerCore :: < TestRuntime , InstanceStorage > :: receive_response ( rx2) . await ??;
623653 Ok ( ( ) )
624654 }
625655
626656 #[ convex_macro:: test_runtime]
627657 async fn test_scheduler_throttles_same_client ( rt : TestRuntime ) -> anyhow:: Result < ( ) > {
628658 initialize_v8 ( ) ;
629- let storage = Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) as Arc < dyn Storage > ;
659+ let storage = InstanceStorage {
660+ files_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
661+ modules_storage : Arc :: new ( LocalDirStorage :: new ( rt. clone ( ) ) ?) ,
662+ } ;
630663 let function_runner_core = FunctionRunnerCore :: _new ( rt. clone ( ) , storage, 50 , 2 ) . await ?;
631664 let ( mut pause1, pause_client1) = PauseController :: new ( [ PAUSE_REQUEST ] ) ;
632665 let DbFixtures { db, .. } = DbFixtures :: new ( & rt) . await ?;
@@ -642,7 +675,7 @@ mod tests {
642675 let request2 = bogus_udf_request ( & db, client, None , sender) . await ?;
643676 function_runner_core. send_request ( request2) ?;
644677 let response =
645- FunctionRunnerCore :: < TestRuntime , Arc < dyn Storage > > :: receive_response ( rx2) . await ?;
678+ FunctionRunnerCore :: < TestRuntime , InstanceStorage > :: receive_response ( rx2) . await ?;
646679 let err = response. unwrap_err ( ) ;
647680 assert ! ( err. is_rejected_before_execution( ) ) ;
648681 assert ! ( err. to_string( ) . contains( NO_AVAILABLE_WORKERS ) ) ;
0 commit comments