@@ -3,11 +3,12 @@ import { performance } from 'node:perf_hooks';
33import { AsyncResource } from 'node:async_hooks' ;
44
55import type { WorkerInfo } from '../worker_pool' ;
6- import type { AbortSignalAny , AbortSignalEventEmitter } from '../abort' ;
6+ import type { Task , TaskQueue , PiscinaTask } from './common' ;
7+
8+ import { onabort , type AbortSignalAny } from '../abort' ;
79import { isMovable } from '../common' ;
810import { kTransferable , kValue , kQueueOptions } from '../symbols' ;
911
10- import type { Task , TaskQueue , PiscinaTask } from './common' ;
1112
1213export { ArrayTaskQueue } from './array_queue' ;
1314export { FixedQueue } from './fixed_queue' ;
@@ -23,6 +24,15 @@ export type TransferList = MessagePort extends {
2324 : never
2425export type TransferListItem = TransferList extends Array < infer T > ? T : never
2526
27+ type TaskInfoParameters = {
28+ task : any ;
29+ transferList : TransferList ;
30+ filename : string ;
31+ name : string ;
32+ abortSignal : AbortSignalAny | null ;
33+ triggerAsyncId : number ;
34+ }
35+
2636/**
2737 * Verifies if a given TaskQueue is valid
2838 *
@@ -41,32 +51,43 @@ export function isTaskQueue (value: TaskQueue): boolean {
4151 ) ;
4252}
4353
44- let taskIdCounter = 0 ;
54+
55+ function taskIdFactory ( ) {
56+ let taskIdCounter = 0 ;
57+ const maxint = 2147483647 ;
58+ return ( ) => {
59+ taskIdCounter = ( taskIdCounter + 1 ) & maxint ;
60+ return taskIdCounter . toString ( 36 ) ;
61+ }
62+ }
63+
4564// Extend AsyncResource so that async relations between posting a task and
4665// receiving its result are visible to diagnostic tools.
4766export class TaskInfo extends AsyncResource implements Task {
67+ static getTaskId : ( ) => string = taskIdFactory ( ) ;
4868 callback : TaskCallback ;
4969 task : any ;
5070 transferList : TransferList ;
5171 filename : string ;
5272 name : string ;
53- taskId : number ;
73+ taskId : string ;
5474 abortSignal : AbortSignalAny | null ;
55- // abortListener : (() => void) | null = null;
5675 workerInfo : WorkerInfo | null = null ;
5776 created : number ;
5877 started : number ;
5978 aborted = false ;
60- _abortListener : ( ( ) => void ) | null = null ;
61-
62- constructor (
63- task : any ,
64- transferList : TransferList ,
65- filename : string ,
66- name : string ,
67- callback : TaskCallback ,
68- abortSignal : AbortSignalAny | null ,
69- triggerAsyncId : number ) {
79+ _abortListener : ( ( ) => void ) = ( ) => { this . aborted = true ; } ;
80+ _abortCleaner : ( ( ) => void ) | null = null ;
81+
82+ constructor ( {
83+ task,
84+ transferList,
85+ filename,
86+ name,
87+ abortSignal,
88+ triggerAsyncId,
89+ } : TaskInfoParameters ,
90+ callback : TaskCallback ) {
7091 super ( 'Piscina.Task' , { requireManualDestroy : true , triggerAsyncId } ) ;
7192 this . callback = callback ;
7293 this . task = task ;
@@ -78,34 +99,31 @@ export class TaskInfo extends AsyncResource implements Task {
7899 if ( isMovable ( task ) ) {
79100 // This condition should never be hit but typescript
80101 // complains if we dont do the check.
81- /* istanbul ignore if */
102+ /* c8 ignore next */
82103 if ( this . transferList == null ) {
83104 this . transferList = [ ] ;
84105 }
85- this . transferList =
86- this . transferList . concat ( task [ kTransferable ] ) ;
106+ this . transferList = this . transferList . concat ( task [ kTransferable ] ) ;
87107 this . task = task [ kValue ] ;
88108 }
89109
90110 this . filename = filename ;
91111 this . name = name ;
92- // TODO: This should not be global
93- this . taskId = taskIdCounter ++ ;
112+ this . taskId = TaskInfo . getTaskId ( ) ;
94113 this . abortSignal = abortSignal ;
95114 this . created = performance . now ( ) ;
96115 this . started = 0 ;
97116 }
98117
99- // TODO: improve this handling - ideally should be extended
100- set abortListener ( value : ( ( ) => void ) ) {
118+ onAbort ( value : ( ( ) => void ) ) {
101119 this . _abortListener = ( ) => {
102120 this . aborted = true ;
103121 value ( ) ;
104122 } ;
105123 }
106124
107- get abortListener ( ) : ( ( ) => void ) | null {
108- return this . _abortListener ;
125+ setAbortListener ( signal : AbortSignalAny ) : void {
126+ this . _abortCleaner = onabort ( signal , this . _abortListener ) ;
109127 }
110128
111129 releaseTask ( ) : any {
@@ -114,19 +132,15 @@ export class TaskInfo extends AsyncResource implements Task {
114132 return ret ;
115133 }
116134
135+ // TODO: implement - helpful for streaming chunks of data from worker to parent
136+ onResponse ( _result : any ) { }
137+
117138 done ( err : Error | null , result ? : any ) : void {
118139 this . runInAsyncScope ( this . callback , null , err , result ) ;
119140 this . emitDestroy ( ) ; // `TaskInfo`s are used only once.
120141 // If an abort signal was used, remove the listener from it when
121142 // done to make sure we do not accidentally leak.
122- if ( this . abortSignal && this . abortListener ) {
123- if ( 'removeEventListener' in this . abortSignal && this . abortListener ) {
124- this . abortSignal . removeEventListener ( 'abort' , this . abortListener ) ;
125- } else {
126- ( this . abortSignal as AbortSignalEventEmitter ) . off (
127- 'abort' , this . abortListener ) ;
128- }
129- }
143+ this . _abortCleaner ?.( ) ;
130144 }
131145
132146 get [ kQueueOptions ] ( ) : { } | null {
0 commit comments