@dignetwork/dig-sdk 0.0.1-alpha.107 → 0.0.1-alpha.109

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.
@@ -2,9 +2,13 @@ export declare class StoreInfoCacheUpdater {
2
2
  private static instance;
3
3
  private storeCoinCache;
4
4
  private updateInterval;
5
+ private lockFilePath;
6
+ private releaseLock;
5
7
  private constructor();
6
8
  static initInstance(): StoreInfoCacheUpdater;
7
- private startCacheUpdater;
9
+ private scheduleNextUpdate;
10
+ private checkAndUpdateCache;
8
11
  private updateCache;
12
+ private setupExitHandlers;
9
13
  }
10
14
  //# sourceMappingURL=StoreInfoCacheUpdater.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StoreInfoCacheUpdater.d.ts","sourceRoot":"","sources":["../../src/blockchain/StoreInfoCacheUpdater.ts"],"names":[],"mappings":"AAMA,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAwB;IAC/C,OAAO,CAAC,cAAc,CAInB;IACH,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO;WAMO,YAAY,IAAI,qBAAqB;IAOnD,OAAO,CAAC,iBAAiB;YAIX,WAAW;CAsE1B"}
1
+ {"version":3,"file":"StoreInfoCacheUpdater.d.ts","sourceRoot":"","sources":["../../src/blockchain/StoreInfoCacheUpdater.ts"],"names":[],"mappings":"AAQA,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAwB;IAC/C,OAAO,CAAC,cAAc,CAInB;IACH,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAsC;IAEzD,OAAO;WAcO,YAAY,IAAI,qBAAqB;IAOnD,OAAO,CAAC,kBAAkB;YAIZ,mBAAmB;YAkBnB,WAAW;IA4FzB,OAAO,CAAC,iBAAiB;CAsB1B"}
@@ -1,16 +1,47 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.StoreInfoCacheUpdater = void 0;
4
- const timers_1 = require("timers");
5
27
  const FullNodePeer_1 = require("./FullNodePeer");
6
28
  const utils_1 = require("../utils");
7
29
  const DataStoreSerializer_1 = require("./DataStoreSerializer");
8
30
  const utils_2 = require("../utils");
