@@ -2,14 +2,14 @@ use anyhow::anyhow;
22use axum:: {
33 body:: Body ,
44 extract:: { Path , State } ,
5- response:: Response ,
5+ response:: { IntoResponse , NoContent , Response } ,
66} ;
77use futures:: TryStreamExt ;
88
99use super :: routes_state:: RouteState ;
1010use crate :: {
1111 blob_store:: BlobStorage ,
12- data_model:: GraphInvocationError ,
12+ data_model:: { DataPayload , GraphInvocationError } ,
1313 http_objects:: { IndexifyAPIError , RequestError } ,
1414} ;
1515
@@ -120,7 +120,7 @@ pub async fn download_fn_output_payload(
120120 . map_err ( |e| IndexifyAPIError :: internal_error_str ( & e. to_string ( ) ) )
121121}
122122
123- /// Get function output
123+ /// Get function output by index
124124#[ utoipa:: path(
125125 get,
126126 path = "v1/namespaces/{namespace}/compute-graphs/{compute_graph}/requests/{request_id}/fn/{fn_name}/outputs/{id}/index/{index}" ,
@@ -159,14 +159,60 @@ pub async fn v1_download_fn_output_payload(
159159 let encoding = output. encoding . clone ( ) ;
160160
161161 let payload = & output. payloads [ index] ;
162- let storage_reader = state
163- . blob_storage
164- . get_blob_store ( & namespace)
162+ let blob_storage = state. blob_storage . get_blob_store ( & namespace) ;
163+ stream_data_payload ( & payload, & blob_storage, & encoding) . await
164+ }
165+
166+ /// Get function output
167+ #[ utoipa:: path(
168+ get,
169+ path = "v1/namespaces/{namespace}/compute-graphs/{compute_graph}/requests/{request_id}/output/{fn_name}" ,
170+ tag = "retrieve" ,
171+ responses(
172+ ( status = 200 , description = "function output" ) ,
173+ ( status = INTERNAL_SERVER_ERROR , description = "internal server error" )
174+ ) ,
175+ ) ]
176+ pub async fn v1_download_fn_output_payload_simple (
177+ Path ( ( namespace, compute_graph, invocation_id, fn_name) ) : Path < (
178+ String ,
179+ String ,
180+ String ,
181+ String ,
182+ ) > ,
183+ State ( state) : State < RouteState > ,
184+ ) -> Result < Response < Body > , IndexifyAPIError > {
185+ let output = state
186+ . indexify_state
187+ . reader ( )
188+ . fn_output_payload_first ( & namespace, & compute_graph, & invocation_id, & fn_name)
189+ . map_err ( |e| {
190+ IndexifyAPIError :: internal_error ( anyhow ! (
191+ "failed to download invocation payload: {}" ,
192+ e
193+ ) )
194+ } ) ?;
195+ let Some ( output) = output else {
196+ return Ok ( NoContent . into_response ( ) ) ;
197+ } ;
198+
199+ let encoding = output. encoding . clone ( ) ;
200+
201+ let payload = & output. payloads [ 0 ] ;
202+ let blob_storage = state. blob_storage . get_blob_store ( & namespace) ;
203+ stream_data_payload ( & payload, & blob_storage, & encoding) . await
204+ }
205+
206+ async fn stream_data_payload (
207+ payload : & DataPayload ,
208+ blob_storage : & BlobStorage ,
209+ encoding : & str ,
210+ ) -> Result < Response < Body > , IndexifyAPIError > {
211+ let storage_reader = blob_storage
165212 . get ( & payload. path )
166213 . await
167214 . map_err ( IndexifyAPIError :: internal_error) ?;
168215
169- // Check if the content type is JSON
170216 if encoding == "application/json" {
171217 let json_bytes = storage_reader
172218 . map_ok ( |chunk| chunk. to_vec ( ) )
0 commit comments