namirasoft-core 1.5.4 → 1.5.5

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,13 +1,13 @@
1
- import { Mutex } from "async-mutex";
2
1
  import { IStorage } from "./IStorage";
3
2
  export declare class CacheService<DataType> {
3
+ private static pending;
4
+ private static fetcherSources;
4
5
  private name;
5
6
  private storage;
6
7
  private duration_minutes;
7
8
  private getVersion;
8
9
  private getFromSource;
9
10
  onExpired?: () => void;
10
- runGetOn?: Mutex;
11
11
  constructor(name: string, storage: IStorage, duration_minutes: number, getVersion: () => Promise<string>, getFromSource: () => Promise<DataType>);
12
12
  get(): Promise<DataType>;
13
13
  set(data: DataType, version?: string): Promise<void>;
@@ -12,6 +12,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.CacheService = void 0;
13
13
  class CacheService {
14
14
  constructor(name, storage, duration_minutes, getVersion, getFromSource) {
15
+ let source = getFromSource.toString();
16
+ let existing = CacheService.fetcherSources[name];
17
+ if (existing !== undefined && existing !== source)
18
+ throw new Error(`CacheService: name "${name}" was already registered with a different getFromSource. The name is a global dedup key — instances that share a name must share the same fetcher.`);
19
+ CacheService.fetcherSources[name] = source;
15
20
  this.name = name;
16
21
  this.storage = storage;
17
22
  this.duration_minutes = duration_minutes;
@@ -20,7 +25,9 @@ class CacheService {
20
25
  }
21
26
  get() {
22
27
  return __awaiter(this, void 0, void 0, function* () {
23
- let innerGet = () => __awaiter(this, void 0, void 0, function* () {
28
+ if (this.name in CacheService.pending)
29
+ return CacheService.pending[this.name];
30
+ let promise = (() => __awaiter(this, void 0, void 0, function* () {
24
31
  let version = yield this.getVersion();
25
32
  let value = this.storage.get(this.name, "");
26
33
  if (value) {
@@ -33,16 +40,16 @@ class CacheService {
33
40
  let ans = yield this.getFromSource();
34
41
  yield this.set(ans, version);
35
42
  return ans;
43
+ }))().finally(() => {
44
+ delete CacheService.pending[this.name];
36
45
  });
37
- if (this.runGetOn)
38
- return yield this.runGetOn.runExclusive(() => __awaiter(this, void 0, void 0, function* () {
39
- return yield innerGet();
40
- }));
41
- return yield innerGet();
46
+ CacheService.pending[this.name] = promise;
47
+ return promise;
42
48
  });
43
49
  }
44
50
  set(data, version) {
45
51
  return __awaiter(this, void 0, void 0, function* () {
52
+ delete CacheService.pending[this.name];
46
53
  if (!version)
47
54
  version = yield this.getVersion();
48
55
  let expires_at = new Date();
@@ -61,8 +68,11 @@ class CacheService {
61
68
  });
62
69
  }
63
70
  del() {
71
+ delete CacheService.pending[this.name];
64
72
  this.storage.del(this.name);
65
73
  }
66
74
  }
67
75
  exports.CacheService = CacheService;
76
+ CacheService.pending = {};
77
+ CacheService.fetcherSources = {};
68
78
  //# sourceMappingURL=CacheService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CacheService.js","sourceRoot":"","sources":["../src/CacheService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAUA,MAAa,YAAY;IASrB,YAAY,IAAY,EAAE,OAAiB,EAAE,gBAAwB,EAAE,UAAiC,EAAE,aAAsC;QAE5I,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACvC,CAAC;IACK,GAAG;;YAEL,IAAI,QAAQ,GAAG,GAAS,EAAE;gBAEtB,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;gBACtC,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC5C,IAAI,KAAK,EACT,CAAC;oBACG,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAA2B,CAAC;oBACxD,IAAI,KAAK,CAAC,OAAO,IAAI,OAAO;wBACxB,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE;4BACvC,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI;gCAClB,OAAO,KAAK,CAAC,IAAI,CAAC;gBAClC,CAAC;gBACD,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;gBACrC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBAC7B,OAAO,GAAG,CAAC;YACf,CAAC,CAAA,CAAC;YACF,IAAI,IAAI,CAAC,QAAQ;gBACb,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAS,EAAE;oBAE/C,OAAO,MAAM,QAAQ,EAAE,CAAC;gBAC5B,CAAC,CAAA,CAAC,CAAC;YACP,OAAO,MAAM,QAAQ,EAAE,CAAC;QAC5B,CAAC;KAAA;IACK,GAAG,CAAC,IAAc,EAAE,OAAgB;;YAEtC,IAAI,CAAC,OAAO;gBACR,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACtC,IAAI,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;YAC5B,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACvE,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,SAAS,EAClB,CAAC;gBACG,IAAI,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;gBACxD,IAAI,KAAK,IAAI,CAAC;oBACV,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;gBACrB,UAAU,CAAC,GAAG,EAAE;;oBAEZ,MAAA,IAAI,CAAC,SAAS,oDAAI,CAAC;gBACvB,CAAC,EAAE,KAAK,CAAC,CAAC;YACd,CAAC;QACL,CAAC;KAAA;IACD,GAAG;QAEC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;CACJ;AAlED,oCAkEC"}
1
+ {"version":3,"file":"CacheService.js","sourceRoot":"","sources":["../src/CacheService.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "framework": "npm",
9
9
  "application": "package",
10
10
  "private": false,
11
- "version": "1.5.4",
11
+ "version": "1.5.5",
12
12
  "author": "Amir Abolhasani",
13
13
  "license": "MIT",
14
14
  "main": "./dist/index.js",
@@ -17,8 +17,7 @@
17
17
  "build": ""
18
18
  },
19
19
  "dependencies": {
20
- "@types/node": "^26.1.0",
21
- "async-mutex": "^0.5.0",
20
+ "@types/node": "^26.1.1",
22
21
  "axios": "^1.18.1",
23
22
  "moment": "^2.30.1",
24
23
  "phone": "^3.1.71",
@@ -1,4 +1,3 @@
1
- import { Mutex } from "async-mutex";
2
1
  import { IStorage } from "./IStorage";
3
2
 
4
3
  interface CacheStorage<DataType>
@@ -10,15 +9,23 @@ interface CacheStorage<DataType>
10
9
 
11
10
  export class CacheService<DataType>
12
11
  {
12
+ private static pending: { [name: string]: Promise<any> } = {};
13
+ private static fetcherSources: { [name: string]: string } = {};
14
+
13
15
  private name: string;
14
16
  private storage: IStorage;
15
17
  private duration_minutes: number;
16
18
  private getVersion: () => Promise<string>;
17
19
  private getFromSource: () => Promise<DataType>;
18
20
  public onExpired?: () => void;
19
- public runGetOn?: Mutex;
20
21
  constructor(name: string, storage: IStorage, duration_minutes: number, getVersion: () => Promise<string>, getFromSource: () => Promise<DataType>)
21
22
  {
23
+ let source = getFromSource.toString();
24
+ let existing = CacheService.fetcherSources[name];
25
+ if (existing !== undefined && existing !== source)
26
+ throw new Error(`CacheService: name "${name}" was already registered with a different getFromSource. The name is a global dedup key — instances that share a name must share the same fetcher.`);
27
+ CacheService.fetcherSources[name] = source;
28
+
22
29
  this.name = name;
23
30
  this.storage = storage;
24
31
  this.duration_minutes = duration_minutes;
@@ -27,7 +34,10 @@ export class CacheService<DataType>
27
34
  }
28
35
  async get(): Promise<DataType>
29
36
  {
30
- let innerGet = async () =>
37
+ if (this.name in CacheService.pending)
38
+ return CacheService.pending[this.name] as Promise<DataType>;
39
+
40
+ let promise = (async (): Promise<DataType> =>
31
41
  {
32
42
  let version = await this.getVersion();
33
43
  let value = this.storage.get(this.name, "");
@@ -42,16 +52,18 @@ export class CacheService<DataType>
42
52
  let ans = await this.getFromSource();
43
53
  await this.set(ans, version);
44
54
  return ans;
45
- };
46
- if (this.runGetOn)
47
- return await this.runGetOn.runExclusive(async () =>
48
- {
49
- return await innerGet();
50
- });
51
- return await innerGet();
55
+ })().finally(() =>
56
+ {
57
+ delete CacheService.pending[this.name];
58
+ }) as Promise<DataType>;
59
+
60
+ CacheService.pending[this.name] = promise;
61
+ return promise;
52
62
  }
53
63
  async set(data: DataType, version?: string)
54
64
  {
65
+ delete CacheService.pending[this.name];
66
+
55
67
  if (!version)
56
68
  version = await this.getVersion();
57
69
  let expires_at = new Date();
@@ -72,6 +84,7 @@ export class CacheService<DataType>
72
84
  }
73
85
  del()
74
86
  {
87
+ delete CacheService.pending[this.name];
75
88
  this.storage.del(this.name);
76
89
  }
77
90
  }