Mini Semaphore (mini-semaphore
A lightweight version of Semaphore
that limits the number of process that can simultaneously access a resource or pool of resources.
This implementation can only work within one javascript runtime thead and realized by Promise
Usage
- how to imports
// typescript
import {
ISimplifiedLock, IFlowableLock, // types
// NOTE: `class` and` object` both have the same interface
MiniSemaphore, // get implementation as class
create, // get implementation as object literal
restrictor // see Flow Restrictor section
} from "mini-semaphore";
// node
const {
MiniSemaphore,
create,
restrictor
} = require("mini-semaphore");
- class
import { MiniSemaphore, IFlowableLock } from "mini-semaphore";
// like Mutex
const ms: IFlowableLock = new MiniSemaphore(1);
// allow multiple
const ms = new MiniSemaphore(10);
- object
import { create as createSemaphore, IFlowableLock } from "mini-semaphore";
const ms: IFlowableLock = createSemaphore(10);
- Also, it can be read as a script element in the html page.
- In that case, access from
MiniSema
global variable
- In that case, access from
<script src="https://unpkg.com/mini-semaphore@latest/umd/index.js"></script>
<script>
// class
const ms = new MiniSema.MiniSemaphore(10);
// object
const mso = MiniSema.create(10);
</script>
Examples
// import MiniSemaphore class
import { MiniSemaphore } from "mini-semaphore";
// create `MiniSemaphore` with appropriate restrictions
// Limit the number of simultaneous requests to fire to 7
const s = new MiniSemaphore(7);
// example function
async function refreshToken(refresh_token: string) {
const fetchOption = {
method: "post",
mode: "cors",
headers: {
"content-type": "application/x-www-form-urlencoded",
host: "login.eveonline.com"
},
body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(refresh_token)}&client_id=${CLIENT_ID}&code_verifier=${VERIFIER}`
} as RequestInit;
let response: Response;
//
// #1 When processing details are write in code
//
await s.acquire(); // If the pending exceeds the limit, wait for ...
// Requires a "try catch" block to surely execute the "release" method
try {
response = await fetch("https://login.eveonline.com/v2/oauth/token", fetchOption);
} finally {
s.release(); // release the pending count
}
const data = await response.json() as TOAuth2AccessTokenResponse;
// ...
//
// #2 simplfied with `IFlowableLock.flow` method (automatic acquire/release)
//
response = await s.flow(async () => fetch("https://login.eveonline.com/v2/oauth/token", fetchOption));
const data = await response.json() as TOAuth2AccessTokenResponse;
// ...
}
Flow Restrictor
- Utility module using
MiniSemaphore
is available
/**
* create a semaphore for each `key`, and limit the number of shares with the value of `restriction`
*
* @param key number or string as tag
* @param restriction number of process restriction
* @param processBody the process body
*/
export declare function multi<T>(key: string | number, restriction: number, processBody: () => Promise<T>): Promise<T>;
/**
* synonym of `multi(key, 1, processBody)`
*
* + use case
* * Avoid concurrent requests to the same url
*
* @param key number or string as tag
* @param processBody the process body
*/
export declare function one<T>(key: string | number, processBody: () => Promise<T>): Promise<T>;
import { restrictor } from "mini-semaphore";
//
// Avoid concurrent requests to the same `id`
//
async function resolve(id: string | number): Promise<TType> {
const data = await restrictor.one(id, async () => {
let d = dataCache[id];
if (d === void 0) {
dataCache[id] = d = await fetch(
`https://esi.evetech.net/latest/universe/types/${id}/`)
).then(res => res.json());
}
return d;
}
);
return data;
}
Authors
- jeffy-g - jeffy-g
License
This project is licensed under the MIT License - see the LICENSE file for details