vona-module-a-redlock 5.0.8 → 5.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.metadata/index.d.ts +54 -0
- package/dist/.metadata/index.js +25 -0
- package/dist/.metadata/this.d.ts +2 -0
- package/dist/.metadata/this.js +2 -0
- package/dist/config/config.d.ts +10 -0
- package/dist/config/config.js +16 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/lib/beanRedlockBase.d.ts +7 -0
- package/dist/lib/beanRedlockBase.js +18 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/service/redlock.d.ts +12 -0
- package/dist/service/redlock.js +76 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/redlock.d.ts +9 -0
- package/dist/types/redlock.js +1 -0
- package/package.json +7 -3
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { BeanScopeUtil, TypeModuleConfig } from 'vona';
|
|
2
|
+
import type { config } from '../config/config.ts';
|
|
3
|
+
/** service: end */
|
|
4
|
+
/** service: begin */
|
|
5
|
+
/** service: end */
|
|
6
|
+
/** service: begin */
|
|
7
|
+
import type { ServiceRedlock } from '../service/redlock.ts';
|
|
8
|
+
/** config: end */
|
|
9
|
+
/** scope: begin */
|
|
10
|
+
import { BeanScopeBase } from 'vona';
|
|
11
|
+
/** service: end */
|
|
12
|
+
/** config: begin */
|
|
13
|
+
import 'vona';
|
|
14
|
+
import 'vona';
|
|
15
|
+
import 'vona';
|
|
16
|
+
export * from '../config/config.ts';
|
|
17
|
+
declare module 'vona-module-a-web' {
|
|
18
|
+
interface IServiceRecord {
|
|
19
|
+
'a-redlock:redlock': never;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
declare module 'vona-module-a-redlock' {
|
|
23
|
+
interface ServiceRedlock {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export interface IModuleService {
|
|
27
|
+
redlock: ServiceRedlock;
|
|
28
|
+
}
|
|
29
|
+
declare module 'vona' {
|
|
30
|
+
interface IBeanRecordGeneral {
|
|
31
|
+
'a-redlock.service.redlock': ServiceRedlock;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** service: begin */
|
|
35
|
+
export * from '../service/redlock.ts';
|
|
36
|
+
export declare class ScopeModuleARedlock extends BeanScopeBase {
|
|
37
|
+
}
|
|
38
|
+
export interface ScopeModuleARedlock {
|
|
39
|
+
util: BeanScopeUtil;
|
|
40
|
+
config: TypeModuleConfig<typeof config>;
|
|
41
|
+
service: IModuleService;
|
|
42
|
+
}
|
|
43
|
+
declare module 'vona' {
|
|
44
|
+
interface IBeanScopeRecord {
|
|
45
|
+
'a-redlock': ScopeModuleARedlock;
|
|
46
|
+
}
|
|
47
|
+
interface IBeanScopeContainer {
|
|
48
|
+
redlock: ScopeModuleARedlock;
|
|
49
|
+
}
|
|
50
|
+
interface IBeanScopeConfig {
|
|
51
|
+
'a-redlock': ReturnType<typeof config>;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** scope: end */
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/** config: end */
|
|
8
|
+
/** scope: begin */
|
|
9
|
+
import { BeanScopeBase } from 'vona';
|
|
10
|
+
import { Scope } from 'vona-module-a-bean';
|
|
11
|
+
/** service: end */
|
|
12
|
+
/** config: begin */
|
|
13
|
+
import 'vona';
|
|
14
|
+
import 'vona';
|
|
15
|
+
import 'vona';
|
|
16
|
+
export * from "../config/config.js";
|
|
17
|
+
/** service: begin */
|
|
18
|
+
export * from "../service/redlock.js";
|
|
19
|
+
let ScopeModuleARedlock = class ScopeModuleARedlock extends BeanScopeBase {
|
|
20
|
+
};
|
|
21
|
+
ScopeModuleARedlock = __decorate([
|
|
22
|
+
Scope()
|
|
23
|
+
], ScopeModuleARedlock);
|
|
24
|
+
export { ScopeModuleARedlock };
|
|
25
|
+
/** scope: end */
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as Redlock from '@sesamecare-oss/redlock';
|
|
2
|
+
import type { VonaApplication } from 'vona';
|
|
3
|
+
import type { IRedisClientRecord } from 'vona-module-a-redis';
|
|
4
|
+
export declare function config(app: VonaApplication): {
|
|
5
|
+
redlock: {
|
|
6
|
+
clients: (keyof IRedisClientRecord)[];
|
|
7
|
+
lockTTL: number;
|
|
8
|
+
options: Redlock.Settings;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function config(app) {
|
|
2
|
+
const lockTTL = app.meta.isLocal ? 8 : app.meta.isTest ? 60 : 30;
|
|
3
|
+
return {
|
|
4
|
+
redlock: {
|
|
5
|
+
clients: ['redlock'],
|
|
6
|
+
lockTTL: lockTTL * 1000,
|
|
7
|
+
// https://github.com/mike-marcacci/node-redlock#configuration
|
|
8
|
+
options: {
|
|
9
|
+
driftFactor: 0.01,
|
|
10
|
+
retryCount: -1,
|
|
11
|
+
retryDelay: 200,
|
|
12
|
+
retryJitter: 100,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FunctionAsync } from 'vona';
|
|
2
|
+
import type { IRedlockLockIsolateOptions } from '../types/redlock.ts';
|
|
3
|
+
import { BeanBase } from 'vona';
|
|
4
|
+
export declare class BeanRedlockBase extends BeanBase {
|
|
5
|
+
protected __get__(prop: string): ((resource: string, fn: FunctionAsync<any>, options?: IRedlockLockIsolateOptions) => Promise<any>) | undefined;
|
|
6
|
+
private _prepareResource;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BeanBase, SymbolModuleBelong } from 'vona';
|
|
2
|
+
export class BeanRedlockBase extends BeanBase {
|
|
3
|
+
__get__(prop) {
|
|
4
|
+
if (prop === 'lock') {
|
|
5
|
+
return (resource, fn, options) => {
|
|
6
|
+
return this.$scope.redlock.service.redlock.lock(this._prepareResource(resource), fn, options);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
else if (prop === 'lockIsolate') {
|
|
10
|
+
return (resource, fn, options) => {
|
|
11
|
+
return this.$scope.redlock.service.redlock.lockIsolate(this._prepareResource(resource), fn, options);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
_prepareResource(resource) {
|
|
16
|
+
return `${this[SymbolModuleBelong]}.${resource}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './beanRedlockBase.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./beanRedlockBase.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Settings } from '@sesamecare-oss/redlock';
|
|
2
|
+
import type { FunctionAsync } from 'vona';
|
|
3
|
+
import type { IRedlockLockIsolateOptions, IRedlockLockOptions } from '../types/redlock.ts';
|
|
4
|
+
import { Redlock } from '@sesamecare-oss/redlock';
|
|
5
|
+
import { BeanBase } from 'vona';
|
|
6
|
+
export declare class ServiceRedlock extends BeanBase {
|
|
7
|
+
private _redlockDefault;
|
|
8
|
+
lock<RESULT>(resource: string, fn: FunctionAsync<RESULT>, options?: IRedlockLockOptions): Promise<RESULT>;
|
|
9
|
+
lockIsolate<RESULT>(resource: string, fn: FunctionAsync<RESULT>, options?: IRedlockLockIsolateOptions): Promise<RESULT>;
|
|
10
|
+
private get redlockDefault();
|
|
11
|
+
create(options: Settings): Redlock;
|
|
12
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Redlock } from '@sesamecare-oss/redlock';
|
|
8
|
+
import { BeanBase, instanceDesp } from 'vona';
|
|
9
|
+
import { Service } from 'vona-module-a-web';
|
|
10
|
+
let ServiceRedlock = class ServiceRedlock extends BeanBase {
|
|
11
|
+
_redlockDefault;
|
|
12
|
+
async lock(resource, fn, options) {
|
|
13
|
+
const instanceName = options?.instanceName === undefined ? this.ctx?.instanceName : options?.instanceName;
|
|
14
|
+
const redlock = options?.redlock ?? this.redlockDefault;
|
|
15
|
+
const lockTTL = options?.lockTTL ?? this.scope.config.redlock.lockTTL;
|
|
16
|
+
// resource
|
|
17
|
+
const _lockResource = `redlock_${this.app.name}:${instanceDesp(instanceName)}:${resource}`;
|
|
18
|
+
// lock
|
|
19
|
+
let _lock = await redlock.acquire([_lockResource], lockTTL);
|
|
20
|
+
// timer
|
|
21
|
+
let _lockTimer = null;
|
|
22
|
+
const _lockDone = () => {
|
|
23
|
+
if (_lockTimer) {
|
|
24
|
+
clearInterval(_lockTimer);
|
|
25
|
+
_lockTimer = null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
_lockTimer = setInterval(() => {
|
|
29
|
+
_lock
|
|
30
|
+
.extend(lockTTL)
|
|
31
|
+
.then(lock => {
|
|
32
|
+
_lock = lock;
|
|
33
|
+
})
|
|
34
|
+
.catch(_err => {
|
|
35
|
+
// need not logger error
|
|
36
|
+
// this.$logger.error(err);
|
|
37
|
+
_lockDone();
|
|
38
|
+
});
|
|
39
|
+
}, lockTTL / 2);
|
|
40
|
+
try {
|
|
41
|
+
return await fn();
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
_lockDone();
|
|
45
|
+
// not await, and throw error
|
|
46
|
+
_lock.release().catch(_err => {
|
|
47
|
+
// do nothing
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async lockIsolate(resource, fn, options) {
|
|
52
|
+
return await this.lock(resource, async () => {
|
|
53
|
+
return await this.bean.database.newDbIsolate(fn, options);
|
|
54
|
+
}, options);
|
|
55
|
+
}
|
|
56
|
+
get redlockDefault() {
|
|
57
|
+
if (!this._redlockDefault) {
|
|
58
|
+
this._redlockDefault = this.create(this.scope.config.redlock.options);
|
|
59
|
+
}
|
|
60
|
+
return this._redlockDefault;
|
|
61
|
+
}
|
|
62
|
+
create(options) {
|
|
63
|
+
// clients
|
|
64
|
+
const clients = [];
|
|
65
|
+
for (const clientName of this.scope.config.redlock.clients) {
|
|
66
|
+
const client = this.app.bean.redis.get(clientName);
|
|
67
|
+
clients.push(client);
|
|
68
|
+
}
|
|
69
|
+
// create
|
|
70
|
+
return new Redlock(clients, options);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
ServiceRedlock = __decorate([
|
|
74
|
+
Service()
|
|
75
|
+
], ServiceRedlock);
|
|
76
|
+
export { ServiceRedlock };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './redlock.ts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./redlock.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Redlock } from '@sesamecare-oss/redlock';
|
|
2
|
+
import type { IDbInfo } from 'vona-module-a-database';
|
|
3
|
+
export interface IRedlockLockOptions {
|
|
4
|
+
instanceName?: string | undefined | null;
|
|
5
|
+
redlock?: Redlock;
|
|
6
|
+
lockTTL?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface IRedlockLockIsolateOptions extends IRedlockLockOptions, IDbInfo {
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vona-module-a-redlock",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.10",
|
|
5
5
|
"title": "a-redlock",
|
|
6
6
|
"vonaModule": {
|
|
7
7
|
"dependencies": {},
|
|
@@ -39,8 +39,12 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@sesamecare-oss/redlock": "^1.4.0"
|
|
41
41
|
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"clean-package": "^2.2.0",
|
|
44
|
+
"rimraf": "^6.0.1"
|
|
45
|
+
},
|
|
42
46
|
"scripts": {
|
|
43
|
-
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
44
|
-
"tsc:publish": "npm run clean && tsc"
|
|
47
|
+
"clean": "rimraf dist tsconfig.build.tsbuildinfo",
|
|
48
|
+
"tsc:publish": "npm run clean && tsc -p tsconfig.build.json"
|
|
45
49
|
}
|
|
46
50
|
}
|