31
+ const lockfile = __importStar(require("proper-lockfile"));
32
+ const path = __importStar(require("path"));
33
+ const utils_3 = require("../utils");
9
34
  class StoreInfoCacheUpdater {
10
35
  constructor(updateIntervalInMinutes = 5) {
36
+ this.releaseLock = null; // Holds the release function for cleanup
11
37
  this.storeCoinCache = new utils_1.FileCache(`stores`);
12
38
  this.updateInterval = updateIntervalInMinutes * 60 * 1000; // Convert minutes to milliseconds
13
- this.startCacheUpdater();
39
+ // Construct lock file path using the path module
40
+ this.lockFilePath = path.join(utils_3.DIG_FOLDER_PATH, 'store-info-cache.lock');
41
+ // Start the cache updater using setTimeout
42
+ this.scheduleNextUpdate();
43
+ // Set up process exit handlers for cleanup
44
+ this.setupExitHandlers();
14
45
  }
15
46
  static initInstance() {
16
47
  if (!StoreInfoCacheUpdater.instance) {
@@ -18,49 +49,110 @@ class StoreInfoCacheUpdater {
18
49
  }
19
50
  return StoreInfoCacheUpdater.instance;
20
51
  }
21
- startCacheUpdater() {
22
- (0, timers_1.setInterval)(() => this.updateCache(), this.updateInterval);
52
+ scheduleNextUpdate() {
53
+ setTimeout(() => this.checkAndUpdateCache(), this.updateInterval);
54
+ }
55
+ async checkAndUpdateCache() {
56
+ try {
57
+ const isLocked = await lockfile.check(this.lockFilePath, {
58
+ stale: this.updateInterval,
59
+ });
60
+ if (!isLocked) {
61
+ await this.updateCache();
62
+ }
63
+ // Else, lock is held; skip update without logging
64
+ }
65
+ catch (error) {
66
+ console.error("Error checking lockfile:", error);
67
+ }
68
+ finally {
69
+ // Schedule the next update regardless of whether we updated or not
70
+ this.scheduleNextUpdate();
71
+ }
23
72
  }
24
73
  async updateCache() {
25
74
  try {
26
- const storeIds = this.storeCoinCache.getCachedKeys();
27
- for (const storeId of storeIds) {
28
- try {
29
- const cachedInfo = this.storeCoinCache.get(storeId);
30
- if (!cachedInfo) {
31
- continue;
75
+ // Attempt to acquire the lock
76
+ const release = await lockfile.lock(this.lockFilePath, {
77
+ retries: {
78
+ retries: 0, // No retries since we already checked the lock
79
+ },
80
+ stale: this.updateInterval, // Lock expires after the update interval
81
+ });
82
+ // Store the release function for cleanup during process exit
83
+ this.releaseLock = release;
84
+ try {
85
+ const storeIds = this.storeCoinCache.getCachedKeys();
86
+ for (const storeId of storeIds) {
87
+ try {
88
+ const cachedInfo = this.storeCoinCache.get(storeId);
89
+ if (!cachedInfo) {
90
+ continue;
91
+ }
92
+ // Deserialize the cached store info
93
+ const { latestStore: serializedStore, latestHeight, latestHash } = cachedInfo;
94
+ const { latestStore: previousInfo } = DataStoreSerializer_1.DataStoreSerializer.deserialize({
95
+ latestStore: serializedStore,
96
+ latestHeight: latestHeight.toString(),
97
+ latestHash: latestHash,
98
+ });
99
+ // Wrap the connection with a timeout
100
+ const peer = await (0, utils_2.withTimeout)(FullNodePeer_1.FullNodePeer.connect(), 60000, "Timeout connecting to FullNodePeer");
101
+ // Wrap the syncStore call with a timeout
102
+ const { latestStore, latestHeight: newHeight } = await (0, utils_2.withTimeout)(peer.syncStore(previousInfo, latestHeight, Buffer.from(latestHash, "hex"), false), 60000, `Timeout syncing store for storeId ${storeId}`);
103
+ // Wrap the getHeaderHash call with a timeout
104
+ const latestHashBuffer = await (0, utils_2.withTimeout)(peer.getHeaderHash(newHeight), 60000, `Timeout getting header hash for height ${newHeight}`);
105
+ // Serialize the updated store data for caching
106
+ const serializedLatestStore = new DataStoreSerializer_1.DataStoreSerializer(latestStore, newHeight, latestHashBuffer).serialize();
107
+ // Recache the updated store info
108
+ this.storeCoinCache.set(storeId, {
109
+ latestStore: serializedLatestStore,
110
+ latestHeight: newHeight,
111
+ latestHash: latestHashBuffer.toString("hex"),
112
+ });
113
+ }
114
+ catch (error) {
115
+ console.error(`Failed to update cache for storeId ${storeId}:`, error);
116
+ // Continue with the next storeId
32
117
  }
33
- // Deserialize the cached store info
34
- const { latestStore: serializedStore, latestHeight, latestHash } = cachedInfo;
35
- const { latestStore: previousInfo } = DataStoreSerializer_1.DataStoreSerializer.deserialize({
36
- latestStore: serializedStore,
37
- latestHeight: latestHeight.toString(),
38
- latestHash: latestHash,
39
- });
40
- // Wrap the connection with a timeout
41
- const peer = await (0, utils_2.withTimeout)(FullNodePeer_1.FullNodePeer.connect(), 60000, "Timeout connecting to FullNodePeer");
42
- // Wrap the syncStore call with a timeout
43
- const { latestStore, latestHeight: newHeight } = await (0, utils_2.withTimeout)(peer.syncStore(previousInfo, latestHeight, Buffer.from(latestHash, "hex"), false), 60000, `Timeout syncing store for storeId ${storeId}`);
44
- // Wrap the getHeaderHash call with a timeout
45
- const latestHashBuffer = await (0, utils_2.withTimeout)(peer.getHeaderHash(newHeight), 60000, `Timeout getting header hash for height ${newHeight}`);
46
- // Serialize the updated store data for caching
47
- const serializedLatestStore = new DataStoreSerializer_1.DataStoreSerializer(latestStore, newHeight, latestHashBuffer).serialize();
48
- // Recache the updated store info
49
- this.storeCoinCache.set(storeId, {
50
- latestStore: serializedLatestStore,
51
- latestHeight: newHeight,
52
- latestHash: latestHashBuffer.toString("hex"),
53
- });
54
- }
55
- catch (error) {
56
- console.error(`Failed to update cache for storeId ${storeId}:`, error);
57
- // Optionally handle specific errors or continue with the next storeId
58
118
  }
59
119
  }
120
+ finally {
121
+ // Always release the lock after finishing the update
122
+ await this.releaseLock?.();
123
+ this.releaseLock = null;
124
+ }
60
125
  }
61
126
  catch (error) {
62
- console.error("Failed to update store cache:", error);
127
+ if (error.code === 'ELOCKED') {
128
+ // Another process acquired the lock; skip without logging
129
+ }
130
+ else {
131
+ console.error("Failed to update store cache:", error);
132
+ }
63
133
  }
64
134
  }
135
+ setupExitHandlers() {
136
+ const cleanup = async () => {
137
+ if (this.releaseLock) {
138
+ try {
139
+ await this.releaseLock();
140
+ console.log("Lock released successfully on process exit.");
141
+ }
142
+ catch (error) {
143
+ console.error("Failed to release lock on exit:", error);
144
+ }
145
+ }
146
+ };
147
+ // Listen for process exit events and call cleanup
148
+ process.on('SIGINT', cleanup); // Catch CTRL+C
149
+ process.on('SIGTERM', cleanup); // Catch termination signals
150
+ process.on('exit', cleanup); // On normal exit
151
+ process.on('uncaughtException', async (error) => {
152
+ console.error("Uncaught exception, cleaning up:", error);
153
+ await cleanup();
154
+ process.exit(1); // Ensure process exits after handling exception
155
+ });
156
+ }
65
157
  }
66
158
  exports.StoreInfoCacheUpdater = StoreInfoCacheUpdater;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dignetwork/dig-sdk",
3
- "version": "0.0.1-alpha.107",
3
+ "version": "0.0.1-alpha.109",
4
4
  "description": "",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
@@ -46,6 +46,7 @@
46
46
  "nconf": "^0.12.1",
47
47
  "node-cache": "^5.1.2",
48
48
  "progress-stream": "^2.0.0",
49
+ "proper-lockfile": "^4.1.2",
49
50
  "superagent": "^10.0.0",
50
51
  "unzipper": "^0.12.3"
51
52
  },
@@ -61,6 +62,7 @@
61
62
  "@types/nconf": "^0.10.7",
62
63
  "@types/node": "^22.1.0",
63
64
  "@types/progress-stream": "^2.0.5",
65
+ "@types/proper-lockfile": "^4.1.4",
64
66
  "@types/superagent": "^8.1.8",
65
67
  "@types/unzipper": "^0.10.10",
66
68
  "chai": "^5.1.1",