123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.WorkQueue = void 0;
- const utils = require("../utils");
- const error_1 = require("../error");
- const emulatorLogger_1 = require("./emulatorLogger");
- const types_1 = require("./types");
- class WorkQueue {
- constructor(mode = types_1.FunctionsExecutionMode.AUTO, maxParallelWork = WorkQueue.DEFAULT_MAX_PARALLEL) {
- this.mode = mode;
- this.maxParallelWork = maxParallelWork;
- this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
- this.queue = [];
- this.running = [];
- this.notifyQueue = () => {
- };
- this.notifyWorkFinish = () => {
- };
- this.stopped = true;
- if (maxParallelWork < 1) {
- throw new error_1.FirebaseError(`Cannot run Functions emulator with less than 1 parallel worker (${WorkQueue.MAX_PARALLEL_ENV}=${process.env[WorkQueue.MAX_PARALLEL_ENV]})`);
- }
- }
- submit(entry) {
- this.queue.push(entry);
- this.notifyQueue();
- this.logState();
- }
- async start() {
- if (!this.stopped) {
- return;
- }
- this.stopped = false;
- while (!this.stopped) {
- if (!this.queue.length) {
- await new Promise((res) => {
- this.notifyQueue = res;
- });
- }
- if (this.running.length >= this.maxParallelWork) {
- this.logger.logLabeled("DEBUG", "work-queue", `waiting for work to finish (running=${this.running})`);
- await new Promise((res) => {
- this.notifyWorkFinish = res;
- });
- }
- const workPromise = this.runNext();
- if (this.mode === types_1.FunctionsExecutionMode.SEQUENTIAL) {
- await workPromise;
- }
- }
- }
- stop() {
- this.stopped = true;
- }
- async flush(timeoutMs = 60000) {
- if (!this.isWorking()) {
- return;
- }
- this.logger.logLabeled("BULLET", "functions", "Waiting for all functions to finish...");
- return new Promise((res, rej) => {
- const delta = 100;
- let elapsed = 0;
- const interval = setInterval(() => {
- elapsed += delta;
- if (elapsed >= timeoutMs) {
- rej(new Error(`Functions work queue not empty after ${timeoutMs}ms`));
- }
- if (!this.isWorking()) {
- clearInterval(interval);
- res();
- }
- }, delta);
- });
- }
- getState() {
- return {
- queuedWork: this.queue.map((work) => work.type),
- queueLength: this.queue.length,
- runningWork: this.running,
- workRunningCount: this.running.length,
- };
- }
- isWorking() {
- const state = this.getState();
- return state.queueLength > 0 || state.workRunningCount > 0;
- }
- async runNext() {
- const next = this.queue.shift();
- if (next) {
- this.running.push(next.type || "anonymous");
- this.logState();
- try {
- await next();
- }
- catch (e) {
- this.logger.log("DEBUG", e);
- }
- finally {
- const index = this.running.indexOf(next.type || "anonymous");
- if (index !== -1) {
- this.running.splice(index, 1);
- }
- this.notifyWorkFinish();
- this.logState();
- }
- }
- }
- logState() {
- this.logger.logLabeled("DEBUG", "work-queue", JSON.stringify(this.getState()));
- }
- }
- exports.WorkQueue = WorkQueue;
- WorkQueue.MAX_PARALLEL_ENV = "FUNCTIONS_EMULATOR_PARALLEL";
- WorkQueue.DEFAULT_MAX_PARALLEL = Number.parseInt(utils.envOverride(WorkQueue.MAX_PARALLEL_ENV, "50"));
|