namirasoft-node-redis 1.4.5 → 1.4.7

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.
@@ -1,6 +1,6 @@
1
1
  import { RedisInstance } from "./RedisInstance";
2
2
  export declare abstract class RedisScope<V> {
3
- private instance;
3
+ protected instance: RedisInstance;
4
4
  constructor(instance: RedisInstance);
5
5
  protected _get(key: string, base64: boolean): Promise<V | null>;
6
6
  protected _set(key: string, value: V, base64: boolean, ttl_seconds?: number, NotExists?: boolean): Promise<"OK" | null>;
@@ -0,0 +1,18 @@
1
+ import { DurationUnit } from "namirasoft-core";
2
+ import { RedisInstance } from "./RedisInstance";
3
+ import { RedisScope } from "./RedisScope";
4
+ import { RedisScopeLock } from "./RedisScopeLock";
5
+ export type RedisScopeDelayParameter = {
6
+ id: string;
7
+ name: string;
8
+ delay: boolean;
9
+ delay_value: number | null;
10
+ delay_unit: DurationUnit | null;
11
+ };
12
+ export declare abstract class RedisScopeDelay<Parameters> extends RedisScope<Date> {
13
+ private locker;
14
+ constructor(instance: RedisInstance, locker: RedisScopeLock<Parameters>);
15
+ protected abstract key(key_parameter: Parameters): string;
16
+ wait(key_parameter: Parameters, parameter: RedisScopeDelayParameter): Promise<void>;
17
+ release(key_parameter: Parameters, parameter: RedisScopeDelayParameter): Promise<void>;
18
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RedisScopeDelay = void 0;
13
+ const namirasoft_core_1 = require("namirasoft-core");
14
+ const RedisScope_1 = require("./RedisScope");
15
+ class RedisScopeDelay extends RedisScope_1.RedisScope {
16
+ constructor(instance, locker) {
17
+ super(instance);
18
+ this.locker = locker;
19
+ this.key = this.key.bind(this);
20
+ this.wait = this.wait.bind(this);
21
+ this.release = this.release.bind(this);
22
+ }
23
+ wait(key_parameter, parameter) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ if (!parameter.delay || !parameter.delay_value || !parameter.delay_unit)
26
+ return;
27
+ let key = this.key(key_parameter);
28
+ let delay_requested = namirasoft_core_1.TimeUnitOperation.toMilliseconds(parameter.delay_value, parameter.delay_unit);
29
+ yield this.locker.waitForLock(key_parameter, Math.ceil(delay_requested / 1000));
30
+ let LastRun = yield this._get(key, false);
31
+ if (!LastRun)
32
+ return;
33
+ let difference = new Date().getTime() - LastRun.getTime();
34
+ let delay_required = Math.max(delay_requested - difference, 0);
35
+ if (delay_required > 0)
36
+ yield new Promise(resolve => setTimeout(resolve, delay_required));
37
+ });
38
+ }
39
+ release(key_parameter, parameter) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ if (!parameter.delay || !parameter.delay_value || !parameter.delay_unit)
42
+ return;
43
+ let key = this.key(key_parameter);
44
+ yield this._set(key, new Date(), false);
45
+ yield this.locker.unlock(key_parameter);
46
+ });
47
+ }
48
+ }
49
+ exports.RedisScopeDelay = RedisScopeDelay;
50
+ ;
51
+ //# sourceMappingURL=RedisScopeDelay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisScopeDelay.js","sourceRoot":"","sources":["../src/RedisScopeDelay.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAkE;AAElE,6CAA0C;AAW1C,MAAsB,eAA4B,SAAQ,uBAAgB;IAGtE,YAAY,QAAuB,EAAE,MAAkC;QAEnE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAEK,IAAI,CAAC,aAAyB,EAAE,SAAmC;;YAErE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,UAAU;gBACnE,OAAO;YAEX,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAElC,IAAI,eAAe,GAAG,mCAAiB,CAAC,cAAc,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;YACpG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;YAEhF,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC1C,IAAI,CAAC,OAAO;gBACR,OAAO;YAEX,IAAI,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAC1D,IAAI,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;YAC/D,IAAI,cAAc,GAAG,CAAC;gBAClB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAC1E,CAAC;KAAA;IACK,OAAO,CAAC,aAAyB,EAAE,SAAmC;;YAExE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,UAAU;gBACnE,OAAO;YAEX,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAClC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YACxC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC5C,CAAC;KAAA;CACJ;AAxCD,0CAwCC;AAAA,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { DurationUnit } from "namirasoft-core";
2
+ import { RedisInstance } from "./RedisInstance";
3
+ import { RedisScope } from "./RedisScope";
4
+ export type RedisScopeLimitParameter = {
5
+ id: string;
6
+ name: string;
7
+ limit: boolean;
8
+ limit_count: number | null;
9
+ limit_per_value: number | null;
10
+ limit_per_unit: DurationUnit | null;
11
+ };
12
+ export declare abstract class RedisScopeLimit<Parameters> extends RedisScope<number> {
13
+ constructor(instance: RedisInstance);
14
+ protected abstract key(key_parameter: Parameters): string;
15
+ getCount(key_parameter: Parameters, limit_per_value: number, limit_per_unit: DurationUnit): Promise<number>;
16
+ add(key_parameter: Parameters, limit_per_value: number, limit_per_unit: DurationUnit): Promise<void>;
17
+ del(key_parameter: Parameters): Promise<void>;
18
+ check(key_parameter: Parameters, parameter: RedisScopeLimitParameter): Promise<void>;
19
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RedisScopeLimit = void 0;
13
+ const namirasoft_core_1 = require("namirasoft-core");
14
+ const RedisScope_1 = require("./RedisScope");
15
+ class RedisScopeLimit extends RedisScope_1.RedisScope {
16
+ constructor(instance) {
17
+ super(instance);
18
+ this.key = this.key.bind(this);
19
+ this.getCount = this.getCount.bind(this);
20
+ this.add = this.add.bind(this);
21
+ this.del = this.del.bind(this);
22
+ }
23
+ getCount(key_parameter, limit_per_value, limit_per_unit) {
24
+ return __awaiter(this, void 0, void 0, function* () {
25
+ let key = this.key(key_parameter);
26
+ let milliseconds = namirasoft_core_1.TimeUnitOperation.toMilliseconds(limit_per_value, limit_per_unit);
27
+ let date_finish = new Date();
28
+ let date_start = namirasoft_core_1.TimeOperation.millisecondsAgo(milliseconds, date_finish);
29
+ return yield this.instance.client.zcount(key, date_start.getTime(), date_finish.getTime());
30
+ });
31
+ }
32
+ add(key_parameter, limit_per_value, limit_per_unit) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ let key = this.key(key_parameter);
35
+ let milliseconds = namirasoft_core_1.TimeUnitOperation.toMilliseconds(limit_per_value, limit_per_unit);
36
+ let date_finish = new Date();
37
+ let date_start = namirasoft_core_1.TimeOperation.millisecondsAgo(milliseconds, date_finish);
38
+ yield this.instance.client.zadd(key, date_finish.getTime(), date_finish.getTime());
39
+ yield this.instance.client.zremrangebyscore(key, 0, date_start.getTime());
40
+ });
41
+ }
42
+ del(key_parameter) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ let key = this.key(key_parameter);
45
+ yield this._del(key);
46
+ });
47
+ }
48
+ check(key_parameter, parameter) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ if (parameter.limit)
51
+ if (parameter.limit_count && parameter.limit_per_value && parameter.limit_per_unit) {
52
+ let count = yield this.getCount(key_parameter, parameter.limit_per_value, parameter.limit_per_unit);
53
+ if (count < parameter.limit_count)
54
+ yield this.add(key_parameter, parameter.limit_per_value, parameter.limit_per_unit);
55
+ else
56
+ throw new Error(`Limit has reached for '${parameter.name}' '${parameter.id}' for ${parameter.limit_count} messages every ${parameter.limit_per_value} ${parameter.limit_per_unit}`);
57
+ }
58
+ });
59
+ }
60
+ }
61
+ exports.RedisScopeLimit = RedisScopeLimit;
62
+ ;
63
+ //# sourceMappingURL=RedisScopeLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisScopeLimit.js","sourceRoot":"","sources":["../src/RedisScopeLimit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { RedisInstance } from "./RedisInstance";
2
+ import { RedisScope } from "./RedisScope";
3
+ export declare abstract class RedisScopeLock<Parameters> extends RedisScope<number> {
4
+ constructor(instance: RedisInstance);
5
+ protected abstract key(key_parameter: Parameters): string;
6
+ lock(key_parameter: Parameters, ttl_seconds: number): Promise<boolean>;
7
+ waitForLock(key_parameter: Parameters, ttl_seconds: number): Promise<void>;
8
+ unlock(key_parameter: Parameters): Promise<void>;
9
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RedisScopeLock = void 0;
13
+ const RedisScope_1 = require("./RedisScope");
14
+ class RedisScopeLock extends RedisScope_1.RedisScope {
15
+ constructor(instance) {
16
+ super(instance);
17
+ this.lock = this.lock.bind(this);
18
+ this.unlock = this.unlock.bind(this);
19
+ }
20
+ lock(key_parameter, ttl_seconds) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ let ans = yield this._set(this.key(key_parameter), Math.random(), true, ttl_seconds);
23
+ if (ans)
24
+ return true;
25
+ return false;
26
+ });
27
+ }
28
+ waitForLock(key_parameter, ttl_seconds) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ while (true) {
31
+ let ans = yield this._set(this.key(key_parameter), Math.random(), true, ttl_seconds);
32
+ if (ans)
33
+ break;
34
+ yield new Promise(res => setTimeout(res, 10));
35
+ }
36
+ });
37
+ }
38
+ unlock(key_parameter) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ yield this._del(this.key(key_parameter));
41
+ });
42
+ }
43
+ }
44
+ exports.RedisScopeLock = RedisScopeLock;
45
+ ;
46
+ //# sourceMappingURL=RedisScopeLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisScopeLock.js","sourceRoot":"","sources":["../src/RedisScopeLock.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,6CAA0C;AAE1C,MAAsB,cAA2B,SAAQ,uBAAkB;IAEvE,YAAY,QAAuB;QAE/B,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAEK,IAAI,CAAC,aAAyB,EAAE,WAAmB;;YAErD,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;YACrF,IAAI,GAAG;gBACH,OAAO,IAAI,CAAC;YAChB,OAAO,KAAK,CAAC;QACjB,CAAC;KAAA;IACK,WAAW,CAAC,aAAyB,EAAE,WAAmB;;YAE5D,OAAO,IAAI,EACX,CAAC;gBACG,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;gBACrF,IAAI,GAAG;oBACH,MAAM;gBACV,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YAClD,CAAC;QACL,CAAC;KAAA;IACK,MAAM,CAAC,aAAyB;;YAElC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;QAC7C,CAAC;KAAA;CACJ;AA9BD,wCA8BC;AAAA,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from "./RedisInstance";
2
2
  export * from "./RedisScope";
