UNPKG

@backstage/plugin-catalog-backend

Version:

The Backstage backend plugin that provides the Backstage catalog

93 lines (89 loc) 2.83 kB
'use strict'; var opentelemetry = require('../util/opentelemetry.cjs.js'); var api = require('@opentelemetry/api'); const DEFAULT_POLLING_INTERVAL_MS = 1e3; const tracer = api.trace.getTracer(opentelemetry.TRACER_ID); function startTaskPipeline(options) { const { loadTasks, processTask, lowWatermark, highWatermark, pollingIntervalMs = DEFAULT_POLLING_INTERVAL_MS } = options; if (lowWatermark >= highWatermark) { throw new Error("lowWatermark must be lower than highWatermark"); } const state = { inFlightCount: 0 }; const abortController = new AbortController(); const abortSignal = abortController.signal; const barrier = createBarrier({ waitTimeoutMillis: pollingIntervalMs, signal: abortSignal }); async function pipelineLoop() { while (!abortSignal.aborted) { if (state.inFlightCount <= lowWatermark) { await opentelemetry.withActiveSpan(tracer, "TaskPipelineLoop", async (span) => { const loadCount = highWatermark - state.inFlightCount; const loadedItems = await Promise.resolve().then(() => loadTasks(loadCount)).catch(() => { return []; }); span.setAttribute("itemCount", loadedItems.length); if (loadedItems.length && !abortSignal.aborted) { state.inFlightCount += loadedItems.length; for (const item of loadedItems) { Promise.resolve().then(() => processTask(item)).catch(() => { }).finally(() => { state.inFlightCount -= 1; barrier.release(); }); } } }); } await barrier.wait(); } } pipelineLoop().catch((error) => { throw new Error(`Unexpected error in processing pipeline loop`, error); }); return () => { abortController.abort(); barrier.destroy(); }; } function createBarrier(options) { const { waitTimeoutMillis, signal } = options; const resolvers = /* @__PURE__ */ new Set(); function wait() { if (signal.aborted || !(waitTimeoutMillis > 0)) { return Promise.resolve(); } return new Promise((resolve) => { const timeoutHandle = setTimeout(done, waitTimeoutMillis); function done() { resolvers.delete(done); clearTimeout(timeoutHandle); resolve(); } resolvers.add(done); }); } function release() { const resolversToCall = new Set(resolvers); resolvers.clear(); for (const resolver of resolversToCall) { resolver(); } } signal.addEventListener("abort", release); return { wait, release, destroy: () => signal.removeEventListener("abort", release) }; } exports.createBarrier = createBarrier; exports.startTaskPipeline = startTaskPipeline; //# sourceMappingURL=TaskPipeline.cjs.js.map