@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
|
|
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":"
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
(
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|