Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
029f2a6872 | |||
66676d89a5 | |||
775a307056 | |||
4aa7621401 | |||
b7ac5cb864 | |||
f580281ccd |
@ -7,10 +7,10 @@
|
|||||||
"projectType": "npm",
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "pushrocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "lik",
|
"gitrepo": "lik",
|
||||||
"description": "light little helpers for node",
|
"description": "light little helpers for node",
|
||||||
"npmPackagename": "@pushrocks/lik",
|
"npmPackagename": "@push.rocks/lik",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pushrocks/lik",
|
"name": "@push.rocks/lik",
|
||||||
"version": "6.0.2",
|
"version": "6.0.4",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "light little helpers for node",
|
"description": "light little helpers for node",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
@ -30,11 +30,11 @@
|
|||||||
"@types/node": "^18.11.18"
|
"@types/node": "^18.11.18"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pushrocks/smartdelay": "^2.0.13",
|
"@push.rocks/smartdelay": "^3.0.2",
|
||||||
"@pushrocks/smartmatch": "^2.0.0",
|
"@push.rocks/smartmatch": "^2.0.0",
|
||||||
"@pushrocks/smartpromise": "^3.1.7",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@pushrocks/smartrx": "^3.0.0",
|
"@push.rocks/smartrx": "^3.0.0",
|
||||||
"@pushrocks/smarttime": "^4.0.1",
|
"@push.rocks/smarttime": "^4.0.1",
|
||||||
"@types/minimatch": "^5.1.2",
|
"@types/minimatch": "^5.1.2",
|
||||||
"@types/symbol-tree": "^3.2.2",
|
"@types/symbol-tree": "^3.2.2",
|
||||||
"symbol-tree": "^3.2.4"
|
"symbol-tree": "^3.2.4"
|
||||||
|
3204
pnpm-lock.yaml
generated
3204
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @pushrocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@pushrocks/lik',
|
name: '@push.rocks/lik',
|
||||||
version: '6.0.2',
|
version: '6.0.4',
|
||||||
description: 'light little helpers for node'
|
description: 'light little helpers for node'
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,14 @@ interface IExecutionSlot<T> {
|
|||||||
mode: 'exclusive' | 'nonexclusive';
|
mode: 'exclusive' | 'nonexclusive';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* allows for avoiding race condition
|
|
||||||
*/
|
|
||||||
export class AsyncExecutionStack {
|
export class AsyncExecutionStack {
|
||||||
private executionSlots: IExecutionSlot<any>[] = [];
|
private executionSlots: IExecutionSlot<any>[] = [];
|
||||||
public async getExclusiveExecutionSlot<T = any>(funcArg: () => Promise<T>, timeoutArg?: number) {
|
private isProcessing = false;
|
||||||
|
|
||||||
|
public async getExclusiveExecutionSlot<T = any>(
|
||||||
|
funcArg: () => Promise<T>,
|
||||||
|
timeoutArg?: number
|
||||||
|
): Promise<T> {
|
||||||
const executionDeferred = plugins.smartpromise.defer<T>();
|
const executionDeferred = plugins.smartpromise.defer<T>();
|
||||||
const executionSlot: IExecutionSlot<T> = {
|
const executionSlot: IExecutionSlot<T> = {
|
||||||
funcToExecute: funcArg,
|
funcToExecute: funcArg,
|
||||||
@ -24,10 +26,11 @@ export class AsyncExecutionStack {
|
|||||||
this.processExecutionSlots();
|
this.processExecutionSlots();
|
||||||
return executionDeferred.promise;
|
return executionDeferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getNonExclusiveExecutionSlot<T = any>(
|
public async getNonExclusiveExecutionSlot<T = any>(
|
||||||
funcArg: () => Promise<T>,
|
funcArg: () => Promise<T>,
|
||||||
timeoutArg?: number
|
timeoutArg?: number
|
||||||
) {
|
): Promise<T> {
|
||||||
const executionDeferred = plugins.smartpromise.defer<T>();
|
const executionDeferred = plugins.smartpromise.defer<T>();
|
||||||
const executionSlot: IExecutionSlot<T> = {
|
const executionSlot: IExecutionSlot<T> = {
|
||||||
funcToExecute: funcArg,
|
funcToExecute: funcArg,
|
||||||
@ -40,43 +43,68 @@ export class AsyncExecutionStack {
|
|||||||
return executionDeferred.promise;
|
return executionDeferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
private currentlyExecutingDeferred: plugins.smartpromise.Deferred<any>;
|
|
||||||
private async processExecutionSlots() {
|
private async processExecutionSlots() {
|
||||||
if (this.currentlyExecutingDeferred) {
|
if (this.isProcessing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentlyExecutingDeferred = plugins.smartpromise.defer();
|
this.isProcessing = true;
|
||||||
let nonExclusiveRunningSlots: IExecutionSlot<any>[] = [];
|
|
||||||
const checkNonExclusiveRunningSlots = async (cleanArg = false) => {
|
|
||||||
if (nonExclusiveRunningSlots.length > 100 || cleanArg) {
|
|
||||||
await Promise.all(nonExclusiveRunningSlots.map(nonExclusiveRunningSlotArg => nonExclusiveRunningSlotArg.executionDeferred.promise));
|
|
||||||
nonExclusiveRunningSlots = [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
while (this.executionSlots.length > 0) {
|
while (this.executionSlots.length > 0) {
|
||||||
const nextExecutionSlot = this.executionSlots.shift();
|
const currentSlot = this.executionSlots[0];
|
||||||
const runNextExecution = async () => {
|
if (currentSlot.mode === 'exclusive') {
|
||||||
if (nextExecutionSlot.timeout) {
|
await this.executeExclusiveSlot(currentSlot);
|
||||||
const result = await Promise.race([
|
this.executionSlots.shift();
|
||||||
nextExecutionSlot.funcToExecute(),
|
|
||||||
plugins.smartdelay.delayFor(nextExecutionSlot.timeout),
|
|
||||||
]);
|
|
||||||
nextExecutionSlot.executionDeferred.resolve(result);
|
|
||||||
} else {
|
|
||||||
nextExecutionSlot.executionDeferred.resolve(await nextExecutionSlot.funcToExecute());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (nextExecutionSlot.mode === 'exclusive') {
|
|
||||||
await checkNonExclusiveRunningSlots(true);
|
|
||||||
await runNextExecution();
|
|
||||||
} else {
|
} else {
|
||||||
nonExclusiveRunningSlots.push(nextExecutionSlot);
|
// Gather all non-exclusive slots at the front of the queue
|
||||||
await checkNonExclusiveRunningSlots(false);
|
const nonExclusiveSlots: IExecutionSlot<any>[] = [];
|
||||||
runNextExecution();
|
while (this.executionSlots.length > 0 && this.executionSlots[0].mode === 'nonexclusive') {
|
||||||
|
nonExclusiveSlots.push(this.executionSlots.shift()!);
|
||||||
|
}
|
||||||
|
await this.executeNonExclusiveSlots(nonExclusiveSlots);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.currentlyExecutingDeferred.resolve();
|
this.isProcessing = false;
|
||||||
this.currentlyExecutingDeferred = null;
|
}
|
||||||
|
|
||||||
|
private async executeExclusiveSlot(slot: IExecutionSlot<any>) {
|
||||||
|
try {
|
||||||
|
if (slot.timeout) {
|
||||||
|
const result = await Promise.race([
|
||||||
|
slot.funcToExecute(),
|
||||||
|
plugins.smartdelay.delayFor(slot.timeout).then(() => {
|
||||||
|
throw new Error('Timeout reached');
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
slot.executionDeferred.resolve(result);
|
||||||
|
} else {
|
||||||
|
const result = await slot.funcToExecute();
|
||||||
|
slot.executionDeferred.resolve(result);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
slot.executionDeferred.reject(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async executeNonExclusiveSlots(slots: IExecutionSlot<any>[]) {
|
||||||
|
const promises = slots.map(async (slot) => {
|
||||||
|
try {
|
||||||
|
if (slot.timeout) {
|
||||||
|
const result = await Promise.race([
|
||||||
|
slot.funcToExecute(),
|
||||||
|
plugins.smartdelay.delayFor(slot.timeout).then(() => {
|
||||||
|
throw new Error('Timeout reached');
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
slot.executionDeferred.resolve(result);
|
||||||
|
} else {
|
||||||
|
const result = await slot.funcToExecute();
|
||||||
|
slot.executionDeferred.resolve(result);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
slot.executionDeferred.reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// ==============
|
// ==============
|
||||||
// @pushrocks
|
// @pushrocks
|
||||||
// ==============
|
// ==============
|
||||||
import * as smartdelay from '@pushrocks/smartdelay';
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
import * as smartmatch from '@pushrocks/smartmatch';
|
import * as smartmatch from '@push.rocks/smartmatch';
|
||||||
import * as smartpromise from '@pushrocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import * as smartrx from '@pushrocks/smartrx';
|
import * as smartrx from '@push.rocks/smartrx';
|
||||||
import * as smarttime from '@pushrocks/smarttime';
|
import * as smarttime from '@push.rocks/smarttime';
|
||||||
|
|
||||||
export { smartdelay, smartmatch, smartpromise, smartrx, smarttime };
|
export { smartdelay, smartmatch, smartpromise, smartrx, smarttime };
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user