3
+ export * from "./RedisScopeDelay";
4
+ export * from "./RedisScopeLimit";
5
+ export * from "./RedisScopeLock";
package/dist/index.js CHANGED
@@ -16,4 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./RedisInstance"), exports);
18
18
  __exportStar(require("./RedisScope"), exports);
19
+ __exportStar(require("./RedisScopeDelay"), exports);
20
+ __exportStar(require("./RedisScopeLimit"), exports);
21
+ __exportStar(require("./RedisScopeLock"), exports);
19
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,+CAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,+CAA6B;AAC7B,oDAAkC;AAClC,oDAAkC;AAClC,mDAAiC"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "framework": "npm",
9
9
  "application": "package",
10
10
  "private": false,
11
- "version": "1.4.5",
11
+ "version": "1.4.7",
12
12
  "author": "Amir Abolhasani",
13
13
  "license": "MIT",
14
14
  "main": "./dist/index.js",
@@ -17,9 +17,9 @@
17
17
  "build": ""
18
18
  },
19
19
  "dependencies": {
20
- "@types/node": "^22.15.3",
20
+ "@types/node": "^22.15.18",
21
21
  "ioredis": "^5.6.1",
22
- "namirasoft-core": "^1.4.72",
22
+ "namirasoft-core": "^1.4.74",
23
23
  "namirasoft-log": "^1.4.29"
24
24
  }
