@azure/core-lro
Version:
Isomorphic client library for supporting long-running operations in node.js and browser.
187 lines • 8.14 kB
JavaScript
;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildCreatePoller = buildCreatePoller;
const operation_js_1 = require("./operation.js");
const constants_js_1 = require("./constants.js");
const core_util_1 = require("@azure/core-util");
/**
* Returns a poller factory.
*/
function buildCreatePoller(inputs) {
const { getOperationLocation, getStatusFromInitialResponse, getStatusFromPollResponse, isOperationError, getResourceLocation, getPollingInterval, getError, resolveOnUnsuccessful, } = inputs;
return ({ init, poll }, options) => {
const { processResult, updateState, withOperationLocation: withOperationLocationCallback, intervalInMs = constants_js_1.POLL_INTERVAL_IN_MS, restoreFrom, } = options || {};
const withOperationLocation = withOperationLocationCallback
? (() => {
let called = false;
return (operationLocation, isUpdated) => {
if (isUpdated)
withOperationLocationCallback(operationLocation);
else if (!called)
withOperationLocationCallback(operationLocation);
called = true;
};
})()
: undefined;
let statePromise;
let state;
if (restoreFrom) {
state = (0, operation_js_1.deserializeState)(restoreFrom);
statePromise = Promise.resolve(state);
}
else {
statePromise = (0, operation_js_1.initOperation)({
init,
processResult,
getOperationStatus: getStatusFromInitialResponse,
withOperationLocation,
setErrorAsResult: !resolveOnUnsuccessful,
}).then((s) => (state = s));
}
let resultPromise;
const abortController = new AbortController();
const handlers = new Map();
const handleProgressEvents = async () => handlers.forEach((h) => h(state));
const cancelErrMsg = "Operation was canceled";
let currentPollIntervalInMs = intervalInMs;
const poller = {
get operationState() {
return state;
},
get result() {
return state === null || state === void 0 ? void 0 : state.result;
},
get isDone() {
var _a;
return ["succeeded", "failed", "canceled"].includes((_a = state === null || state === void 0 ? void 0 : state.status) !== null && _a !== void 0 ? _a : "");
},
onProgress: (callback) => {
const s = Symbol();
handlers.set(s, callback);
return () => handlers.delete(s);
},
serialize: async () => {
await statePromise;
return JSON.stringify({
state,
});
},
submitted: async () => {
await statePromise;
},
pollUntilDone: async (pollOptions) => {
resultPromise !== null && resultPromise !== void 0 ? resultPromise : (resultPromise = (async () => {
await statePromise;
if (!state) {
throw new Error("Poller should be initialized but it is not!");
}
const { abortSignal: inputAbortSignal } = pollOptions || {};
// In the future we can use AbortSignal.any() instead
function abortListener() {
abortController.abort();
}
const abortSignal = abortController.signal;
if (inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.aborted) {
abortController.abort();
}
else if (!abortSignal.aborted) {
inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.addEventListener("abort", abortListener, { once: true });
}
try {
if (!poller.isDone) {
await poller.poll({ abortSignal });
while (!poller.isDone) {
await (0, core_util_1.delay)(currentPollIntervalInMs, { abortSignal });
await poller.poll({ abortSignal });
}
}
}
finally {
inputAbortSignal === null || inputAbortSignal === void 0 ? void 0 : inputAbortSignal.removeEventListener("abort", abortListener);
}
if (resolveOnUnsuccessful) {
return poller.result;
}
else {
switch (state.status) {
case "succeeded":
return poller.result;
case "canceled":
throw new Error(cancelErrMsg);
case "failed":
throw state.error;
case "notStarted":
case "running":
throw new Error(`Polling completed without succeeding or failing`);
}
}
})().finally(() => {
resultPromise = undefined;
}));
return resultPromise;
},
async poll(pollOptions) {
await statePromise;
if (!state) {
throw new Error("Poller should be initialized but it is not!");
}
if (resolveOnUnsuccessful) {
if (poller.isDone)
return state;
}
else {
switch (state.status) {
case "succeeded":
return state;
case "canceled":
throw new Error(cancelErrMsg);
case "failed":
throw state.error;
}
}
await (0, operation_js_1.pollOperation)({
poll,
state,
getOperationLocation,
isOperationError,
withOperationLocation,
getPollingInterval,
getOperationStatus: getStatusFromPollResponse,
getResourceLocation,
processResult,
getError,
updateState,
options: pollOptions,
setDelay: (pollIntervalInMs) => {
currentPollIntervalInMs = pollIntervalInMs;
},
setErrorAsResult: !resolveOnUnsuccessful,
});
await handleProgressEvents();
if (!resolveOnUnsuccessful) {
switch (state.status) {
case "canceled":
throw new Error(cancelErrMsg);
case "failed":
throw state.error;
}
}
return state;
},
then(onfulfilled, onrejected) {
return poller.pollUntilDone().then(onfulfilled, onrejected);
},
catch(onrejected) {
return poller.pollUntilDone().catch(onrejected);
},
finally(onfinally) {
return poller.pollUntilDone().finally(onfinally);
},
[Symbol.toStringTag]: "Poller",
};
return poller;
};
}
//# sourceMappingURL=poller.js.map