@@ -16,7 +16,10 @@ use common::{
16
16
CoDelQueueSender ,
17
17
} ,
18
18
execution_context:: ExecutionContext ,
19
- http:: fetch:: FetchClient ,
19
+ http:: {
20
+ fetch:: FetchClient ,
21
+ RoutedHttpPath ,
22
+ } ,
20
23
knobs:: {
21
24
FUNRUN_ISOLATE_ACTIVE_THREADS ,
22
25
ISOLATE_QUEUE_SIZE ,
@@ -60,6 +63,7 @@ use isolate::{
60
63
client:: {
61
64
initialize_v8,
62
65
EnvironmentData ,
66
+ HttpActionRequest ,
63
67
IsolateWorkerHandle ,
64
68
Request as IsolateRequest ,
65
69
RequestType as IsolateRequestType ,
@@ -75,8 +79,11 @@ use isolate::{
75
79
ActionRequestParams ,
76
80
ConcurrencyLimiter ,
77
81
FunctionOutcome ,
82
+ HttpActionRequest as HttpActionRequestInner ,
83
+ HttpActionResponseStreamer ,
78
84
IsolateConfig ,
79
85
UdfCallback ,
86
+ ValidatedHttpPath ,
80
87
ValidatedPathAndArgs ,
81
88
} ;
82
89
use keybroker:: {
@@ -121,6 +128,38 @@ const MAX_ISOLATE_WORKERS: usize = 128;
121
128
// active permits more frequently than that.
122
129
const ACTIVE_CONCURRENCY_PERMITS_LOG_FREQUENCY : Duration = Duration :: from_secs ( 10 ) ;
123
130
131
+ pub struct RunRequestArgs {
132
+ pub instance_name : String ,
133
+ pub instance_secret : InstanceSecret ,
134
+ pub reader : Arc < dyn PersistenceReader > ,
135
+ pub convex_origin : ConvexOrigin ,
136
+ pub bootstrap_metadata : BootstrapMetadata ,
137
+ pub table_count_snapshot : Arc < dyn TableCountSnapshot > ,
138
+ pub text_index_snapshot : Arc < dyn TransactionTextSnapshot > ,
139
+ pub action_callbacks : Arc < dyn ActionCallbacks > ,
140
+ pub fetch_client : Arc < dyn FetchClient > ,
141
+ pub log_line_sender : Option < mpsc:: UnboundedSender < LogLine > > ,
142
+ pub udf_type : UdfType ,
143
+ pub identity : Identity ,
144
+ pub ts : RepeatableTimestamp ,
145
+ pub existing_writes : FunctionWrites ,
146
+ pub system_env_vars : BTreeMap < EnvVarName , EnvVarValue > ,
147
+ pub in_memory_index_last_modified : BTreeMap < IndexId , Timestamp > ,
148
+ pub context : ExecutionContext ,
149
+ }
150
+
151
+ pub struct FunctionMetadata {
152
+ pub path_and_args : ValidatedPathAndArgs ,
153
+ pub journal : QueryJournal ,
154
+ }
155
+
156
+ pub struct HttpActionMetadata {
157
+ pub http_response_streamer : HttpActionResponseStreamer ,
158
+ pub http_module_path : ValidatedHttpPath ,
159
+ pub routed_path : RoutedHttpPath ,
160
+ pub http_request : HttpActionRequestInner ,
161
+ }
162
+
124
163
#[ async_trait]
125
164
pub trait StorageForInstance < RT : Runtime > : Debug + Clone + Send + Sync + ' static {
126
165
/// Gets a storage impl for a instance. Agnostic to what kind of storage -
@@ -336,25 +375,64 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
336
375
#[ minitrace:: trace]
337
376
pub async fn run_function_no_retention_check (
338
377
& self ,
339
- instance_name : String ,
340
- instance_secret : InstanceSecret ,
341
- reader : Arc < dyn PersistenceReader > ,
342
- convex_origin : ConvexOrigin ,
343
- bootstrap_metadata : BootstrapMetadata ,
344
- table_count_snapshot : Arc < dyn TableCountSnapshot > ,
345
- text_index_snapshot : Arc < dyn TransactionTextSnapshot > ,
346
- action_callbacks : Arc < dyn ActionCallbacks > ,
347
- fetch_client : Arc < dyn FetchClient > ,
348
- log_line_sender : Option < mpsc:: UnboundedSender < LogLine > > ,
349
- path_and_args : ValidatedPathAndArgs ,
350
- udf_type : UdfType ,
351
- identity : Identity ,
352
- ts : RepeatableTimestamp ,
353
- existing_writes : FunctionWrites ,
354
- journal : QueryJournal ,
355
- system_env_vars : BTreeMap < EnvVarName , EnvVarValue > ,
356
- in_memory_index_last_modified : BTreeMap < IndexId , Timestamp > ,
357
- context : ExecutionContext ,
378
+ run_request_args : RunRequestArgs ,
379
+ function_metadata : FunctionMetadata ,
380
+ ) -> anyhow:: Result < (
381
+ Option < FunctionFinalTransaction > ,
382
+ FunctionOutcome ,
383
+ FunctionUsageStats ,
384
+ ) > {
385
+ if run_request_args. udf_type == UdfType :: HttpAction {
386
+ anyhow:: bail!( "You can't run http actions from this method" ) ;
387
+ }
388
+ self . run_function_no_retention_check_inner ( run_request_args, Some ( function_metadata) , None )
389
+ . await
390
+ }
391
+
392
+ #[ minitrace:: trace]
393
+ pub async fn run_http_action_no_retention_check (
394
+ & self ,
395
+ run_request_args : RunRequestArgs ,
396
+ http_action_metadata : HttpActionMetadata ,
397
+ ) -> anyhow:: Result < ( FunctionOutcome , FunctionUsageStats ) > {
398
+ if run_request_args. udf_type != UdfType :: HttpAction {
399
+ anyhow:: bail!( "You can only run http actions with this method" ) ;
400
+ }
401
+ let ( _, outcome, stats) = self
402
+ . run_function_no_retention_check_inner (
403
+ run_request_args,
404
+ None ,
405
+ Some ( http_action_metadata) ,
406
+ )
407
+ . await ?;
408
+
409
+ Ok ( ( outcome, stats) )
410
+ }
411
+
412
+ #[ minitrace:: trace]
413
+ pub async fn run_function_no_retention_check_inner (
414
+ & self ,
415
+ RunRequestArgs {
416
+ instance_name,
417
+ instance_secret,
418
+ reader,
419
+ convex_origin,
420
+ bootstrap_metadata,
421
+ table_count_snapshot,
422
+ text_index_snapshot,
423
+ action_callbacks,
424
+ fetch_client,
425
+ log_line_sender,
426
+ udf_type,
427
+ identity,
428
+ ts,
429
+ existing_writes,
430
+ system_env_vars,
431
+ in_memory_index_last_modified,
432
+ context,
433
+ } : RunRequestArgs ,
434
+ function_metadata : Option < FunctionMetadata > ,
435
+ http_action_metadata : Option < HttpActionMetadata > ,
358
436
) -> anyhow:: Result < (
359
437
Option < FunctionFinalTransaction > ,
360
438
FunctionOutcome ,
@@ -410,6 +488,10 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
410
488
411
489
match udf_type {
412
490
UdfType :: Query | UdfType :: Mutation => {
491
+ let FunctionMetadata {
492
+ path_and_args,
493
+ journal,
494
+ } = function_metadata. context ( "Missing function metadata for query or mutation" ) ?;
413
495
let ( tx, rx) = oneshot:: channel ( ) ;
414
496
let request = IsolateRequest :: new (
415
497
instance_name,
@@ -439,6 +521,8 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
439
521
) )
440
522
} ,
441
523
UdfType :: Action => {
524
+ let FunctionMetadata { path_and_args, .. } =
525
+ function_metadata. context ( "Missing function metadata for action" ) ?;
442
526
let ( tx, rx) = oneshot:: channel ( ) ;
443
527
let log_line_sender =
444
528
log_line_sender. context ( "Missing log line sender for action" ) ?;
@@ -469,7 +553,43 @@ impl<RT: Runtime, S: StorageForInstance<RT>> FunctionRunnerCore<RT, S> {
469
553
) )
470
554
} ,
471
555
UdfType :: HttpAction => {
472
- anyhow:: bail!( "Funrun does not support http actions yet" )
556
+ let HttpActionMetadata {
557
+ http_response_streamer,
558
+ http_module_path,
559
+ routed_path,
560
+ http_request,
561
+ } = http_action_metadata. context ( "Missing http action metadata" ) ?;
562
+ let ( tx, rx) = oneshot:: channel ( ) ;
563
+ let log_line_sender =
564
+ log_line_sender. context ( "Missing log line sender for http action" ) ?;
565
+ let request = IsolateRequest :: new (
566
+ instance_name,
567
+ IsolateRequestType :: HttpAction {
568
+ request : HttpActionRequest {
569
+ http_module_path,
570
+ routed_path,
571
+ http_request,
572
+ identity,
573
+ transaction,
574
+ context,
575
+ } ,
576
+ response : tx,
577
+ queue_timer : queue_timer ( ) ,
578
+ action_callbacks,
579
+ fetch_client,
580
+ log_line_sender,
581
+ http_response_streamer,
582
+ environment_data,
583
+ } ,
584
+ EncodedSpan :: from_parent ( ) ,
585
+ ) ;
586
+ self . send_request ( request) ?;
587
+ let outcome = Self :: receive_response ( rx) . await ??;
588
+ Ok ( (
589
+ None ,
590
+ FunctionOutcome :: HttpAction ( outcome) ,
591
+ usage_tracker. gather_user_stats ( ) ,
592
+ ) )
473
593
} ,
474
594
}
475
595
}
@@ -593,31 +713,37 @@ impl<RT: Runtime> FunctionRunner<RT> for InProcessFunctionRunner<RT> {
593
713
. upgrade ( )
594
714
. context ( shutdown_error ( ) ) ?;
595
715
716
+ let request_metadata = RunRequestArgs {
717
+ instance_name : self . instance_name . clone ( ) ,
718
+ instance_secret : self . instance_secret ,
719
+ reader : self . persistence_reader . clone ( ) ,
720
+ convex_origin : self . convex_origin . clone ( ) ,
721
+ bootstrap_metadata : self . database . bootstrap_metadata . clone ( ) ,
722
+ table_count_snapshot,
723
+ text_index_snapshot,
724
+ action_callbacks,
725
+ fetch_client : self . fetch_client . clone ( ) ,
726
+ log_line_sender,
727
+ udf_type,
728
+ identity,
729
+ ts,
730
+ existing_writes,
731
+ system_env_vars,
732
+ in_memory_index_last_modified,
733
+ context,
734
+ } ;
735
+
596
736
// NOTE: We run the function without checking retention until after the
597
737
// function execution. It is important that we do not surface any errors
598
738
// or results until after we call `validate_run_function_result` below.
599
739
let result = self
600
740
. server
601
741
. run_function_no_retention_check (
602
- self . instance_name . clone ( ) ,
603
- self . instance_secret ,
604
- self . persistence_reader . clone ( ) ,
605
- self . convex_origin . clone ( ) ,
606
- self . database . bootstrap_metadata . clone ( ) ,
607
- table_count_snapshot,
608
- text_index_snapshot,
609
- action_callbacks,
610
- self . fetch_client . clone ( ) ,
611
- log_line_sender,
612
- path_and_args,
613
- udf_type,
614
- identity,
615
- ts,
616
- existing_writes,
617
- journal,
618
- system_env_vars,
619
- in_memory_index_last_modified,
620
- context,
742
+ request_metadata,
743
+ FunctionMetadata {
744
+ path_and_args,
745
+ journal,
746
+ } ,
621
747
)
622
748
. await ;
623
749
validate_run_function_result ( udf_type, * ts, self . database . retention_validator ( ) ) . await ?;
0 commit comments