Skip to content

Commit

Permalink
Improved lock mechanism using lock-token.
Browse files Browse the repository at this point in the history
  • Loading branch information
fenying committed Aug 20, 2018
1 parent 3a0814c commit fbc60c9
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 54 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# Changes Logs

## v0.2.0

- Added documents.
- Improved lock mechanism using lock-token.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@

[![npm version](https://img.shields.io/npm/v/@litert/mutex.svg?colorB=brightgreen)](https://www.npmjs.com/package/@litert/mutex "Stable Version")
[![License](https://img.shields.io/npm/l/@litert/mutex.svg?maxAge=2592000?style=plastic)](https://github.com/litert/mutex/blob/master/LICENSE)
[![node](https://img.shields.io/node/v/@litert/mutex.svg?colorB=brightgreen)](https://nodejs.org/dist/latest-v8.x/)
[![GitHub issues](https://img.shields.io/github/issues/litert/mutex.js.svg)](https://github.com/litert/mutex.js/issues)
[![GitHub Releases](https://img.shields.io/github/release/litert/mutex.js.svg)](https://github.com/litert/mutex.js/releases "Stable Release")

A mutex implement for Node.js.
A mutex implement for JavaScript.

## Requirement

- TypeScript v2.6.1 (or newer)
- Node.js v8.0.0 (or newer)
- TypeScript v2.9.2 (or newer)

## Installation

```sh
npm i @litert/mutex --save
```

## Document

- [简体中文版](./docs/zh-CN/README.md)

## License

This library is published under [Apache-2.0](./LICENSE) license.
7 changes: 7 additions & 0 deletions docs/zh-CN/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# LiteRT/Mutex 文档

Mutex.js 库提供互斥量,用于多会话、多进程环境下,对资源的访问进行控制。

## 目录

- [API 文档](./apis/README.md)
10 changes: 10 additions & 0 deletions docs/zh-CN/apis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# LiteRT/Mutex API 文档

## 目录

- [接口 IDriver](./interface.IDriver.md)
- [接口 IFactory](./interface.IFactory.md)
- [接口 IMutex](./interface.IMutex.md)
- [模块方法 createFactory](./method.createFactory.md)
- [模块方法 getDefaultFactory](./method.getDefaultFactory.md)
- [模块方法 createIntraprocessDriver](./method.createIntraprocessDriver.md)
38 changes: 38 additions & 0 deletions docs/zh-CN/apis/interface.IDriver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 接口 IDriver

该接口描述一个驱动对象的基本方法。

```ts
interface IDriver {

/**
* 尝试锁定一个互斥量。
*
* @param key 互斥量的唯一名称。
* @param token 互斥量的锁定状态标识,用于确认是由哪个对象锁定的。
* @param expiringAt 互斥量的锁定有效时长。设置为 0 则永不过期。
* 这是一个毫秒时间戳。
*/
lock(
key: string,
token: string,
expiringAt: number
): Promise<boolean> | boolean;

/**
* 根据锁定标识解锁一个互斥量。
*
* @param key 互斥量的唯一名称。
* @param token 互斥量的锁定状态标识,用于确认是由哪个对象锁定的。
*/
unlock(key: string, token: string): Promise<boolean> | boolean;

/**
* 判断一个互斥量是否被(指定锁定标识的拥有者)锁定。
*
* @param key 互斥量的唯一名称。
* @param token 互斥量的锁定状态标识,用于确认是由哪个对象锁定的。
*/
checkLocked(key: string, token: string): Promise<boolean> | boolean;
}
```
37 changes: 37 additions & 0 deletions docs/zh-CN/apis/interface.IFactory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 接口 IFactory

该接口描述一个工厂对象的基本方法。

```ts
interface IFactory {

/**
* 将一个驱动对象注册为一种互斥量类型。
*
* @param name 类型名称
* @param driver 驱动对象
*/
registerType(
name: string,
driver: IDriver
): this;

/**
* 列出所有可用的互斥量类型名称。
*/
listTypes(): string[];

/**
* 创建一个指定类型的互斥量对象。
*
* @param type 互斥量类型
* @param key 互斥量的唯一标识符
* @param ttl 互斥量的锁定有效时长。设置为 0 则永不过期。默认值:0 (毫秒)
*/
createMutex(
type: string,
key: string,
ttl?: number
): IMutex;
}
```
74 changes: 74 additions & 0 deletions docs/zh-CN/apis/interface.IMutex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 接口 IMutex

该接口描述一个互斥量对象的基本操作接口。

每个互斥量通过一个 key 进行标识。而一个互斥量对象是对特定一个互斥量的控制器。多个对象
可以通过同一个 key 对同一个互斥量进行控制。彼此之间的控制相互排斥。

```ts
interface IMutex {

/**
* 获取当前对象互斥量的唯一名称。
*/
readonly key: string;

/**
* 当前对象对该互斥量的每次锁定有效时长,单位:毫秒。
*
* 0 表示永久有效。
*/
readonly ttl: number;

/**
* 当前对象对该互斥量的锁定时间,这是一个毫秒时间戳。
*
* 0 表示未锁定。
*/
readonly lockedAt: number;

/**
* 该互斥量的锁定状态过期时间,到这个时间则该互斥量的锁定状态自动解除。
*
* 这是一个毫秒时间戳。
*
* 0 表示未永不过期。
*/
readonly expiringAt: number;

/**
* 检查当前对象是否成功锁定了该互斥量。
*/
isLocked(): boolean;

/**
* 检查当前对象对该互斥量的锁定状态是否已经过期。
*/
isExpired(): boolean;

/**
* 重新检查当前对象对该互斥量的锁定状态。
*/
recheckLocked(): Promise<boolean> | boolean;

/**
* 尝试锁定该互斥量。该接口是非阻塞的,一旦失败立即返回,而不是等待其他会话、进程
* 释放锁。
*
* 如果该互斥量此前已经被当前对象锁定了,则也会返回 false。
*
* @param ttl 锁定状态的有效时长,该参数可以覆盖该互斥量对象的设置。如果设置为
* 0 则互斥量的锁定状态永不过期。
* 默认值:0 (毫秒)
*/
lock(ttl?: number): Promise<boolean> | boolean;

/**
* 解除当前对象对该互斥量的锁定。
*
* 如果该互斥量不是被当前对象锁定的,则无法解除锁定,返回 false。
*/
unlock(): Promise<boolean> | boolean;
}

```
7 changes: 7 additions & 0 deletions docs/zh-CN/apis/method.createFactory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 模块方法 createFactory

该方法用于创建一个互斥量对象的工厂对象。

```ts
function createFactory(): IFactory;
```
10 changes: 10 additions & 0 deletions docs/zh-CN/apis/method.createIntraprocessDriver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 模块方法 createIntraprocessDriver

该方法用于创建一个进程内(`Intraprocess`)的互斥量驱动对象。

> 每个 `Intraprocess` 对象彼此独立隔离,即不同的 `Intraprocess` 对象之间,可以有
> 同名的互斥量,且互不干扰。
```ts
function createIntraprocessDriver(): IDriver;
```
7 changes: 7 additions & 0 deletions docs/zh-CN/apis/method.getDefaultFactory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 模块方法 getDefaultFactory

该方法用于获取默认的互斥量对象的工厂对象。

```ts
function getDefaultFactory(): IFactory;
```
8 changes: 1 addition & 7 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@litert/mutex",
"version": "0.1.0",
"description": "A mutex implement for Node.js.",
"version": "0.2.0",
"description": "A mutex implement for JavaScript.",
"main": "./lib/index.js",
"scripts": {
"prepare": "npm run rebuild",
Expand Down Expand Up @@ -29,10 +29,6 @@
"types": "./lib/index.d.ts",
"typings": "./lib/index.d.ts",
"devDependencies": {
"@types/node": "^8.10.26",
"typescript": "^2.9.2"
},
"engines": {
"node": ">=8.0.0"
}
}
15 changes: 8 additions & 7 deletions src/lib/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,31 @@ export interface IDriver {
* Try locking up a mutex.
*
* @param key The key of mutex to be locked.
* @param lockedAt The locked-time of mutex.
* @param token The lock-token of mutex.
* @param expiringAt The expiring-time of mutex. It never expires if
* set to 0. Default: 0 (ms)
*/
lock(
key: string,
lockedAt: number,
token: string,
expiringAt: number
): Promise<boolean> | boolean;

/**
* Unlock a mutex.
*
* @param key The key of mutex to be unlocked.
* @param lockedAt The time of mutex when it's locked.
* @param token The lock-token of mutex.
*/
unlock(key: string, lockedAt: number): Promise<boolean> | boolean;
unlock(key: string, token: string): Promise<boolean> | boolean;

/**
* Check if a mutex is locked.
*
* @param key The key of mutex to be checked.
* @param lockedAt The time of mutex when it's locked.
* @param token The lock-token of mutex.
*/
checkLocked(key: string, lockedAt: number): Promise<boolean> | boolean;
checkLocked(key: string, token: string): Promise<boolean> | boolean;
}

export interface IFactory {
Expand Down Expand Up @@ -126,7 +126,8 @@ export interface IMutex {
recheckLocked(): Promise<boolean> | boolean;

/**
* Try locking up a mutex.
* Try locking up a mutex. This is a non-blocking method. It would return
* immediately if the mutex is locked by others.
*
* Return false if this mutex is already locked (by anyone).
*
Expand Down
18 changes: 9 additions & 9 deletions src/lib/Driver.Intraprocess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ class Lock {

public expiringAt: number;

public lockedAt: number;
public token: string;

public constructor(
lockedAt: number,
token: string,
expiringAt: number
) {

this.expiringAt = expiringAt;

this.lockedAt = lockedAt;
this.token = token;
}

public isExpired(): boolean {
Expand All @@ -50,7 +50,7 @@ implements Com.IDriver {

public lock(
key: string,
lockedAt: number,
token: string,
expiringAt: number
): boolean {

Expand All @@ -61,21 +61,21 @@ implements Com.IDriver {
return false;
}

this._locks[key] = new Lock(lockedAt, expiringAt);
this._locks[key] = new Lock(token, expiringAt);

return true;
}

public unlock(
key: string,
lockedAt: number
token: string
): boolean {

let lock = this._locks[key];

if (lock) {

if (lock.lockedAt === lockedAt) {
if (lock.token === token) {

delete this._locks[key];
return true;
Expand All @@ -91,7 +91,7 @@ implements Com.IDriver {

public checkLocked(
key: string,
lockedAt: number
token: string
): boolean {

let lock = this._locks[key];
Expand All @@ -105,7 +105,7 @@ implements Com.IDriver {
return false;
}

if (lock.lockedAt === lockedAt) {
if (lock.token === token) {

return true;
}
Expand Down
Loading

0 comments on commit fbc60c9

Please sign in to comment.