@salesforce/core
Version:
Core libraries to interact with SFDX projects, orgs, and APIs.
142 lines • 5.24 kB
JavaScript
"use strict";
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PollingClient = void 0;
const timers_1 = require("timers");
const kit_1 = require("@salesforce/kit");
const ts_types_1 = require("@salesforce/ts-types");
const logger_1 = require("../logger");
const sfdxError_1 = require("../sfdxError");
/**
* This is a polling client that can be used to poll the status of long running tasks. It can be used as a replacement
* for Streaming when streaming topics are not available or when streaming handshakes are failing. Why wouldn't you
* want to use this? It can impact Salesforce API usage.
*
* ```
* const options: PollingClient.Options = {
* async poll(): Promise<StatusResult> {
* return Promise.resolve({ completed: true, payload: 'Hello World' });
* },
* frequency: Duration.milliseconds(10),
* timeout: Duration.minutes(1)
* };
* const client = await PollingClient.create(options);
* const pollResult = await client.subscribe();
* console.log(`pollResult: ${pollResult}`);
* ```
*/
class PollingClient extends kit_1.AsyncOptionalCreatable {
/**
* Constructor
*
* @param options Polling client options
* @ignore
*/
constructor(options) {
super(options);
this.options = ts_types_1.ensure(options);
}
/**
* Asynchronous initializer.
*/
async init() {
this.logger = await logger_1.Logger.child(this.constructor.name);
}
/**
* Returns a promise to call the specified polling function using the interval and timeout specified
* in the polling options.
*/
subscribe() {
// This promise is held open while setInterval tries to resolve or reject.
// If set interval can't do it then the timeout will reject.
return new Promise((resolve, reject) => {
// Use set interval to periodically call the polling function
// This try catch enables support for time{0} since setInterval only supports
// time {1}. In other words, we should call first then wait for the first interval.
this.doPoll()
.then((result) => {
if (result && result.completed) {
resolve(result.payload);
}
else {
this.interval = timers_1.setInterval(
// eslint-disable-next-line @typescript-eslint/no-misused-promises
PollingClient.prototype.doPoll.bind(this, resolve, reject), this.options.frequency.milliseconds);
}
})
.catch(() => {
this.interval = timers_1.setInterval(
// eslint-disable-next-line @typescript-eslint/no-misused-promises
PollingClient.prototype.doPoll.bind(this, resolve, reject), this.options.frequency.milliseconds);
});
// hard polling timeout.
this.timeout = setTimeout(() => {
this.logger.debug('Polling timed out');
this.clearAll();
// @todo should go in messages.
reject(new sfdxError_1.SfdxError('The client has timed out.', this.options.timeoutErrorName || 'PollingClientTimeout'));
}, this.options.timeout.milliseconds);
});
}
async doPoll(resolve, reject) {
try {
// Poll can be an async function.
const sample = await this.options.poll();
if (sample.completed) {
this.clearAll();
if (resolve) {
resolve(sample.payload);
}
else {
return sample;
}
}
}
catch (e) {
this.clearAll();
if (reject) {
reject(e);
}
else {
throw e;
}
}
}
clearAll() {
if (this.interval) {
this.logger.debug('Clearing the polling interval');
clearInterval(this.interval);
}
if (this.timeout) {
this.logger.debug('Clearing the timeout interval');
clearTimeout(this.timeout);
}
}
}
exports.PollingClient = PollingClient;
(function (PollingClient) {
/**
* Default options set for polling. The default options specify a timeout of 3 minutes and polling frequency of 15
* seconds;
*/
class DefaultPollingOptions {
/**
* constructor
*
* @param poll The function used for polling status.
* {@link StatusResult}
*/
constructor(poll) {
this.poll = poll;
this.timeout = kit_1.Duration.minutes(3);
this.frequency = kit_1.Duration.seconds(15);
}
}
PollingClient.DefaultPollingOptions = DefaultPollingOptions;
})(PollingClient = exports.PollingClient || (exports.PollingClient = {}));
//# sourceMappingURL=pollingClient.js.map