11use crate :: prelude:: * ;
22
3- use crate :: execution:: { evaluator, memoization, row_indexer, stats} ;
3+ use crate :: execution:: { evaluator, indexing_status , memoization, row_indexer, stats} ;
44use crate :: lib_context:: LibContext ;
55use crate :: { base:: schema:: FlowSchema , ops:: interface:: SourceExecutorListOptions } ;
66use axum:: {
@@ -100,7 +100,7 @@ pub async fn get_keys(
100100}
101101
102102#[ derive( Deserialize ) ]
103- pub struct EvaluateDataParams {
103+ pub struct SourceRowKeyParams {
104104 field : String ,
105105 key : Vec < String > ,
106106}
@@ -111,56 +111,82 @@ pub struct EvaluateDataResponse {
111111 data : value:: ScopeValue ,
112112}
113113
114+ struct SourceRowKeyContextHolder < ' a > {
115+ plan : Arc < plan:: ExecutionPlan > ,
116+ import_op_idx : usize ,
117+ schema : & ' a FlowSchema ,
118+ key : value:: KeyValue ,
119+ }
120+
121+ impl < ' a > SourceRowKeyContextHolder < ' a > {
122+ async fn create ( flow_ctx : & ' a FlowContext , source_row_key : SourceRowKeyParams ) -> Result < Self > {
123+ let schema = & flow_ctx. flow . data_schema ;
124+ let import_op_idx = flow_ctx
125+ . flow
126+ . flow_instance
127+ . import_ops
128+ . iter ( )
129+ . position ( |op| op. name == source_row_key. field )
130+ . ok_or_else ( || {
131+ ApiError :: new (
132+ & format ! ( "source field not found: {}" , source_row_key. field) ,
133+ StatusCode :: BAD_REQUEST ,
134+ )
135+ } ) ?;
136+ let plan = flow_ctx. flow . get_execution_plan ( ) . await ?;
137+ let import_op = & plan. import_ops [ import_op_idx] ;
138+ let field_schema = & schema. fields [ import_op. output . field_idx as usize ] ;
139+ let table_schema = match & field_schema. value_type . typ {
140+ schema:: ValueType :: Table ( table) => table,
141+ _ => api_bail ! ( "field is not a table: {}" , source_row_key. field) ,
142+ } ;
143+ let key_field = table_schema
144+ . key_field ( )
145+ . ok_or_else ( || api_error ! ( "field {} does not have a key" , source_row_key. field) ) ?;
146+ let key = value:: KeyValue :: from_strs ( source_row_key. key , & key_field. value_type . typ ) ?;
147+ Ok ( Self {
148+ plan,
149+ import_op_idx,
150+ schema,
151+ key,
152+ } )
153+ }
154+
155+ fn as_context < ' b > ( & ' b self ) -> evaluator:: SourceRowEvaluationContext < ' b > {
156+ evaluator:: SourceRowEvaluationContext {
157+ plan : & self . plan ,
158+ import_op : & self . plan . import_ops [ self . import_op_idx ] ,
159+ schema : self . schema ,
160+ key : & self . key ,
161+ }
162+ }
163+ }
164+
114165pub async fn evaluate_data (
115166 Path ( flow_name) : Path < String > ,
116- Query ( query) : Query < EvaluateDataParams > ,
167+ Query ( query) : Query < SourceRowKeyParams > ,
117168 State ( lib_context) : State < Arc < LibContext > > ,
118169) -> Result < Json < EvaluateDataResponse > , ApiError > {
119170 let flow_ctx = lib_context. get_flow_context ( & flow_name) ?;
120- let schema = & flow_ctx. flow . data_schema ;
121-
122- let import_op_idx = flow_ctx
123- . flow
124- . flow_instance
125- . import_ops
126- . iter ( )
127- . position ( |op| op. name == query. field )
128- . ok_or_else ( || {
129- ApiError :: new (
130- & format ! ( "source field not found: {}" , query. field) ,
131- StatusCode :: BAD_REQUEST ,
132- )
133- } ) ?;
134- let plan = flow_ctx. flow . get_execution_plan ( ) . await ?;
135- let import_op = & plan. import_ops [ import_op_idx] ;
136- let field_schema = & schema. fields [ import_op. output . field_idx as usize ] ;
137- let table_schema = match & field_schema. value_type . typ {
138- schema:: ValueType :: Table ( table) => table,
139- _ => api_bail ! ( "field is not a table: {}" , query. field) ,
140- } ;
141- let key_field = table_schema
142- . key_field ( )
143- . ok_or_else ( || api_error ! ( "field {} does not have a key" , query. field) ) ?;
144- let key = value:: KeyValue :: from_strs ( query. key , & key_field. value_type . typ ) ?;
145-
171+ let source_row_key_ctx = SourceRowKeyContextHolder :: create ( & flow_ctx, query) . await ?;
146172 let evaluate_output = row_indexer:: evaluate_source_entry_with_memory (
147- & evaluator:: SourceRowEvaluationContext {
148- plan : & plan,
149- import_op,
150- schema,
151- key : & key,
152- } ,
173+ & source_row_key_ctx. as_context ( ) ,
153174 memoization:: EvaluationMemoryOptions {
154175 enable_cache : true ,
155176 evaluation_only : true ,
156177 } ,
157178 & lib_context. builtin_db_pool ,
158179 )
159180 . await ?
160- . ok_or_else ( || api_error ! ( "value not found for source at the specified key: {key:?}" ) ) ?;
181+ . ok_or_else ( || {
182+ api_error ! (
183+ "value not found for source at the specified key: {key:?}" ,
184+ key = source_row_key_ctx. key
185+ )
186+ } ) ?;
161187
162188 Ok ( Json ( EvaluateDataResponse {
163- schema : schema . clone ( ) ,
189+ schema : flow_ctx . flow . data_schema . clone ( ) ,
164190 data : evaluate_output. data_scope . into ( ) ,
165191 } ) )
166192}
@@ -182,3 +208,18 @@ pub async fn update(
182208 live_updater. wait ( ) . await ?;
183209 Ok ( Json ( live_updater. index_update_info ( ) ) )
184210}
211+
212+ pub async fn get_row_index_status (
213+ Path ( flow_name) : Path < String > ,
214+ Query ( query) : Query < SourceRowKeyParams > ,
215+ State ( lib_context) : State < Arc < LibContext > > ,
216+ ) -> Result < Json < indexing_status:: SourceRowIndexingStatus > , ApiError > {
217+ let flow_ctx = lib_context. get_flow_context ( & flow_name) ?;
218+ let source_row_key_ctx = SourceRowKeyContextHolder :: create ( & flow_ctx, query) . await ?;
219+ let index_status = indexing_status:: get_source_row_indexing_status (
220+ & source_row_key_ctx. as_context ( ) ,
221+ & lib_context. builtin_db_pool ,
222+ )
223+ . await ?;
224+ Ok ( Json ( index_status) )
225+ }
0 commit comments