1
- import { dirname , join } from 'path'
2
- import { fileURLToPath } from 'url'
3
1
import { Worker } from 'worker_threads'
4
2
5
3
interface SignatureTask {
@@ -16,54 +14,73 @@ interface SignatureResult {
16
14
17
15
export class SignatureWorkerPool {
18
16
private workers : Worker [ ] = [ ]
19
- private taskQueue : SignatureTask [ ] = [ ]
20
17
private results : Map < number , SignatureResult > = new Map ( )
21
18
private nextTaskId = 0
19
+ private pendingResults = 0
22
20
23
21
constructor ( numWorkers : number = 4 ) {
24
- const __filename = fileURLToPath ( import . meta . url )
25
- const __dirname = dirname ( __filename )
26
- const workerPath = join ( __dirname , 'signatureWorker.ts ')
22
+ const workerCode = `
23
+ const { parentPort } = require('worker_threads' )
24
+ const { ecrecover } = require('@ethereumjs/util ')
27
25
26
+ parentPort.on('message', (data) => {
27
+ const { tasks, taskId } = data
28
+ const results = tasks.map(task => {
29
+ const publicKey = ecrecover(task.msgHash, task.v, task.r, task.s, task.chainId)
30
+ return { publicKey }
31
+ })
32
+ parentPort.postMessage({ results, taskId })
33
+ })
34
+ `
35
+
36
+ // Initialize workers
28
37
for ( let i = 0 ; i < numWorkers ; i ++ ) {
29
- const worker = new Worker ( workerPath , {
30
- // Use tsx to run TypeScript files
31
- execArgv : [ '-r' , 'tsx/register' ] ,
32
- } )
38
+ const worker = new Worker ( workerCode , { eval : true } )
33
39
34
- worker . on ( 'message' , ( results : SignatureResult [ ] ) => {
40
+ worker . on ( 'message' , ( data : { results : SignatureResult [ ] ; taskId : number } ) => {
41
+ const { results, taskId } = data
35
42
results . forEach ( ( result , index ) => {
36
- this . results . set ( this . nextTaskId - results . length + index , result )
43
+ this . results . set ( taskId + index , result )
37
44
} )
45
+ this . pendingResults --
38
46
} )
47
+
39
48
this . workers . push ( worker )
40
49
}
41
50
}
42
51
43
52
async processBatch ( tasks : SignatureTask [ ] ) : Promise < Map < number , SignatureResult > > {
53
+ // Clear previous results
54
+ this . results . clear ( )
55
+ this . nextTaskId = 0
56
+ this . pendingResults = 0
57
+
58
+ // Calculate batch size per worker
44
59
const batchSize = Math . ceil ( tasks . length / this . workers . length )
45
- const promises : Promise < void > [ ] = [ ]
46
60
61
+ // Process tasks in parallel
47
62
for ( let i = 0 ; i < this . workers . length ; i ++ ) {
48
63
const start = i * batchSize
49
64
const end = Math . min ( start + batchSize , tasks . length )
65
+ if ( start >= tasks . length ) break
66
+
50
67
const batch = tasks . slice ( start , end )
68
+ this . pendingResults ++
69
+ this . workers [ i ] . postMessage ( { tasks : batch , taskId : this . nextTaskId } )
70
+ this . nextTaskId += batch . length
71
+ }
51
72
52
- if ( batch . length > 0 ) {
53
- promises . push (
54
- new Promise ( ( resolve ) => {
55
- this . workers [ i ] . postMessage ( batch )
56
- resolve ( )
57
- } ) ,
58
- )
59
- }
73
+ // Wait for all results
74
+ while ( this . pendingResults > 0 ) {
75
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) )
60
76
}
61
77
62
- await Promise . all ( promises )
63
78
return this . results
64
79
}
65
80
66
81
terminate ( ) {
67
- this . workers . forEach ( ( worker ) => worker . terminate ( ) )
82
+ for ( const worker of this . workers ) {
83
+ worker . terminate ( )
84
+ }
68
85
}
69
86
}
0 commit comments