25
25
  }
package/src/RedisScope.ts CHANGED
@@ -3,7 +3,7 @@ import { RedisInstance } from "./RedisInstance";
3
3
 
4
4
  export abstract class RedisScope<V>
5
5
  {
6
- private instance: RedisInstance;
6
+ protected instance: RedisInstance;
7
7
  constructor(instance: RedisInstance)
8
8
  {
9
9
  this.instance = instance;
@@ -0,0 +1,54 @@
1
+ import { DurationUnit, TimeUnitOperation } from "namirasoft-core";
2
+ import { RedisInstance } from "./RedisInstance";
3
+ import { RedisScope } from "./RedisScope";
4
+ import { RedisScopeLock } from "./RedisScopeLock";
5
+
6
+ export type RedisScopeDelayParameter = {
7
+ id: string;
8
+ name: string;
9
+ delay: boolean;
10
+ delay_value: number | null;
11
+ delay_unit: DurationUnit | null;
12
+ };
13
+
14
+ export abstract class RedisScopeDelay<Parameters> extends RedisScope<Date>
15
+ {
16
+ private locker: RedisScopeLock<Parameters>;
17
+ constructor(instance: RedisInstance, locker: RedisScopeLock<Parameters>)
18
+ {
19
+ super(instance);
20
+ this.locker = locker;
21
+ this.key = this.key.bind(this);
22
+ this.wait = this.wait.bind(this);
23
+ this.release = this.release.bind(this);
24
+ }
25
+ protected abstract key(key_parameter: Parameters): string;
26
+ async wait(key_parameter: Parameters, parameter: RedisScopeDelayParameter): Promise<void>
27
+ {
28
+ if (!parameter.delay || !parameter.delay_value || !parameter.delay_unit)
29
+ return;
30
+
31
+ let key = this.key(key_parameter);
32
+
33
+ let delay_requested = TimeUnitOperation.toMilliseconds(parameter.delay_value, parameter.delay_unit);
34
+ await this.locker.waitForLock(key_parameter, Math.ceil(delay_requested / 1000));
35
+
36
+ let LastRun = await this._get(key, false);
37
+ if (!LastRun)
38
+ return;
39
+
40
+ let difference = new Date().getTime() - LastRun.getTime();
41
+ let delay_required = Math.max(delay_requested - difference, 0);
42
+ if (delay_required > 0)
43
+ await new Promise(resolve => setTimeout(resolve, delay_required));
44
+ }
45
+ async release(key_parameter: Parameters, parameter: RedisScopeDelayParameter)
46
+ {
47
+ if (!parameter.delay || !parameter.delay_value || !parameter.delay_unit)
48
+ return;
49
+
50
+ let key = this.key(key_parameter);
51
+ await this._set(key, new Date(), false);
52
+ await this.locker.unlock(key_parameter);
53
+ }
54
+ };
@@ -0,0 +1,63 @@
1
+ import { DurationUnit, TimeOperation, TimeUnitOperation } from "namirasoft-core";
2
+ import { RedisInstance } from "./RedisInstance";
3
+ import { RedisScope } from "./RedisScope";
4
+
5
+ export type RedisScopeLimitParameter = {
6
+ id: string;
7
+ name: string;
8
+ limit: boolean;
9
+ limit_count: number | null;
10
+ limit_per_value: number | null;
11
+ limit_per_unit: DurationUnit | null;
12
+ };
13
+
14
+ export abstract class RedisScopeLimit<Parameters> extends RedisScope<number>
15
+ {
16
+ constructor(instance: RedisInstance)
17
+ {
18
+ super(instance);
19
+ this.key = this.key.bind(this);
20
+ this.getCount = this.getCount.bind(this);
21
+ this.add = this.add.bind(this);
22
+ this.del = this.del.bind(this);
23
+ }
24
+ protected abstract key(key_parameter: Parameters): string;
25
+ async getCount(key_parameter: Parameters, limit_per_value: number, limit_per_unit: DurationUnit): Promise<number>
26
+ {
27
+ let key = this.key(key_parameter);
28
+
29
+ let milliseconds = TimeUnitOperation.toMilliseconds(limit_per_value, limit_per_unit);
30
+ let date_finish = new Date();
31
+ let date_start = TimeOperation.millisecondsAgo(milliseconds, date_finish);
32
+
33
+ return await this.instance.client.zcount(key, date_start.getTime(), date_finish.getTime());
34
+ }
35
+ async add(key_parameter: Parameters, limit_per_value: number, limit_per_unit: DurationUnit)
36
+ {
37
+ let key = this.key(key_parameter);
38
+
39
+ let milliseconds = TimeUnitOperation.toMilliseconds(limit_per_value, limit_per_unit);
40
+ let date_finish = new Date();
41
+ let date_start = TimeOperation.millisecondsAgo(milliseconds, date_finish)
42
+
43
+ await this.instance.client.zadd(key, date_finish.getTime(), date_finish.getTime());
44
+ await this.instance.client.zremrangebyscore(key, 0, date_start.getTime());
45
+ }
46
+ async del(key_parameter: Parameters)
47
+ {
48
+ let key = this.key(key_parameter);
49
+ await this._del(key);
50
+ }
51
+ async check(key_parameter: Parameters, parameter: RedisScopeLimitParameter)
52
+ {
53
+ if (parameter.limit)
54
+ if (parameter.limit_count && parameter.limit_per_value && parameter.limit_per_unit)
55
+ {
56
+ let count = await this.getCount(key_parameter, parameter.limit_per_value, parameter.limit_per_unit);
57
+ if (count < parameter.limit_count)
58
+ await this.add(key_parameter, parameter.limit_per_value, parameter.limit_per_unit);
59
+ else
60
+ throw new Error(`Limit has reached for '${parameter.name}' '${parameter.id}' for ${parameter.limit_count} messages every ${parameter.limit_per_value} ${parameter.limit_per_unit}`);
61
+ }
62
+ }
63
+ };
@@ -0,0 +1,34 @@
1
+ import { RedisInstance } from "./RedisInstance";
2
+ import { RedisScope } from "./RedisScope";
3
+
4
+ export abstract class RedisScopeLock<Parameters> extends RedisScope<number>
5
+ {
6
+ constructor(instance: RedisInstance)
7
+ {
8
+ super(instance);
9
+ this.lock = this.lock.bind(this);
10
+ this.unlock = this.unlock.bind(this);
11
+ }
12
+ protected abstract key(key_parameter: Parameters): string;
13
+ async lock(key_parameter: Parameters, ttl_seconds: number): Promise<boolean>
14
+ {
15
+ let ans = await this._set(this.key(key_parameter), Math.random(), true, ttl_seconds);
16
+ if (ans)
17
+ return true;
18
+ return false;
19
+ }
20
+ async waitForLock(key_parameter: Parameters, ttl_seconds: number): Promise<void>
21
+ {
22
+ while (true)
23
+ {
24
+ let ans = await this._set(this.key(key_parameter), Math.random(), true, ttl_seconds);
25
+ if (ans)
26
+ break;
27
+ await new Promise(res => setTimeout(res, 10));
28
+ }
29
+ }
30
+ async unlock(key_parameter: Parameters)
31
+ {
32
+ await this._del(this.key(key_parameter));
33
+ }
34
+ };
package/src/index.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from "./RedisInstance";
2
- export * from "./RedisScope";
2
+ export * from "./RedisScope";
3
+ export * from "./RedisScopeDelay";
4
+ export * from "./RedisScopeLimit";
5
+ export * from "./RedisScopeLock";