@@ -25,9 +25,13 @@ import {
2525 OnStatusUpdateFn ,
2626 ProcessBulkRequestParams ,
2727 ProcessBulkRequestResponse ,
28+ ProcessBulkRequestResponseBase ,
29+ ProcessBulkRequestResponseWithResult ,
2830 ProcessBulkRequestStatuses ,
2931} from '../types/index.js' ;
3032import { IExecConsumer , VoucherInfo } from '../types/internalTypes.js' ;
33+ import { getResultFromCompletedTask } from './getResultFromCompletedTask.js' ;
34+ import { waitForTaskCompletion } from './waitForTaskCompletion.js' ;
3135
3236export type ProcessBulkRequest = typeof processBulkRequest ;
3337
@@ -38,18 +42,22 @@ const waitForRetry = (ms: number): Promise<void> => {
3842 } ) ;
3943} ;
4044
41- export const processBulkRequest = async ( {
45+ export const processBulkRequest = async <
46+ Params extends ProcessBulkRequestParams
47+ > ( {
4248 iexec = throwIfMissing ( ) ,
4349 defaultWorkerpool,
4450 bulkRequest,
4551 workerpool,
4652 useVoucher = false ,
4753 voucherOwner,
54+ path,
4855 pemPrivateKey,
56+ waitForResult = false ,
4957 onStatusUpdate = ( ) => { } ,
50- } : IExecConsumer &
51- DefaultWorkerpoolConsumer &
52- ProcessBulkRequestParams ) : Promise < ProcessBulkRequestResponse > => {
58+ } : IExecConsumer & DefaultWorkerpoolConsumer & Params ) : Promise <
59+ ProcessBulkRequestResponse < Params >
60+ > => {
5361 const vRequestorder = bulkRequestSchema ( )
5462 . label ( 'bulkRequest' )
5563 . required ( )
@@ -64,6 +72,10 @@ export const processBulkRequest = async ({
6472 const vVoucherOwner = addressOrEnsSchema ( )
6573 . label ( 'voucherOwner' )
6674 . validateSync ( voucherOwner ) ;
75+ const vWaitForResult = booleanSchema ( )
76+ . label ( 'waitForResult' )
77+ . validateSync ( waitForResult ) ;
78+ const vPath = stringSchema ( ) . label ( 'path' ) . validateSync ( path ) ;
6779 const vPemPrivateKey = stringSchema ( )
6880 . label ( 'pemPrivateKey' )
6981 . validateSync ( pemPrivateKey ) ;
@@ -72,17 +84,22 @@ export const processBulkRequest = async ({
7284 OnStatusUpdateFn < ProcessBulkRequestStatuses >
7385 > ( onStatusUpdate ) ;
7486
75- // Validate that pemPrivateKey is provided if iexec_result_encryption is true
76- if (
87+ const iexecResultEncryption =
7788 // JSON parse safe thanks to bulkRequestSchema validation
78- JSON . parse ( vRequestorder . params ) ?. iexec_result_encryption === true &&
79- ! vPemPrivateKey
80- ) {
89+ JSON . parse ( vRequestorder . params ) ?. iexec_result_encryption === true ;
90+ // Validate that pemPrivateKey is provided if iexec_result_encryption is true
91+ if ( vWaitForResult && iexecResultEncryption && ! vPemPrivateKey ) {
8192 throw new ValidationError (
8293 'Missing pemPrivateKey required for result decryption'
8394 ) ;
8495 }
8596
97+ if ( vWaitForResult && ! iexecResultEncryption && vPemPrivateKey ) {
98+ throw new ValidationError (
99+ 'pemPrivateKey is passed but result encryption is not enabled in bulkRequest this is likely an error when preparing the bulk request'
100+ ) ;
101+ }
102+
86103 try {
87104 let userVoucher : VoucherInfo | undefined ;
88105 if ( vUseVoucher ) {
@@ -241,11 +258,7 @@ export const processBulkRequest = async ({
241258 { pageSize : Math . max ( volume , 10 ) } // Fetch all deals (min page size 10)
242259 ) ;
243260
244- const tasks : Array < {
245- taskId : string ;
246- dealId : string ;
247- bulkIndex : number ;
248- } > = [ ] ;
261+ const tasks : ProcessBulkRequestResponseBase [ 'tasks' ] = [ ] ;
249262
250263 for ( const deal of deals ) {
251264 const dealTasks = await Promise . all (
@@ -259,6 +272,7 @@ export const processBulkRequest = async ({
259272 ) ;
260273 tasks . push ( ...dealTasks ) ;
261274 }
275+ tasks . sort ( ( a , b ) => a . bulkIndex - b . bulkIndex ) ;
262276
263277 vOnStatusUpdate ( {
264278 title : 'MATCH_ORDERS_LOOP' ,
@@ -269,8 +283,74 @@ export const processBulkRequest = async ({
269283 } ,
270284 } ) ;
271285
286+ if ( ! vWaitForResult ) {
287+ return {
288+ tasks,
289+ } as ProcessBulkRequestResponse < Params > ;
290+ }
291+
292+ const tasksWithResults =
293+ tasks as ProcessBulkRequestResponseWithResult [ 'tasks' ] ;
294+
295+ await Promise . all (
296+ tasksWithResults . map ( async ( task ) => {
297+ try {
298+ vOnStatusUpdate ( {
299+ title : 'PROCESS_BULK_SLICE' ,
300+ isDone : false ,
301+ payload : task ,
302+ } ) ;
303+ vOnStatusUpdate ( {
304+ title : 'CONSUME_TASK' ,
305+ isDone : false ,
306+ payload : task ,
307+ } ) ;
308+ const { status, success } = await waitForTaskCompletion ( {
309+ iexec,
310+ taskId : task . taskId ,
311+ dealId : task . dealId ,
312+ } ) ;
313+ task . status = status ;
314+ task . success = success ;
315+ vOnStatusUpdate ( {
316+ title : 'CONSUME_TASK' ,
317+ isDone : true ,
318+ payload : task ,
319+ } ) ;
320+ if ( ! success ) {
321+ throw new Error ( `Task ended with status: ${ status } ` ) ;
322+ }
323+ const { result } = await getResultFromCompletedTask ( {
324+ iexec,
325+ taskId : task . taskId ,
326+ path : vPath ,
327+ pemPrivateKey : vPemPrivateKey ,
328+ onStatusUpdate : ( update ) => {
329+ vOnStatusUpdate ( {
330+ ...update ,
331+ payload : { ...update . payload , task } ,
332+ } ) ;
333+ } ,
334+ } ) ;
335+ task . result = result ;
336+ vOnStatusUpdate ( {
337+ title : 'PROCESS_BULK_SLICE' ,
338+ isDone : true ,
339+ payload : task ,
340+ } ) ;
341+ } catch ( error ) {
342+ task . error = error as Error ;
343+ vOnStatusUpdate ( {
344+ title : 'PROCESS_BULK_SLICE' ,
345+ isDone : true ,
346+ payload : task ,
347+ } ) ;
348+ }
349+ } )
350+ ) ;
351+
272352 return {
273- tasks : tasks . sort ( ( a , b ) => a . bulkIndex - b . bulkIndex ) ,
353+ tasks : tasksWithResults ,
274354 } ;
275355 } catch ( error ) {
276356 console . error ( '[processBulkRequest] ERROR' , error ) ;
0 commit comments