@@ -8,7 +8,13 @@ import * as http from "http";
88import * as logger from "../logger" ;
99import * as track from "../track" ;
1010import { Constants } from "./constants" ;
11- import { EmulatorInfo , EmulatorInstance , EmulatorLog , Emulators } from "./types" ;
11+ import {
12+ EmulatorInfo ,
13+ EmulatorInstance ,
14+ EmulatorLog ,
15+ Emulators ,
16+ FunctionsExecutionMode ,
17+ } from "./types" ;
1218import * as chokidar from "chokidar" ;
1319
1420import * as spawn from "cross-spawn" ;
@@ -29,6 +35,7 @@ import { EmulatorLogger, Verbosity } from "./emulatorLogger";
2935import { RuntimeWorkerPool , RuntimeWorker } from "./functionsRuntimeWorker" ;
3036import { PubsubEmulator } from "./pubsubEmulator" ;
3137import { FirebaseError } from "../error" ;
38+ import { WorkQueue } from "./workQueue" ;
3239
3340const EVENT_INVOKE = "functions:invoke" ;
3441
@@ -47,6 +54,7 @@ export interface FunctionsEmulatorArgs {
4754 host ?: string ;
4855 quiet ?: boolean ;
4956 disabledRuntimeFeatures ?: FunctionsRuntimeFeatures ;
57+ debugPort ?: number ;
5058}
5159
5260// FunctionsRuntimeInstance is the handler for a running function invocation
@@ -99,14 +107,26 @@ export class FunctionsEmulator implements EmulatorInstance {
99107 private server ?: http . Server ;
100108 private triggers : EmulatedTriggerDefinition [ ] = [ ] ;
101109 private knownTriggerIDs : { [ triggerId : string ] : boolean } = { } ;
102- private workerPool : RuntimeWorkerPool = new RuntimeWorkerPool ( ) ;
110+
111+ private workerPool : RuntimeWorkerPool ;
112+ private workQueue : WorkQueue ;
103113
104114 constructor ( private args : FunctionsEmulatorArgs ) {
105115 // TODO: Would prefer not to have static state but here we are!
106116 EmulatorLogger . verbosity = this . args . quiet ? Verbosity . QUIET : Verbosity . DEBUG ;
117+
118+ const mode = this . args . debugPort
119+ ? FunctionsExecutionMode . SEQUENTIAL
120+ : FunctionsExecutionMode . AUTO ;
121+ this . workerPool = new RuntimeWorkerPool ( mode ) ;
122+ this . workQueue = new WorkQueue ( mode ) ;
107123 }
108124
109125 createHubServer ( ) : express . Application {
126+ // TODO(samstern): Should not need this here but some tests are directly calling this method
127+ // because FunctionsEmulator.start() is not test-safe due to askInstallNodeVersion.
128+ this . workQueue . start ( ) ;
129+
110130 const hub = express ( ) ;
111131
112132 hub . use ( ( req , res , next ) => {
@@ -140,14 +160,18 @@ export class FunctionsEmulator implements EmulatorInstance {
140160 req : express . Request ,
141161 res : express . Response
142162 ) => {
143- this . handleBackgroundTrigger ( req , res ) ;
163+ this . workQueue . submit ( ( ) => {
164+ return this . handleBackgroundTrigger ( req , res ) ;
165+ } ) ;
144166 } ;
145167
146168 const httpsHandler : express . RequestHandler = async (
147169 req : express . Request ,
148170 res : express . Response
149171 ) => {
150- this . handleHttpsTrigger ( req , res ) ;
172+ this . workQueue . submit ( ( ) => {
173+ return this . handleHttpsTrigger ( req , res ) ;
174+ } ) ;
151175 } ;
152176
153177 // The ordering here is important. The longer routes (background)
@@ -185,6 +209,7 @@ export class FunctionsEmulator implements EmulatorInstance {
185209 async start ( ) : Promise < void > {
186210 this . nodeBinary = await this . askInstallNodeVersion ( this . args . functionsDir ) ;
187211 const { host, port } = this . getInfo ( ) ;
212+ this . workQueue . start ( ) ;
188213 this . server = this . createHubServer ( ) . listen ( port , host ) ;
189214 }
190215
@@ -315,6 +340,7 @@ export class FunctionsEmulator implements EmulatorInstance {
315340 }
316341
317342 async stop ( ) : Promise < void > {
343+ this . workQueue . stop ( ) ;
318344 this . workerPool . exit ( ) ;
319345 Promise . resolve ( this . server && this . server . close ( ) ) ;
320346 }
@@ -566,6 +592,10 @@ export class FunctionsEmulator implements EmulatorInstance {
566592 args . unshift ( "--no-warnings" ) ;
567593 }
568594
595+ if ( this . args . debugPort ) {
596+ args . unshift ( `--inspect=${ this . args . debugPort } ` ) ;
597+ }
598+
569599 const childProcess = spawn ( opts . nodeBinary , args , {
570600 env : { node : opts . nodeBinary , ...opts . env , ...process . env } ,
571601 cwd : frb . cwd ,
0 commit comments