UNPKG

@amplience/dc-cli

Version:
137 lines (136 loc) 5.39 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PublishQueue = exports.delay = exports.DEFAULT_PUBLISH_RATE_LIMIT = exports.MAX_PUBLISH_RATE_LIMIT = void 0; const dc_management_sdk_js_1 = require("dc-management-sdk-js"); const node_fetch_1 = __importDefault(require("node-fetch")); exports.MAX_PUBLISH_RATE_LIMIT = 80; exports.DEFAULT_PUBLISH_RATE_LIMIT = 35; const delay = (duration) => { return new Promise((resolve) => { setTimeout(resolve, duration); }); }; exports.delay = delay; class PublishQueue { constructor(config) { this.maxWaiting = 35; this.maxAttempts = 30; this.attemptDelay = 1000; this.attemptRateLimit = 60000 / 35; this.failedJobs = []; this.unresolvedJobs = []; this.inProgressJobs = []; this.waitingList = []; this.delayUntil = []; this.delayId = 0; this.waitInProgress = false; const http = new dc_management_sdk_js_1.AxiosHttpClient({}); if (config.clientId && config.clientSecret) { this.auth = new dc_management_sdk_js_1.Oauth2AuthHeaderProvider({ client_id: config.clientId, client_secret: config.clientSecret }, { authUrl: process.env.AUTH_URL || 'https://auth.amplience.net' }, http); } else if (config.patToken) { this.auth = new dc_management_sdk_js_1.PatTokenAuthHeaderProvider(config.patToken); } const publishRateLimit = Math.min((config === null || config === void 0 ? void 0 : config.publishRateLimit) || exports.DEFAULT_PUBLISH_RATE_LIMIT, exports.MAX_PUBLISH_RATE_LIMIT); this.attemptRateLimit = 60000 / publishRateLimit; } async fetch(href, method) { return await (0, node_fetch_1.default)(href, { method: method, headers: { Authorization: await this.auth.getAuthHeader() } }); } async publish(item) { await this.rateLimit(); const publishLink = item._links['publish']; if (publishLink == null) { throw new Error('Cannot publish the item - link not available.'); } const publish = await this.fetch(publishLink.href, 'POST'); if (publish.status != 204) { throw new Error(`Failed to start publish: ${publish.statusText} - ${await publish.text()}`); } const publishJobInfoHref = publish.headers.get('Location'); if (publishJobInfoHref == null) { throw new Error('Expected publish job location in header. Has the publish workflow changed?'); } this.inProgressJobs.push({ href: publishJobInfoHref, item }); } async waitForOldestPublish() { if (this.inProgressJobs.length === 0) { return; } this.waitInProgress = true; const oldestJob = this.inProgressJobs[0]; this.inProgressJobs.splice(0, 1); let attempts = 0; for (; attempts < this.maxAttempts; attempts++) { let job; try { job = await (await this.fetch(oldestJob.href, 'GET')).json(); } catch (e) { continue; } if (job.state === 'COMPLETED') { break; } else if (job.state === 'FAILED') { this.failedJobs.push(oldestJob); break; } else { await (0, exports.delay)(this.attemptDelay); } } if (attempts == this.maxAttempts) { this.unresolvedJobs.push(oldestJob); } const oldestWaiter = this.waitingList[0]; if (oldestWaiter != null) { this.waitingList.splice(0, 1); oldestWaiter.resolver(); } if (this.waitingList.length > 0 || this.awaitingAll) { await this.waitForOldestPublish(); } else { this.waitInProgress = false; } } async rateLimit() { const now = Date.now(); if (now < this.delayUntil[this.delayId] || 0) { await (0, exports.delay)(this.delayUntil[this.delayId] - now); } this.delayUntil[this.delayId] = now + this.attemptRateLimit * this.maxWaiting; this.delayId = (this.delayId + 1) % this.maxWaiting; if (this.inProgressJobs.length != this.maxWaiting) { return; } let resolver = () => { }; const myPromise = new Promise((resolve) => { resolver = resolve; }); this.waitingList.push({ promise: myPromise, resolver: resolver }); if (!this.waitInProgress) { this.waitForOldestPublish(); } await myPromise; } async waitForAll() { var _a; if (this.waitInProgress) { await ((_a = this.waitingList[this.waitingList.length - 1]) === null || _a === void 0 ? void 0 : _a.promise); } this.inProgressJobs = [...this.inProgressJobs, ...this.unresolvedJobs]; this.unresolvedJobs = []; this.awaitingAll = true; await this.waitForOldestPublish(); } isEmpty() { return this.inProgressJobs.length === 0 && this.unresolvedJobs.length === 0; } } exports.PublishQueue = PublishQueue;