mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
Moved path_exists and promises to es6
This commit is contained in:
parent
6ed711a4d8
commit
4ff00e278a
8 changed files with 59 additions and 31 deletions
|
@ -25,7 +25,8 @@ const randomString = require('../utils/randomstring');
|
||||||
const hooks = require('../../static/js/pluginfw/hooks');
|
const hooks = require('../../static/js/pluginfw/hooks');
|
||||||
import pad_utils from "../../static/js/pad_utils";
|
import pad_utils from "../../static/js/pad_utils";
|
||||||
import {SmartOpAssembler} from "../../static/js/SmartOpAssembler";
|
import {SmartOpAssembler} from "../../static/js/SmartOpAssembler";
|
||||||
const promises = require('../utils/promises');
|
import {} from '../utils/promises';
|
||||||
|
import {timesLimit} from "async";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copied from the Etherpad source code. It converts Windows line breaks to Unix
|
* Copied from the Etherpad source code. It converts Windows line breaks to Unix
|
||||||
|
@ -586,12 +587,14 @@ class Pad {
|
||||||
p.push(db.remove(`pad2readonly:${padID}`));
|
p.push(db.remove(`pad2readonly:${padID}`));
|
||||||
|
|
||||||
// delete all chat messages
|
// delete all chat messages
|
||||||
p.push(promises.timesLimit(this.chatHead + 1, 500, async (i: string) => {
|
// @ts-ignore
|
||||||
|
p.push(timesLimit(this.chatHead + 1, 500, async (i: string) => {
|
||||||
await this.db.remove(`pad:${this.id}:chat:${i}`, null);
|
await this.db.remove(`pad:${this.id}:chat:${i}`, null);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// delete all revisions
|
// delete all revisions
|
||||||
p.push(promises.timesLimit(this.head + 1, 500, async (i: string) => {
|
// @ts-ignore
|
||||||
|
p.push(timesLimit(this.head + 1, 500, async (i: string) => {
|
||||||
await this.db.remove(`pad:${this.id}:revs:${i}`, null);
|
await this.db.remove(`pad:${this.id}:revs:${i}`, null);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CustomError = require('../utils/customError');
|
const CustomError = require('../utils/customError');
|
||||||
const promises = require('../utils/promises');
|
import {firstSatisfies} from '../utils/promises';
|
||||||
const randomString = require('../utils/randomstring');
|
const randomString = require('../utils/randomstring');
|
||||||
const db = require('./DB');
|
const db = require('./DB');
|
||||||
const groupManager = require('./GroupManager');
|
const groupManager = require('./GroupManager');
|
||||||
|
@ -79,7 +79,7 @@ exports.findAuthorID = async (groupID:string, sessionCookie: string) => {
|
||||||
groupID: string;
|
groupID: string;
|
||||||
validUntil: number;
|
validUntil: number;
|
||||||
}|null) => (si != null && si.groupID === groupID && now < si.validUntil);
|
}|null) => (si != null && si.groupID === groupID && now < si.validUntil);
|
||||||
const sessionInfo = await promises.firstSatisfies(sessionInfoPromises, isMatch);
|
const sessionInfo = await firstSatisfies(sessionInfoPromises, isMatch) as any;
|
||||||
if (sessionInfo == null) return undefined;
|
if (sessionInfo == null) return undefined;
|
||||||
return sessionInfo.authorID;
|
return sessionInfo.authorID;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@ const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const _ = require('underscore');
|
const _ = require('underscore');
|
||||||
const pluginDefs = require('../../static/js/pluginfw/plugin_defs');
|
const pluginDefs = require('../../static/js/pluginfw/plugin_defs');
|
||||||
const existsSync = require('../utils/path_exists');
|
import existsSync from '../utils/path_exists';
|
||||||
const settings = require('../utils/Settings');
|
const settings = require('../utils/Settings');
|
||||||
|
|
||||||
// returns all existing messages merged together and grouped by langcode
|
// returns all existing messages merged together and grouped by langcode
|
||||||
|
|
|
@ -74,7 +74,7 @@ const express = require('./hooks/express');
|
||||||
const hooks = require('../static/js/pluginfw/hooks');
|
const hooks = require('../static/js/pluginfw/hooks');
|
||||||
const pluginDefs = require('../static/js/pluginfw/plugin_defs');
|
const pluginDefs = require('../static/js/pluginfw/plugin_defs');
|
||||||
const plugins = require('../static/js/pluginfw/plugins');
|
const plugins = require('../static/js/pluginfw/plugins');
|
||||||
const {Gate} = require('./utils/promises');
|
import {Gate} from './utils/promises';
|
||||||
const stats = require('./stats')
|
const stats = require('./stats')
|
||||||
|
|
||||||
const logger = log4js.getLogger('server');
|
const logger = log4js.getLogger('server');
|
||||||
|
@ -100,7 +100,7 @@ const removeSignalListener = (signal: NodeJS.Signals, listener: NodeJS.SignalsLi
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let startDoneGate: { resolve: () => void; }
|
let startDoneGate: Gate<unknown>
|
||||||
exports.start = async () => {
|
exports.start = async () => {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case State.INITIAL:
|
case State.INITIAL:
|
||||||
|
@ -181,12 +181,14 @@ exports.start = async () => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Error occurred while starting Etherpad');
|
logger.error('Error occurred while starting Etherpad');
|
||||||
state = State.STATE_TRANSITION_FAILED;
|
state = State.STATE_TRANSITION_FAILED;
|
||||||
|
// @ts-ignore
|
||||||
startDoneGate.resolve();
|
startDoneGate.resolve();
|
||||||
return await exports.exit(err);
|
return await exports.exit(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('Etherpad is running');
|
logger.info('Etherpad is running');
|
||||||
state = State.RUNNING;
|
state = State.RUNNING;
|
||||||
|
// @ts-ignore
|
||||||
startDoneGate.resolve();
|
startDoneGate.resolve();
|
||||||
|
|
||||||
// Return the HTTP server to make it easier to write tests.
|
// Return the HTTP server to make it easier to write tests.
|
||||||
|
@ -228,11 +230,13 @@ exports.stop = async () => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Error occurred while stopping Etherpad');
|
logger.error('Error occurred while stopping Etherpad');
|
||||||
state = State.STATE_TRANSITION_FAILED;
|
state = State.STATE_TRANSITION_FAILED;
|
||||||
|
// @ts-ignore
|
||||||
stopDoneGate.resolve();
|
stopDoneGate.resolve();
|
||||||
return await exports.exit(err);
|
return await exports.exit(err);
|
||||||
}
|
}
|
||||||
logger.info('Etherpad stopped');
|
logger.info('Etherpad stopped');
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
|
// @ts-ignore
|
||||||
stopDoneGate.resolve();
|
stopDoneGate.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
const fs = require('fs');
|
import fs from 'node:fs';
|
||||||
|
|
||||||
const check = (path:string) => {
|
const check = (path:string) => {
|
||||||
const existsSync = fs.statSync || fs.existsSync;
|
const existsSync = fs.statSync || fs.existsSync;
|
||||||
|
@ -13,4 +13,4 @@ const check = (path:string) => {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = check;
|
export default check;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// `predicate`. Resolves to `undefined` if none of the Promises satisfy `predicate`, or if
|
// `predicate`. Resolves to `undefined` if none of the Promises satisfy `predicate`, or if
|
||||||
// `promises` is empty. If `predicate` is nullish, the truthiness of the resolved value is used as
|
// `promises` is empty. If `predicate` is nullish, the truthiness of the resolved value is used as
|
||||||
// the predicate.
|
// the predicate.
|
||||||
exports.firstSatisfies = <T>(promises: Promise<T>[], predicate: null|Function) => {
|
export const firstSatisfies = <T>(promises: Promise<T>[], predicate: null|Function) => {
|
||||||
if (predicate == null) {
|
if (predicate == null) {
|
||||||
predicate = (x: any) => x;
|
predicate = (x: any) => x;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ exports.firstSatisfies = <T>(promises: Promise<T>[], predicate: null|Function) =
|
||||||
// `total` is greater than `concurrency`, then `concurrency` Promises will be created right away,
|
// `total` is greater than `concurrency`, then `concurrency` Promises will be created right away,
|
||||||
// and each remaining Promise will be created once one of the earlier Promises resolves.) This async
|
// and each remaining Promise will be created once one of the earlier Promises resolves.) This async
|
||||||
// function resolves once all `total` Promises have resolved.
|
// function resolves once all `total` Promises have resolved.
|
||||||
exports.timesLimit = async (total: number, concurrency: number, promiseCreator: Function) => {
|
export const timesLimit = async (total: number, concurrency: number, promiseCreator: Function) => {
|
||||||
if (total > 0 && concurrency <= 0) throw new RangeError('concurrency must be positive');
|
if (total > 0 && concurrency <= 0) throw new RangeError('concurrency must be positive');
|
||||||
let next = 0;
|
let next = 0;
|
||||||
const addAnother = () => promiseCreator(next++).finally(() => {
|
const addAnother = () => promiseCreator(next++).finally(() => {
|
||||||
|
@ -61,7 +61,7 @@ exports.timesLimit = async (total: number, concurrency: number, promiseCreator:
|
||||||
* An ordinary Promise except the `resolve` and `reject` executor functions are exposed as
|
* An ordinary Promise except the `resolve` and `reject` executor functions are exposed as
|
||||||
* properties.
|
* properties.
|
||||||
*/
|
*/
|
||||||
class Gate<T> extends Promise<T> {
|
export class Gate<T> extends Promise<T> {
|
||||||
// Coax `.then()` into returning an ordinary Promise, not a Gate. See
|
// Coax `.then()` into returning an ordinary Promise, not a Gate. See
|
||||||
// https://stackoverflow.com/a/65669070 for the rationale.
|
// https://stackoverflow.com/a/65669070 for the rationale.
|
||||||
static get [Symbol.species]() { return Promise; }
|
static get [Symbol.species]() { return Promise; }
|
||||||
|
@ -75,4 +75,3 @@ class Gate<T> extends Promise<T> {
|
||||||
Object.assign(this, props);
|
Object.assign(this, props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Gate = Gate;
|
|
||||||
|
|
22
src/tests/backend-new/specs/path_exists.ts
Normal file
22
src/tests/backend-new/specs/path_exists.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import check from "../../../node/utils/path_exists";
|
||||||
|
import {expect, describe, it} from "vitest";
|
||||||
|
|
||||||
|
describe('Test path exists', function () {
|
||||||
|
it('should return true if the path exists - directory', function () {
|
||||||
|
const path = './locales';
|
||||||
|
const result = check(path);
|
||||||
|
expect(result).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if the path exists - file', function () {
|
||||||
|
const path = './locales/en.json';
|
||||||
|
const result = check(path);
|
||||||
|
expect(result).toBeTruthy();
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return false if the path does not exist', function () {
|
||||||
|
const path = './path_not_exists.ts';
|
||||||
|
const result = check(path);
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
});
|
||||||
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
import {MapArrayType} from "../../../node/types/MapType";
|
import {MapArrayType} from "../../../node/types/MapType";
|
||||||
|
|
||||||
const assert = require('assert').strict;
|
import {timesLimit} from '../../../node/utils/promises';
|
||||||
const promises = require('../../../node/utils/promises');
|
import {describe, it, expect} from "vitest";
|
||||||
|
|
||||||
describe(__filename, function () {
|
describe(__filename, function () {
|
||||||
describe('promises.timesLimit', function () {
|
describe('promises.timesLimit', function () {
|
||||||
|
@ -15,7 +15,7 @@ describe(__filename, function () {
|
||||||
const testPromises: TestPromise[] = [];
|
const testPromises: TestPromise[] = [];
|
||||||
const makePromise = (index: number) => {
|
const makePromise = (index: number) => {
|
||||||
// Make sure index increases by one each time.
|
// Make sure index increases by one each time.
|
||||||
assert.equal(index, wantIndex++);
|
expect(index).toEqual(wantIndex++);
|
||||||
// Save the resolve callback (so the test can trigger resolution)
|
// Save the resolve callback (so the test can trigger resolution)
|
||||||
// and the promise itself (to wait for resolve to take effect).
|
// and the promise itself (to wait for resolve to take effect).
|
||||||
const p:TestPromise = {};
|
const p:TestPromise = {};
|
||||||
|
@ -28,17 +28,17 @@ describe(__filename, function () {
|
||||||
|
|
||||||
const total = 11;
|
const total = 11;
|
||||||
const concurrency = 7;
|
const concurrency = 7;
|
||||||
const timesLimitPromise = promises.timesLimit(total, concurrency, makePromise);
|
const timesLimitPromise = timesLimit(total, concurrency, makePromise);
|
||||||
|
|
||||||
it('honors concurrency', async function () {
|
it('honors concurrency', async function () {
|
||||||
assert.equal(wantIndex, concurrency);
|
expect(wantIndex).toEqual(concurrency);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates another when one completes', async function () {
|
it('creates another when one completes', async function () {
|
||||||
const {promise, resolve} = testPromises.shift()!;
|
const {promise, resolve} = testPromises.shift()!;
|
||||||
resolve!();
|
resolve!();
|
||||||
await promise;
|
await promise;
|
||||||
assert.equal(wantIndex, concurrency + 1);
|
expect(wantIndex).toEqual(concurrency + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates the expected total number of promises', async function () {
|
it('creates the expected total number of promises', async function () {
|
||||||
|
@ -49,7 +49,7 @@ describe(__filename, function () {
|
||||||
resolve!();
|
resolve!();
|
||||||
await promise;
|
await promise;
|
||||||
}
|
}
|
||||||
assert.equal(wantIndex, total);
|
expect(wantIndex).toEqual(total);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves', async function () {
|
it('resolves', async function () {
|
||||||
|
@ -58,35 +58,35 @@ describe(__filename, function () {
|
||||||
|
|
||||||
it('does not create too many promises if total < concurrency', async function () {
|
it('does not create too many promises if total < concurrency', async function () {
|
||||||
wantIndex = 0;
|
wantIndex = 0;
|
||||||
assert.equal(testPromises.length, 0);
|
expect(testPromises.length).toEqual(0);
|
||||||
const total = 7;
|
const total = 7;
|
||||||
const concurrency = 11;
|
const concurrency = 11;
|
||||||
const timesLimitPromise = promises.timesLimit(total, concurrency, makePromise);
|
const timesLimitPromise = timesLimit(total, concurrency, makePromise);
|
||||||
while (testPromises.length > 0) {
|
while (testPromises.length > 0) {
|
||||||
const {promise, resolve} = testPromises.pop()!;
|
const {promise, resolve} = testPromises.pop()!;
|
||||||
resolve!();
|
resolve!();
|
||||||
await promise;
|
await promise;
|
||||||
}
|
}
|
||||||
await timesLimitPromise;
|
await timesLimitPromise;
|
||||||
assert.equal(wantIndex, total);
|
expect(wantIndex).toEqual(total);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts total === 0, concurrency > 0', async function () {
|
it('accepts total === 0, concurrency > 0', async function () {
|
||||||
wantIndex = 0;
|
wantIndex = 0;
|
||||||
assert.equal(testPromises.length, 0);
|
expect(testPromises.length).toEqual(0);
|
||||||
await promises.timesLimit(0, concurrency, makePromise);
|
await timesLimit(0, concurrency, makePromise);
|
||||||
assert.equal(wantIndex, 0);
|
expect(wantIndex).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts total === 0, concurrency === 0', async function () {
|
it('accepts total === 0, concurrency === 0', async function () {
|
||||||
wantIndex = 0;
|
wantIndex = 0;
|
||||||
assert.equal(testPromises.length, 0);
|
expect(testPromises.length).toEqual(0);
|
||||||
await promises.timesLimit(0, 0, makePromise);
|
await timesLimit(0, 0, makePromise);
|
||||||
assert.equal(wantIndex, 0);
|
expect(wantIndex).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects total > 0, concurrency === 0', async function () {
|
it('rejects total > 0, concurrency === 0', async function () {
|
||||||
await assert.rejects(promises.timesLimit(total, 0, makePromise), RangeError);
|
expect(timesLimit(total, 0, makePromise)).rejects.toThrow(RangeError);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
Reference in a new issue