New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

reentrant-lock

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

reentrant-lock - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

9

index.d.ts

@@ -1,9 +0,12 @@

declare type ReentrantLockReleaser = () => void;
interface UnlockFn {
(): void;
}
export declare class ReentrantLock {
private current?;
private last?;
private next;
acquire(): Promise<ReentrantLockReleaser>;
private readonly chainNoop;
private readonly chainNext;
acquire(): Promise<UnlockFn>;
lock<T>(op: () => Promise<T>): Promise<T>;
}
export {};

@@ -6,8 +6,8 @@ "use strict";

constructor() {
this.next = () => {
this.chainNoop = () => void (0);
this.chainNext = () => {
if (this.current === this.last) {
this.current = undefined;
this.last = undefined;
this.current = this.last = undefined;
}
else if (this.current && this.current.next) {
else {
this.current.next();

@@ -19,13 +19,20 @@ }

if (!this.last) {
/* c8 ignore next */
this.current = this.last = () => null;
return Promise.resolve(this.next);
let noop = this.current = this.last = this.chainNoop;
return Promise.resolve(() => {
if (noop) {
noop = undefined;
this.chainNext();
}
});
}
else {
return new Promise((resolve, reject) => {
const lockChainItem = () => {
this.current = lockChainItem;
resolve(this.next);
return new Promise((resolve) => {
let lockChainFn = () => {
if (lockChainFn) {
this.current = lockChainFn;
lockChainFn = undefined;
resolve(this.chainNext);
}
};
this.last = this.last.next = lockChainItem;
this.last = this.last.next = lockChainFn;
});

@@ -35,5 +42,5 @@ }

lock(op) {
return this.acquire().then(releaser => op().finally(releaser));
return this.acquire().then(unlock => op().finally(unlock));
}
}
exports.ReentrantLock = ReentrantLock;
{
"name": "reentrant-lock",
"version": "2.0.1",
"version": "3.0.0",
"description": "Lock blocks of code to prevent concurrent execution",

@@ -30,8 +30,8 @@ "keywords": [

"devDependencies": {
"@types/tape": "^4.13.2",
"c8": "^7.11.3",
"tape": "^5.5.3",
"ts-node": "^10.8.1",
"typescript": "^4.7.3"
"@types/tape": "^5.6.1",
"c8": "^8.0.1",
"tape": "^5.6.6",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
}
}
# ReentrantLock
## Lock mechanism for promises, using a linked list like implementation.
This module is intended to lock promises, forcing some code block to be executed complete before while other contexts wait for the lock to be released.
The module has been written without using arrays using a linked function chain.
### Lightweight lock mechanism for promises, using a linked list implementation.
You can use same lock multiple times to lock different code blocks.
Lightweight, dependency free, promise lock mechanism.
It allows 2 semantics:
* Passing an async callback to the lock method
It's implemented without relying on arrays using a linked function chain.
The implementation can be reviewed in a moment, it is under 50 lines.
## Examples:
The library can be used to avoid concurrent execution of an async block that contains await calls.
For example a token refresh http request than can be invoked from different promises.
The next example summarized how to reduce the possible overload caused by that common situation:
```js
const promiseLock = new ReentrantLock();
const refreshLocker = new ReentrantLock();
let accessToken = "..."
let refreshToken = "..."
function isTokenExpired() {
... // return bool
}
async function refreshToken() {
// We lock the refresh block execution
await refreshLocker.lock(async ()=>{
// By checking the state again after the lock was released we know the previous consumer has already refreshed the token
if(!isTokenExpired()) {
// So we can abort the execution avoiding an unnecessary server call
return;
}
let newCredentials = await fetch(...);
...
});
}
export async function myApiCall1() {
if(isTokenExpired()) {
await refreshToken();
}
... // consume the api with a valid token
}
export async function myApiCall2() {
if(isTokenExpired()) {
await refreshToken();
}
... // consume the api with a valid token
}
...
// Somewhere in the code
await Promise.all([myApiCall1(), myApiCall2()]);
...
```
Also can be used to chain async executions that are not awaited and need to be non concurrent.
For example to display messages in an UI one after another like in the next basic example:
```js
const tooltipLocker = new ReentrantLock();
function displayTextForAWhile(text) {
const paragraph = document.createElement("p");
paragraph.textContent = text;
tooltipLocker.lock((unlock) => {
document.body.appendChild(elemDiv);
setTimeout(() => {
paragraph.remove();
unlock();
}, 2000);
})
.then(() => console.debug(`Text '${text}' displayed at ${new Date().getTime()}`))
.catch((err) => ...);
}
displayTextForAWhile("One tip");
displayTextForAWhile("Other tip");
displayTextForAWhile("Another one");
```
# Semantic
The library allows two semantics:
Passing an async callback to the lock method:
```js
const promiseLocker = new ReentrantLock();
async function () {
...
await promiseLock.lock(async ()=>{
await promiseLocker.lock(async ()=>{
// your code block

@@ -21,12 +102,15 @@ });

```
* Adquire the lock (you need to release it always)
Acquire and release the lock:
```js
const promiseLock = new ReentrantLock();
const promiseLocker = new ReentrantLock();
async function () {
...
const releaseLockFn = await promiseLock.acquire();
const unlockFn = await promiseLocker.acquire();
try{
// your code block
} finally {
releaseLockFn();
// unlock next consumer
unlockFn();
}

@@ -33,0 +117,0 @@ ...

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc