rename promise-retry to retry

This commit is contained in:
Girish Ramakrishnan
2026-03-27 11:39:38 +01:00
parent b08e3a5128
commit 9c3c8cc9d1
15 changed files with 45 additions and 45 deletions
+6 -6
View File
@@ -7,7 +7,7 @@ import dns from './dns.js';
import openssl from './openssl.js';
import path from 'node:path';
import paths from './paths.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import superagent from '@cloudron/superagent';
import users from './users.js';
@@ -244,7 +244,7 @@ Acme2.prototype.waitForOrder = async function (orderUrl) {
log(`waitForOrder: ${orderUrl}`);
return await promiseRetry({ times: 15, interval: 20000, log }, async () => {
return await retry({ times: 15, interval: 20000, log }, async () => {
log('waitForOrder: getting status');
const result = await this.postAsGet(orderUrl);
@@ -297,7 +297,7 @@ Acme2.prototype.waitForChallenge = async function (challenge) {
log(`waitingForChallenge: ${JSON.stringify(challenge)}`);
await promiseRetry({ times: 15, interval: 20000, log }, async () => {
await retry({ times: 15, interval: 20000, log }, async () => {
log('waitingForChallenge: getting status');
const result = await this.postAsGet(challenge.url);
@@ -335,7 +335,7 @@ Acme2.prototype.signCertificate = async function (finalizationUrl, csrPem) {
Acme2.prototype.downloadCertificate = async function (certUrl) {
assert.strictEqual(typeof certUrl, 'string');
return await promiseRetry({ times: 5, interval: 20000, log }, async () => {
return await retry({ times: 5, interval: 20000, log }, async () => {
log(`downloadCertificate: downloading certificate of ${this.cn}`);
const result = await this.postAsGet(certUrl);
@@ -485,7 +485,7 @@ Acme2.prototype.acmeFlow = async function () {
};
Acme2.prototype.loadDirectory = async function () {
await promiseRetry({ times: 3, interval: 20000, log }, async () => {
await retry({ times: 3, interval: 20000, log }, async () => {
const response = await superagent.get(this.caDirectory).timeout(30000).ok(() => true);
if (response.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Invalid response code when fetching directory : ${response.status}`);
@@ -522,7 +522,7 @@ async function getCertificate(fqdn, domainObject, key) {
const owner = await users.getOwner();
const email = owner?.email || 'webmaster@cloudron.io'; // can error if not activated yet
return await promiseRetry({ times: 3, interval: 0, log }, async function () {
return await retry({ times: 3, interval: 0, log }, async function () {
log(`getCertificate: for fqdn ${fqdn} and domain ${domainObject.domain}`);
const acme = new Acme2(fqdn, domainObject, email, key, { /* profile: 'shortlived' */ });
+2 -2
View File
@@ -14,7 +14,7 @@ import mail from './mail.js';
import manifestFormat from '@cloudron/manifest-format';
import oidcClients from './oidcclients.js';
import paths from './paths.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import semver from 'semver';
import settings from './settings.js';
@@ -388,7 +388,7 @@ async function getApp(appId) {
async function downloadIcon(appStoreId, version) {
const iconUrl = `${await getApiServerOrigin()}/api/v1/apps/${appStoreId}/versions/${version}/icon`;
return await promiseRetry({ times: 10, interval: 5000, log }, async function () {
return await retry({ times: 10, interval: 5000, log }, async function () {
const [networkError, response] = await safe(superagent.get(iconUrl)
.timeout(60 * 1000)
.ok(() => true));
+2 -2
View File
@@ -21,7 +21,7 @@ import manifestFormat from '@cloudron/manifest-format';
import os from 'node:os';
import path from 'node:path';
import paths from './paths.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import reverseProxy from './reverseproxy.js';
import safe from 'safetydance';
import services from './services.js';
@@ -63,7 +63,7 @@ async function allocateContainerIp(app) {
if (app.manifest.id === constants.PROXY_APP_APPSTORE_ID) return;
await promiseRetry({ times: 10, interval: 0, log }, async function () {
await retry({ times: 10, interval: 0, log }, async function () {
const iprange = iputils.intFromIp(constants.APPS_IPv4_END) - iputils.intFromIp(constants.APPS_IPv4_START);
const rnd = Math.floor(Math.random() * iprange);
const containerIp = iputils.ipFromInt(iputils.intFromIp(constants.APPS_IPv4_START) + rnd);
+3 -3
View File
@@ -12,7 +12,7 @@ import path from 'node:path';
import paths from '../paths.js';
import { pipeline } from 'node:stream/promises';
import ProgressStream from '../progress-stream.js';
import promiseRetry from '../promise-retry.js';
import retry from '../retry.js';
import safe from 'safetydance';
import shellModule from '../shell.js';
import syncer from '../syncer.js';
@@ -193,7 +193,7 @@ async function sync(backupSite, remotePath, dataLayout, progressCallback) {
} else if (change.operation === 'remove') {
await backupSites.storageApi(backupSite).remove(backupSite.config, fullPath);
} else if (change.operation === 'add') {
await promiseRetry({ times: 5, interval: 20000, log }, async (retryCount) => {
await retry({ times: 5, interval: 20000, log }, async (retryCount) => {
reportUploadProgress(`Current: ${change.path}` + (retryCount > 1 ? ` (Try ${retryCount})` : ''));
if (retryCount > 1) log(`sync: retrying ${change.path} position ${change.position} try ${retryCount}`);
const uploader = await backupSites.storageApi(backupSite).upload(backupSite.config, backupSite.limits, fullPath);
@@ -259,7 +259,7 @@ async function downloadDir(backupSite, remotePath, dataLayout, progressCallback)
const [mkdirError] = await safe(fs.promises.mkdir(path.dirname(destFilePath), { recursive: true }));
if (mkdirError) throw new BoxError(BoxError.FS_ERROR, mkdirError.message);
await promiseRetry({ times: 3, interval: 20000 }, async function () {
await retry({ times: 3, interval: 20000 }, async function () {
reportProgress(`Current: ${relativePath}`);
const [downloadError, sourceStream] = await safe(backupSites.storageApi(backupSite).download(backupSite.config, entry.path));
+3 -3
View File
@@ -9,7 +9,7 @@ import fs from 'node:fs';
import HashStream from '../hash-stream.js';
import path from 'node:path';
import ProgressStream from '../progress-stream.js';
import promiseRetry from '../promise-retry.js';
import retry from '../retry.js';
import safe from 'safetydance';
import stream from 'stream/promises';
import { Transform } from 'node:stream';
@@ -253,7 +253,7 @@ async function download(backupSite, remotePath, dataLayout, progressCallback) {
log(`download: Downloading ${remotePath} to ${dataLayout.toString()}`);
await promiseRetry({ times: 3, interval: 20000, log }, async () => {
await retry({ times: 3, interval: 20000, log }, async () => {
progressCallback({ message: `Downloading backup ${remotePath}` });
const sourceStream = await backupSites.storageApi(backupSite).download(backupSite.config, remotePath);
@@ -269,7 +269,7 @@ async function upload(backupSite, remotePath, dataLayout, progressCallback) {
log(`upload: uploading to site ${backupSite.id} path ${remotePath} (encrypted: ${!!backupSite.encryption}) dataLayout ${dataLayout.toString()}`);
return await promiseRetry({ times: 5, interval: 20000, log }, async () => {
return await retry({ times: 5, interval: 20000, log }, async () => {
progressCallback({ message: `Uploading backup ${remotePath}` });
const uploader = await backupSites.storageApi(backupSite).upload(backupSite.config, backupSite.limits, remotePath);
+2 -2
View File
@@ -2,7 +2,7 @@ import assert from 'node:assert';
import BoxError from './boxerror.js';
import logger from './logger.js';
import manifestFormat from '@cloudron/manifest-format';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import superagent from '@cloudron/superagent';
@@ -170,7 +170,7 @@ async function getAppUpdate(app, options) {
}
async function downloadIcon(manifest) {
return await promiseRetry({ times: 10, interval: 5000, log }, async function () {
return await retry({ times: 10, interval: 5000, log }, async function () {
const [networkError, response] = await safe(superagent.get(manifest.iconUrl)
.timeout(60 * 1000)
.ok(() => true));
+3 -3
View File
@@ -9,7 +9,7 @@ import ipaddr from './ipaddr.js';
import mail from './mail.js';
import mailServer from './mailserver.js';
import network from './network.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import tasks from './tasks.js';
import tld from 'tldjs';
@@ -250,7 +250,7 @@ async function registerLocations(locations, options, progressCallback) {
for (const location of locations) {
progressCallback({ message: `Registering location ${fqdn(location.subdomain, location.domain)}` });
await promiseRetry({ times: 200, interval: 5000, log, retry: (error) => error.retryable }, async function () {
await retry({ times: 200, interval: 5000, log, retry: (error) => error.retryable }, async function () {
// cname records cannot co-exist with other records
const [getError, values] = await safe(getDnsRecords(location.subdomain, location.domain, 'CNAME'));
if (!getError && values.length === 1) {
@@ -300,7 +300,7 @@ async function unregisterLocations(locations, progressCallback) {
for (const location of locations) {
progressCallback({ message: `Unregistering location: ${location.subdomain ? (location.subdomain + '.') : ''}${location.domain}` });
await promiseRetry({ times: 30, interval: 5000, log, retry: (error) => error.retryable }, async function () {
await retry({ times: 30, interval: 5000, log, retry: (error) => error.retryable }, async function () {
if (ipv4) await unregisterLocation(location, 'A', ipv4);
if (ipv6) await unregisterLocation(location, 'AAAA', ipv6);
});
+2 -2
View File
@@ -4,7 +4,7 @@ import constants from '../constants.js';
import logger from '../logger.js';
import dig from '../dig.js';
import dns from '../dns.js';
import promiseRetry from '../promise-retry.js';
import retry from '../retry.js';
import safe from 'safetydance';
import superagent from '@cloudron/superagent';
import waitForDns from './waitfordns.js';
@@ -88,7 +88,7 @@ async function waitForAction(domainConfig, id) {
assert.strictEqual(typeof domainConfig, 'object');
assert.strictEqual(typeof id, 'number');
await promiseRetry({ times: 100, interval: 1000, log }, async () => {
await retry({ times: 100, interval: 1000, log }, async () => {
const [error, response] = await safe(superagent.get(`${ENDPOINT}/actions/${id}`)
.set('Authorization', `Bearer ${domainConfig.token}`)
.timeout(30 * 1000)
+2 -2
View File
@@ -3,7 +3,7 @@ import BoxError from '../boxerror.js';
import logger from '../logger.js';
import dig from '../dig.js';
import dns from 'node:dns';
import promiseRetry from '../promise-retry.js';
import retry from '../retry.js';
import safe from 'safetydance';
import _ from '../underscore.js';
@@ -89,7 +89,7 @@ async function waitForDns(hostname, zoneName, type, value, options) {
log(`waitForDns: waiting for ${hostname} to be ${value} in zone ${zoneName}`);
await promiseRetry(Object.assign({ log }, options), async function () {
await retry(Object.assign({ log }, options), async function () {
const nameservers = await dig.resolve(zoneName, 'NS', { timeout: 5000 });
if (!nameservers) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Unable to get nameservers');
log(`waitForDns: nameservers are ${JSON.stringify(nameservers)}`);
+3 -3
View File
@@ -10,7 +10,7 @@ import fs from 'node:fs';
import mailServer from './mailserver.js';
import os from 'node:os';
import paths from './paths.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import services from './services.js';
import shellModule from './shell.js';
import safe from 'safetydance';
@@ -459,7 +459,7 @@ async function downloadImage(manifest) {
const parsedManifestRef = parseImageRef(manifest.dockerImage);
await promiseRetry({ times: 10, interval: 5000, log, retry: (pullError) => pullError.reason !== BoxError.FS_ERROR }, async () => {
await retry({ times: 10, interval: 5000, log, retry: (pullError) => pullError.reason !== BoxError.FS_ERROR }, async () => {
// custom (non appstore) image
if (parsedManifestRef.registry !== null || !parsedManifestRef.fullRepositoryName.startsWith('cloudron/')) return await pullImage(manifest.dockerImage);
@@ -763,7 +763,7 @@ async function createSubcontainer(app, name, cmd, options) {
const mergedOptions = Object.assign({}, containerOptions, options);
// attempt a few times in case ephemeral ports got allocated during container recreation
const [createError, container] = await safe(promiseRetry({ times: 3, interval: 30000, log, retry: (err) => err.statusCode === 500 && /address already in use/.test(err.message) }, async function () {
const [createError, container] = await safe(retry({ times: 3, interval: 30000, log, retry: (err) => err.statusCode === 500 && /address already in use/.test(err.message) }, async function () {
return await gConnection.createContainer(mergedOptions);
}));
if (createError && createError.statusCode === 409) throw new BoxError(BoxError.ALREADY_EXISTS, createError);
+5 -5
View File
@@ -2,7 +2,7 @@ import assert from 'node:assert';
import BoxError from './boxerror.js';
import database from './database.js';
import logger from './logger.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
const { log } = logger('locks');
@@ -59,7 +59,7 @@ function canAcquire(data, type) {
async function acquire(type) {
assert.strictEqual(typeof type, 'string');
await promiseRetry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
await retry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
const { version, data } = await read();
const error = canAcquire(data, type);
if (error) throw error;
@@ -72,13 +72,13 @@ async function acquire(type) {
async function wait(type) {
assert.strictEqual(typeof type, 'string');
await promiseRetry({ times: Number.MAX_SAFE_INTEGER, interval: 10000, log }, async () => await acquire(type));
await retry({ times: Number.MAX_SAFE_INTEGER, interval: 10000, log }, async () => await acquire(type));
}
async function release(type) {
assert.strictEqual(typeof type, 'string');
await promiseRetry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
await retry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
const { version, data } = await read();
if (!(type in data)) throw new BoxError(BoxError.BAD_STATE, `Lock ${type} was never acquired`);
if (data[type] !== gTaskId) throw new BoxError(BoxError.BAD_STATE, `Task ${gTaskId} attempted to release lock ${type} acquired by ${data[type]}`);
@@ -98,7 +98,7 @@ async function releaseAll() {
async function releaseByTaskId(taskId) {
assert.strictEqual(typeof taskId, 'string');
await promiseRetry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
await retry({ times: Number.MAX_SAFE_INTEGER, interval: 100, log, retry: (error) => error.reason === BoxError.CONFLICT }, async () => {
const { version, data } = await read();
for (const type of Object.keys(data)) {
+2 -2
View File
@@ -2,7 +2,7 @@ import assert from 'node:assert';
import timers from 'timers/promises';
import util from 'node:util';
async function promiseRetry(options, asyncFunction) {
async function retry(options, asyncFunction) {
assert.strictEqual(typeof options, 'object');
assert(util.types.isAsyncFunction(asyncFunction));
@@ -20,4 +20,4 @@ async function promiseRetry(options, asyncFunction) {
}
}
export default promiseRetry;
export default retry;
+2 -2
View File
@@ -23,7 +23,7 @@ import os from 'node:os';
import path from 'node:path';
import paths from './paths.js';
import { pipeFileToRequest, pipeRequestToFile } from '@cloudron/pipework';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import semver from 'semver';
import settings from './settings.js';
@@ -194,7 +194,7 @@ async function waitForContainer(containerName, tokenEnvName) {
const result = await getContainerDetails(containerName, tokenEnvName);
await promiseRetry({ times: 20, interval: 15000, log }, async () => {
await retry({ times: 20, interval: 15000, log }, async () => {
const [networkError, response] = await safe(superagent.get(`http://${result.ip}:3000/healthcheck?access_token=${result.token}`)
.timeout(20000)
.ok(() => true));
@@ -1,12 +1,12 @@
import { describe, it } from 'mocha';
import assert from 'node:assert/strict';
import promiseRetry from '../promise-retry.js';
import retry from '../retry.js';
import safe from 'safetydance';
describe('promiseRetry', function () {
describe('retry', function () {
it('normal return', async function () {
const result = await promiseRetry({ times: 5, interval: 1000 }, async () => {
const result = await retry({ times: 5, interval: 1000 }, async () => {
return 42;
});
@@ -14,7 +14,7 @@ describe('promiseRetry', function () {
});
it('throws error', async function () {
const [error] = await safe(promiseRetry({ times: 5, interval: 1000 }, async () => {
const [error] = await safe(retry({ times: 5, interval: 1000 }, async () => {
throw new Error('42');
}));
@@ -23,7 +23,7 @@ describe('promiseRetry', function () {
it('3 tries', async function () {
let tryCount = 0;
const result = await promiseRetry({ times: 5, interval: 1000 }, async () => {
const result = await retry({ times: 5, interval: 1000 }, async () => {
if (++tryCount == 3) return 42; else throw new Error('42');
});
@@ -32,7 +32,7 @@ describe('promiseRetry', function () {
it('can abort with 1 try only', async function () {
let tryCount = 0;
const [error] = await safe(promiseRetry({ times: 5, interval: 1000, retry: () => false }, async () => {
const [error] = await safe(retry({ times: 5, interval: 1000, retry: () => false }, async () => {
++tryCount;
throw tryCount;
}));
+2 -2
View File
@@ -19,7 +19,7 @@ import notifications from './notifications.js';
import os from 'node:os';
import path from 'node:path';
import paths from './paths.js';
import promiseRetry from './promise-retry.js';
import retry from './retry.js';
import safe from 'safetydance';
import semver from 'semver';
import settings from './settings.js';
@@ -72,7 +72,7 @@ async function downloadBoxUrl(url, file) {
safe.fs.unlinkSync(file);
await promiseRetry({ times: 10, interval: 5000, log }, async function () {
await retry({ times: 10, interval: 5000, log }, async function () {
log(`downloadBoxUrl: downloading ${url} to ${file}`);
const [error] = await safe(shell.spawn('curl', ['-s', '--fail', url, '-o', file], { encoding: 'utf8' }));
if (error) throw new BoxError(BoxError.NETWORK_ERROR, `Failed to download ${url}: ${error.message}`);