22 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44
5- import { generateUUIDv4 } from "./utils.js" ;
6-
75// The possible states a dispatcher instance can be in.
86export const enum DispatcherState {
97 // The dispatcher has not been initialized yet.
@@ -29,36 +27,25 @@ const enum Commands {
2927 Stop ,
3028 // The dispatcher should stop executing the queued tasks and clear the queue.
3129 Clear ,
30+ // Exactly like a normal Task, but spawned for tests.
31+ TestTask ,
3232}
3333
3434// A task the dispatcher knows how to execute.
3535type Task = ( ) => Promise < void > ;
3636
3737// An executable command.
3838type Command = {
39- testId ?: string ,
4039 task : Task ,
4140 command : Commands . Task ,
4241} | {
43- command : Exclude < Commands , Commands . Task > ,
42+ resolver : ( value : void | PromiseLike < void > ) => void ,
43+ task : Task ,
44+ command : Commands . TestTask ,
45+ } | {
46+ command : Exclude < Commands , Commands . Task | Commands . TestTask > ,
4447} ;
4548
46- /**
47- * An observer of the commands being executed by the dispatcher.
48- */
49- class DispatcherObserver {
50- constructor ( private cb : ( command : Command ) => void ) { }
51-
52- /**
53- * Updates an observer when the dispatcher finishes executing a command.
54- *
55- * @param command The command that was just executed by the dispatcher.
56- */
57- update ( command : Command ) : void {
58- this . cb ( command ) ;
59- }
60- }
61-
6249/**
6350 * A task dispatcher for async tasks.
6451 *
@@ -74,56 +61,11 @@ class Dispatcher {
7461 // This is `undefined` in case there is no ongoing execution of tasks.
7562 private currentJob ?: Promise < void > ;
7663
77- // Observers that are notified about every executed command in this dispacther.
78- //
79- // This is private, because we only expect `testLaunch` to attach observers as of yet.
80- private observers : DispatcherObserver [ ] ;
81-
8264 constructor ( readonly maxPreInitQueueSize = 100 ) {
83- this . observers = [ ] ;
8465 this . queue = [ ] ;
8566 this . state = DispatcherState . Uninitialized ;
8667 }
8768
88- /**
89- * Attaches an observer that will be notified about state changes on the Dispatcher.
90- *
91- * # Note
92- *
93- * This is a private function because only the `testLaunch` function
94- * is expected to watch the state of the Dispatcher as of yet.
95- *
96- * @param observer The observer to attach.
97- */
98- private attachObserver ( observer : DispatcherObserver ) : void {
99- this . observers . push ( observer ) ;
100- }
101-
102- /**
103- * Un-attaches an observer that will be notified about state changes on the Dispatcher.
104- *
105- * # Note
106- *
107- * This is a private function because only the `testLaunch` function
108- * is expected to watch the state of the Dispatcher as of yet.
109- *
110- * @param observer The observer to attach.
111- */
112- private unattachObserver ( observer : DispatcherObserver ) : void {
113- this . observers = this . observers . filter ( curr => observer !== curr ) ;
114- }
115-
116- /**
117- * Notify any currently attached observer that a new command was executed.
118- *
119- * @param command The command to notify about
120- */
121- private notifyObservers ( command : Command ) : void {
122- for ( const observer of this . observers ) {
123- observer . update ( command ) ;
124- }
125- }
126-
12769 /**
12870 * Gets the oldest command added to the queue.
12971 *
@@ -155,16 +97,25 @@ class Dispatcher {
15597 switch ( nextCommand . command ) {
15698 case ( Commands . Stop ) :
15799 this . state = DispatcherState . Stopped ;
158- this . notifyObservers ( nextCommand ) ;
159100 return ;
160101 case ( Commands . Clear ) :
102+ // Unblock test resolvers before clearing the queue.
103+ this . queue . forEach ( c => {
104+ if ( c . command === Commands . TestTask ) {
105+ c . resolver ( ) ;
106+ }
107+ } ) ;
108+
161109 this . queue = [ ] ;
162110 this . state = DispatcherState . Stopped ;
163- this . notifyObservers ( nextCommand ) ;
164111 return ;
112+ case ( Commands . TestTask ) :
113+ await this . executeTask ( nextCommand . task ) ;
114+ nextCommand . resolver ( ) ;
115+ nextCommand = this . getNextCommand ( ) ;
116+ continue ;
165117 case ( Commands . Task ) :
166118 await this . executeTask ( nextCommand . task ) ;
167- this . notifyObservers ( nextCommand ) ;
168119 nextCommand = this . getNextCommand ( ) ;
169120 }
170121 }
@@ -368,55 +319,19 @@ class Dispatcher {
368319 *
369320 * @returns A promise which only resolves once the task is done being executed
370321 * or is guaranteed to not be executed ever i.e. if the queue gets cleared.
371- * This promise is rejected if the dispatcher takes more than 1s
372- * to execute the current task i.e. if the dispatcher is uninitialized.
373322 */
374323 testLaunch ( task : Task ) : Promise < void > {
375- const testId = generateUUIDv4 ( ) ;
376- console . info ( "Launching a test task." , testId ) ;
377-
378- this . resume ( ) ;
379- const wasLaunched = this . launchInternal ( {
380- testId,
381- task,
382- command : Commands . Task
383- } ) ;
384-
385- if ( ! wasLaunched ) {
386- return Promise . reject ( ) ;
387- }
388-
389- // This promise will resolve:
390- //
391- // - If the dispatcher gets a Clear command;
392- // - If a task with `testId` is executed;
393- //
394- // This promise will reject if:
395- //
396- // - If we wait for this task to be execute for more than 1s.
397- // This is to attend to the case where the dispatcher is Stopped
398- // and the task takes to long to be executed.
399- return new Promise ( ( resolve , reject ) => {
400- const observer = new DispatcherObserver ( ( command : Command ) => {
401- const isCurrentTask = ( command . command === Commands . Task && command . testId === testId ) ;
402- if ( isCurrentTask || command . command === Commands . Clear ) {
403- this . unattachObserver ( observer ) ;
404- clearTimeout ( timeout ) ;
405- resolve ( ) ;
406- }
324+ return new Promise ( ( resolver , reject ) => {
325+ this . resume ( ) ;
326+ const wasLaunched = this . launchInternal ( {
327+ resolver,
328+ task,
329+ command : Commands . TestTask
407330 } ) ;
408331
409- const timeout = setTimeout ( ( ) => {
410- console . error (
411- `Test task ${ testId } took to long to execute.` ,
412- "Please check if the dispatcher was initialized and is not stopped." ,
413- "Bailing out."
414- ) ;
415- this . unattachObserver ( observer ) ;
332+ if ( ! wasLaunched ) {
416333 reject ( ) ;
417- } , 1000 ) ;
418-
419- this . attachObserver ( observer ) ;
334+ }
420335 } ) ;
421336 }
422337}
0 commit comments