@@ -28,48 +28,36 @@ async function writeTaskOutput(path, message) {
2828 }
2929}
3030
31- async function start ( ) {
32- const { IEXEC_OUT , IEXEC_APP_DEVELOPER_SECRET , IEXEC_REQUESTER_SECRET_1 } =
33- process . env ;
34-
35- const workerEnv = validateWorkerEnv ( { IEXEC_OUT } ) ;
36-
37- // Parse and validate app secrets
38- let appDeveloperSecret ;
39- try {
40- appDeveloperSecret = JSON . parse ( IEXEC_APP_DEVELOPER_SECRET ) ;
41- appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS =
42- appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS
43- ? JSON . parse ( appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS )
44- : undefined ;
45- } catch ( e ) {
46- throw new Error ( 'Failed to parse the developer secret' ) ;
31+ async function processProtectedData (
32+ index ,
33+ {
34+ IEXEC_IN ,
35+ IEXEC_OUT ,
36+ appDeveloperSecret,
37+ requesterSecret,
38+ datasetFilename = null ,
4739 }
48- appDeveloperSecret = validateAppSecret ( appDeveloperSecret ) ;
49-
50- // Parse and validate requester secrets
51- let requesterSecret ;
40+ ) {
41+ // Parse the protected data
42+ let protectedData ;
5243 try {
53- requesterSecret = IEXEC_REQUESTER_SECRET_1
54- ? JSON . parse ( IEXEC_REQUESTER_SECRET_1 )
44+ const deserializerConfig = datasetFilename
45+ ? { protectedDataPath : ` ${ IEXEC_IN } / ${ datasetFilename } ` }
5546 : { } ;
56- } catch {
57- throw new Error ( 'Failed to parse requester secret' ) ;
58- }
59- requesterSecret = validateRequesterSecret ( requesterSecret ) ;
6047
61- // Decrypt protected email
62- let protectedData ;
63- try {
64- const deserializer = new IExecDataProtectorDeserializer ( ) ;
48+ const deserializer = new IExecDataProtectorDeserializer ( deserializerConfig ) ;
6549 protectedData = {
6650 email : await deserializer . getValue ( 'email' , 'string' ) ,
6751 } ;
6852 } catch ( e ) {
69- throw Error ( `Failed to parse ProtectedData: ${ e . message } ` ) ;
53+ const errorMessage =
54+ index === 0
55+ ? `Failed to parse ProtectedData: ${ e . message } `
56+ : `Failed to parse ProtectedData ${ index } : ${ e . message } ` ;
57+ throw Error ( errorMessage ) ;
7058 }
7159
72- // Validate format
60+ // Validate the protected data
7361 validateProtectedData ( protectedData ) ;
7462
7563 // Step 1: Check if email was already validated
@@ -122,24 +110,142 @@ async function start() {
122110 senderName : requesterSecret . senderName ,
123111 } ) ;
124112
125- // Step 5: Encode result as ABI-style bool
126- const bool32Bytes = Buffer . alloc ( 32 ) ;
127- if ( isEmailValidated ) {
128- bool32Bytes [ 31 ] = 1 ; // set last byte to 1 for true
113+ if ( index === 0 ) {
114+ await writeTaskOutput (
115+ `${ IEXEC_OUT } /result.txt` ,
116+ JSON . stringify ( response , null , 2 )
117+ ) ;
118+ }
119+
120+ return { index, response, isEmailValidated } ;
121+ }
122+
123+ async function start ( ) {
124+ const {
125+ IEXEC_IN ,
126+ IEXEC_OUT ,
127+ IEXEC_APP_DEVELOPER_SECRET ,
128+ IEXEC_REQUESTER_SECRET_1 ,
129+ IEXEC_BULK_SLICE_SIZE ,
130+ } = process . env ;
131+
132+ // Check worker env
133+ const workerEnv = validateWorkerEnv ( { IEXEC_OUT } ) ;
134+
135+ // Parse the app developer secret environment variable
136+ let appDeveloperSecret ;
137+ try {
138+ appDeveloperSecret = JSON . parse ( IEXEC_APP_DEVELOPER_SECRET ) ;
139+ appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS =
140+ appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS
141+ ? JSON . parse ( appDeveloperSecret . WEB3MAIL_WHITELISTED_APPS )
142+ : undefined ;
143+ } catch {
144+ throw Error ( 'Failed to parse the developer secret' ) ;
145+ }
146+ appDeveloperSecret = validateAppSecret ( appDeveloperSecret ) ;
147+
148+ // Parse the requester secret environment variable
149+ let requesterSecret ;
150+ try {
151+ requesterSecret = IEXEC_REQUESTER_SECRET_1
152+ ? JSON . parse ( IEXEC_REQUESTER_SECRET_1 )
153+ : { } ;
154+ } catch {
155+ throw Error ( 'Failed to parse requester secret' ) ;
156+ }
157+ requesterSecret = validateRequesterSecret ( requesterSecret ) ;
158+
159+ const bulkSize = parseInt ( IEXEC_BULK_SLICE_SIZE , 10 ) || 0 ;
160+ const results = [ ] ;
161+
162+ if ( bulkSize > 0 ) {
163+ // Process multiple protected data
164+ const promises = [ ] ;
165+ for ( let i = 1 ; i <= bulkSize ; i += 1 ) {
166+ const datasetFilename = process . env [ `IEXEC_DATASET_${ i } _FILENAME` ] ;
167+
168+ const promise = processProtectedData ( i , {
169+ IEXEC_IN ,
170+ IEXEC_OUT : workerEnv . IEXEC_OUT ,
171+ appDeveloperSecret,
172+ requesterSecret,
173+ datasetFilename,
174+ } )
175+ . then ( ( result ) => result )
176+ . catch ( ( error ) => ( {
177+ index : i ,
178+ resultFileName : datasetFilename
179+ ? `${ datasetFilename } .txt`
180+ : `dataset-${ i } .txt` ,
181+ response : {
182+ status : 500 ,
183+ message : `Failed to process dataset ${ i } : ${ error . message } ` ,
184+ } ,
185+ } ) ) ;
186+
187+ promises . push ( promise ) ;
188+ }
189+
190+ const bulkResults = await Promise . all ( promises ) ;
191+ results . push ( ...bulkResults ) ;
192+ } else {
193+ // Process single protected data
194+ const result = await processProtectedData ( 0 , {
195+ IEXEC_IN ,
196+ IEXEC_OUT : workerEnv . IEXEC_OUT ,
197+ appDeveloperSecret,
198+ requesterSecret,
199+ } ) ;
200+
201+ results . push ( result ) ;
202+ }
203+
204+ // Create result.txt for bulk processing
205+ if ( bulkSize > 0 ) {
206+ const successCount = results . filter (
207+ ( r ) => r . response . status === 200
208+ ) . length ;
209+ const errorCount = results . filter ( ( r ) => r . response . status !== 200 ) . length ;
210+
211+ const bulkResult = {
212+ message : `Bulk processing completed: ${ successCount } successful, ${ errorCount } failed` ,
213+ status : 200 ,
214+ 'total-processed' : results . length ,
215+ 'success-count' : successCount ,
216+ 'error-count' : errorCount ,
217+ 'dataset-results' : results . map ( ( r ) => ( {
218+ index : r . index ,
219+ dataset :
220+ process . env [ `IEXEC_DATASET_${ r . index } _FILENAME` ] ||
221+ `dataset-${ r . index } ` ,
222+ response : r . response ,
223+ } ) ) ,
224+ } ;
225+
226+ await writeTaskOutput (
227+ `${ workerEnv . IEXEC_OUT } /result.txt` ,
228+ JSON . stringify ( bulkResult , null , 2 )
229+ ) ;
230+ }
231+
232+ const computedData = {
233+ 'deterministic-output-path' : `${ workerEnv . IEXEC_OUT } /result.txt` ,
234+ } ;
235+
236+ // Add callback data for single processing if useCallback is enabled
237+ if ( bulkSize === 0 && requesterSecret . useCallback && results [ 0 ] ) {
238+ const bool32Bytes = Buffer . alloc ( 32 ) ;
239+ if ( results [ 0 ] . isEmailValidated ) {
240+ bool32Bytes [ 31 ] = 1 ; // set last byte to 1 for true
241+ }
242+ const callbackData = `0x${ bool32Bytes . toString ( 'hex' ) } ` ;
243+ computedData [ 'callback-data' ] = callbackData ;
129244 }
130- const callbackData = `0x${ bool32Bytes . toString ( 'hex' ) } ` ;
131245
132- // Write outputs
133- await writeTaskOutput (
134- `${ workerEnv . IEXEC_OUT } /result.txt` ,
135- JSON . stringify ( response , null , 2 )
136- ) ;
137246 await writeTaskOutput (
138247 `${ workerEnv . IEXEC_OUT } /computed.json` ,
139- JSON . stringify ( {
140- 'deterministic-output-path' : `${ workerEnv . IEXEC_OUT } /result.txt` ,
141- ...( requesterSecret . useCallback && { 'callback-data' : callbackData } ) ,
142- } )
248+ JSON . stringify ( computedData , null , 2 )
143249 ) ;
144250}
145251
0 commit comments