@activeledger/activenetwork 2.15.6 → 4.3.3
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/es/network/cpus.d.ts +1 -0
- package/es/network/cpus.d.ts.map +1 -1
- package/es/network/cpus.js +26 -15
- package/es/network/cpus.js.map +1 -1
- package/es/network/endpoints.d.ts +7 -3
- package/es/network/endpoints.d.ts.map +1 -1
- package/es/network/endpoints.js +685 -172
- package/es/network/endpoints.js.map +1 -1
- package/es/network/home.d.ts.map +1 -1
- package/es/network/home.js +41 -19
- package/es/network/home.js.map +1 -1
- package/es/network/host.d.ts +15 -7
- package/es/network/host.d.ts.map +1 -1
- package/es/network/host.js +631 -240
- package/es/network/host.js.map +1 -1
- package/es/network/locker.d.ts +10 -5
- package/es/network/locker.d.ts.map +1 -1
- package/es/network/locker.js +50 -17
- package/es/network/locker.js.map +1 -1
- package/es/network/maintain.d.ts.map +1 -1
- package/es/network/maintain.js +42 -42
- package/es/network/maintain.js.map +1 -1
- package/es/network/neighbour.d.ts +8 -4
- package/es/network/neighbour.d.ts.map +1 -1
- package/es/network/neighbour.js +82 -18
- package/es/network/neighbour.js.map +1 -1
- package/es/network/neighbourhood.d.ts +1 -1
- package/es/network/neighbourhood.d.ts.map +1 -1
- package/es/network/neighbourhood.js +39 -42
- package/es/network/neighbourhood.js.map +1 -1
- package/es/network/p2pClient.d.ts +20 -0
- package/es/network/p2pClient.d.ts.map +1 -0
- package/es/network/p2pClient.js +84 -0
- package/es/network/p2pClient.js.map +1 -0
- package/es/network/process.js +99 -65
- package/es/network/process.js.map +1 -1
- package/es/network/utils.d.ts.map +1 -1
- package/es/network/utils.js +17 -21
- package/es/network/utils.js.map +1 -1
- package/lib/network/cpus.d.ts +1 -0
- package/lib/network/cpus.d.ts.map +1 -1
- package/lib/network/cpus.js +26 -15
- package/lib/network/cpus.js.map +1 -1
- package/lib/network/endpoints.d.ts +7 -3
- package/lib/network/endpoints.d.ts.map +1 -1
- package/lib/network/endpoints.js +684 -171
- package/lib/network/endpoints.js.map +1 -1
- package/lib/network/home.d.ts.map +1 -1
- package/lib/network/home.js +41 -19
- package/lib/network/home.js.map +1 -1
- package/lib/network/host.d.ts +15 -7
- package/lib/network/host.d.ts.map +1 -1
- package/lib/network/host.js +630 -239
- package/lib/network/host.js.map +1 -1
- package/lib/network/locker.d.ts +10 -5
- package/lib/network/locker.d.ts.map +1 -1
- package/lib/network/locker.js +50 -17
- package/lib/network/locker.js.map +1 -1
- package/lib/network/maintain.d.ts.map +1 -1
- package/lib/network/maintain.js +42 -42
- package/lib/network/maintain.js.map +1 -1
- package/lib/network/neighbour.d.ts +8 -4
- package/lib/network/neighbour.d.ts.map +1 -1
- package/lib/network/neighbour.js +82 -18
- package/lib/network/neighbour.js.map +1 -1
- package/lib/network/neighbourhood.d.ts +1 -1
- package/lib/network/neighbourhood.d.ts.map +1 -1
- package/lib/network/neighbourhood.js +39 -42
- package/lib/network/neighbourhood.js.map +1 -1
- package/lib/network/p2pClient.d.ts +20 -0
- package/lib/network/p2pClient.d.ts.map +1 -0
- package/lib/network/p2pClient.js +88 -0
- package/lib/network/p2pClient.js.map +1 -0
- package/lib/network/process.js +98 -64
- package/lib/network/process.js.map +1 -1
- package/lib/network/utils.d.ts.map +1 -1
- package/lib/network/utils.js +17 -21
- package/lib/network/utils.js.map +1 -1
- package/package.json +10 -8
package/lib/network/host.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Host = void 0;
|
|
4
|
-
const http_1 = require("http");
|
|
5
4
|
const child_process_1 = require("child_process");
|
|
6
5
|
const fs_1 = require("fs");
|
|
7
6
|
const path_1 = require("path");
|
|
7
|
+
const net = require("net");
|
|
8
8
|
const activeoptions_1 = require("@activeledger/activeoptions");
|
|
9
9
|
const activecrypto_1 = require("@activeledger/activecrypto");
|
|
10
10
|
const activelogger_1 = require("@activeledger/activelogger");
|
|
@@ -15,80 +15,72 @@ const index_1 = require("./index");
|
|
|
15
15
|
const locker_1 = require("./locker");
|
|
16
16
|
const cpus_1 = require("./cpus");
|
|
17
17
|
const process = require("process");
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
18
|
+
const uWebSockets_js_1 = require("uWebSockets.js");
|
|
19
|
+
const RELEASE_SHUTDOWN_TIMEOUT = 1 * 60 * 1000;
|
|
20
|
+
const RELEASE_DELETE_TIMEOUT = 2 * 60 * 1000;
|
|
21
|
+
const TIMER_QUEUE_INTERVAL = 2 * 1000;
|
|
21
22
|
const GRACEFUL_PROC_SHUTDOWN = 7 * 60 * 1000;
|
|
22
23
|
const KILL_PROC_SHUTDOWN = 2.5 * 1000;
|
|
24
|
+
const MAX_RETRIES = 35;
|
|
25
|
+
function peekBytes(chunks, n) {
|
|
26
|
+
if (chunks.length > 0 && chunks[0].length >= n) {
|
|
27
|
+
return chunks[0];
|
|
28
|
+
}
|
|
29
|
+
let total = 0;
|
|
30
|
+
let end = 0;
|
|
31
|
+
while (end < chunks.length && total < n) {
|
|
32
|
+
total += chunks[end].length;
|
|
33
|
+
end++;
|
|
34
|
+
}
|
|
35
|
+
return Buffer.concat(chunks.slice(0, end));
|
|
36
|
+
}
|
|
23
37
|
class Host extends home_1.Home {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
p2pServer;
|
|
39
|
+
listenSocket;
|
|
40
|
+
api;
|
|
41
|
+
dbConnection;
|
|
42
|
+
dbErrorConnection;
|
|
43
|
+
dbEventConnection;
|
|
44
|
+
processPending = {};
|
|
45
|
+
cpuReady = 0;
|
|
46
|
+
hybridHosts;
|
|
47
|
+
busyLocksQueue = { internal: [], external: [] };
|
|
48
|
+
shutdown() {
|
|
49
|
+
if (this.listenSocket) {
|
|
50
|
+
(0, uWebSockets_js_1.us_listen_socket_close)(this.listenSocket);
|
|
51
|
+
this.listenSocket = null;
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
activelogger_1.ActiveLogger.info("Stopping HTTP Server");
|
|
54
|
+
this.api.close();
|
|
55
|
+
activelogger_1.ActiveLogger.info("Shutting down...");
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}, 1300);
|
|
42
58
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
(data[0] == 0x1f && data[1] == 0x8b)) {
|
|
54
|
-
try {
|
|
55
|
-
data = await activeoptions_1.ActiveGZip.ungzip(data);
|
|
56
|
-
}
|
|
57
|
-
catch (_a) {
|
|
59
|
+
}
|
|
60
|
+
pending(entry, remoteAddr, internal = false, forceRestart = false, isP2P = false) {
|
|
61
|
+
return new Promise(async (resolve, reject) => {
|
|
62
|
+
if (entry.$broadcast && entry.$nodes) {
|
|
63
|
+
const nodeSpoofCheck = Object.keys(entry.$nodes);
|
|
64
|
+
if (nodeSpoofCheck.length) {
|
|
65
|
+
for (let i = nodeSpoofCheck.length; i--;) {
|
|
66
|
+
const nodeCheck = nodeSpoofCheck[i];
|
|
67
|
+
if (!this.neighbourhood.checkFirewall(remoteAddr, nodeCheck)) {
|
|
68
|
+
return reject("Bad Neighbour Payload");
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
|
-
|
|
61
|
-
false)
|
|
62
|
-
.then((body) => {
|
|
63
|
-
this.processEndpoints(req, res, body.body, body.from);
|
|
64
|
-
})
|
|
65
|
-
.catch((error) => {
|
|
66
|
-
this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || {}), req.headers["accept-encoding"]);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
71
|
+
}
|
|
69
72
|
}
|
|
70
|
-
|
|
71
|
-
this.
|
|
73
|
+
if (forceRestart && this.processPending[entry.$umid]) {
|
|
74
|
+
this.destroy(entry.$umid, true);
|
|
75
|
+
delete this.processPending[entry.$umid];
|
|
72
76
|
}
|
|
73
|
-
});
|
|
74
|
-
const cpuTotal = cpus_1.PhysicalCores.count();
|
|
75
|
-
const latestSetupMsg = this.getLatestSetup();
|
|
76
|
-
for (let i = 0; i < cpuTotal; i++) {
|
|
77
|
-
const processor = this.createProcessor(cpuTotal);
|
|
78
|
-
this.processors.push(processor);
|
|
79
|
-
processor.send(latestSetupMsg);
|
|
80
|
-
}
|
|
81
|
-
this.standbyProcess = this.createProcessor(cpuTotal);
|
|
82
|
-
this.standbyProcess.send(latestSetupMsg);
|
|
83
|
-
this.processorIterator = this.processors[Symbol.iterator]();
|
|
84
|
-
this.timerQueue();
|
|
85
|
-
}
|
|
86
|
-
pending(entry, internal = false) {
|
|
87
|
-
return new Promise((resolve, reject) => {
|
|
88
77
|
if (entry.$broadcast) {
|
|
89
78
|
if (this.processPending[entry.$umid]) {
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
if (!this.processPending[entry.$umid]?.finished &&
|
|
80
|
+
this.processPending[entry.$umid]?.pid &&
|
|
81
|
+
!this.processPending[entry.$umid]?.entry?.$nodes?.[this.reference]
|
|
82
|
+
?.leader) {
|
|
83
|
+
activelogger_1.ActiveLogger.debug(`Broadcast Recieved [${isP2P ? "P2P" : "HTTP"}] : ` + entry.$umid);
|
|
92
84
|
const processor = this.findProcessor(this.processPending[entry.$umid].pid);
|
|
93
85
|
if (processor) {
|
|
94
86
|
processor.send({
|
|
@@ -102,35 +94,327 @@ class Host extends home_1.Home {
|
|
|
102
94
|
else {
|
|
103
95
|
}
|
|
104
96
|
}
|
|
97
|
+
else {
|
|
98
|
+
const pendingEntry = this.processPending[entry.$umid]?.entry;
|
|
99
|
+
if (pendingEntry) {
|
|
100
|
+
delete entry.$nodes[this.reference];
|
|
101
|
+
pendingEntry.$nodes = { ...pendingEntry.$nodes, ...entry.$nodes };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!entry.$$noreply) {
|
|
105
|
+
this.broadcast(entry.$umid, false, true);
|
|
106
|
+
}
|
|
105
107
|
return resolve({
|
|
106
108
|
status: 200,
|
|
107
109
|
data: this.processPending[entry.$umid].entry,
|
|
110
|
+
dontRelease: true,
|
|
108
111
|
});
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
if (!this.processPending[entry.$umid]) {
|
|
112
115
|
this.processPending[entry.$umid] = {
|
|
113
|
-
entry
|
|
116
|
+
entry,
|
|
114
117
|
resolve: (response) => {
|
|
115
|
-
this.
|
|
116
|
-
|
|
118
|
+
if (internal && this.processPending[entry.$umid]?.responded) {
|
|
119
|
+
this.release(entry.$umid);
|
|
120
|
+
}
|
|
121
|
+
if (this.processPending[entry.$umid]) {
|
|
122
|
+
this.processPending[entry.$umid].finished = true;
|
|
123
|
+
}
|
|
124
|
+
if (!this.processPending[entry.$umid]?.responded) {
|
|
125
|
+
resolve(response);
|
|
126
|
+
try {
|
|
127
|
+
this.processPending[entry.$umid].responded = true;
|
|
128
|
+
activelogger_1.ActiveLogger.debug("Client Response TX : " + entry.$umid);
|
|
129
|
+
}
|
|
130
|
+
catch { }
|
|
131
|
+
}
|
|
117
132
|
},
|
|
118
133
|
reject: (response) => {
|
|
119
|
-
this.
|
|
120
|
-
|
|
134
|
+
if (this.processPending[entry.$umid]) {
|
|
135
|
+
this.processPending[entry.$umid].finished = true;
|
|
136
|
+
}
|
|
137
|
+
if (!this.processPending[entry.$umid]?.responded) {
|
|
138
|
+
reject(response);
|
|
139
|
+
try {
|
|
140
|
+
this.processPending[entry.$umid].responded = true;
|
|
141
|
+
}
|
|
142
|
+
catch { }
|
|
143
|
+
}
|
|
121
144
|
},
|
|
122
145
|
pid: 0,
|
|
146
|
+
finished: false,
|
|
147
|
+
responded: false,
|
|
123
148
|
};
|
|
149
|
+
if (entry.$tx.$expire && remoteAddr !== this.host) {
|
|
150
|
+
if (await this.dbConnection.exists(`${entry.$umid}:umid`)) {
|
|
151
|
+
if (entry.$nodes) {
|
|
152
|
+
entry.$nodes[this.reference] = {
|
|
153
|
+
vote: false,
|
|
154
|
+
commit: false,
|
|
155
|
+
error: `Transaction Exists : ${entry.$umid}`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
entry.$nodes = {
|
|
160
|
+
[this.reference]: {
|
|
161
|
+
vote: false,
|
|
162
|
+
commit: false,
|
|
163
|
+
error: `Transaction Exists : ${entry.$umid}`,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return this.processPending[entry.$umid].resolve({
|
|
168
|
+
status: 200,
|
|
169
|
+
data: entry,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
124
173
|
this.processQueue(entry, internal);
|
|
174
|
+
if (internal && entry.$broadcast) {
|
|
175
|
+
this.processPending[entry.$umid].responded = true;
|
|
176
|
+
return resolve({
|
|
177
|
+
status: 200,
|
|
178
|
+
data: { ok: true },
|
|
179
|
+
dontRelease: true,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
125
182
|
}
|
|
126
183
|
else {
|
|
127
184
|
return resolve({
|
|
128
185
|
status: 200,
|
|
129
186
|
data: this.processPending[entry.$umid].entry,
|
|
187
|
+
dontRelease: true,
|
|
130
188
|
});
|
|
131
189
|
}
|
|
132
190
|
});
|
|
133
191
|
}
|
|
192
|
+
constructor() {
|
|
193
|
+
super();
|
|
194
|
+
if (activeoptions_1.ActiveOptions.get("p2pStreamServer", false)) {
|
|
195
|
+
this.p2pServer = net.createServer((socket) => {
|
|
196
|
+
activelogger_1.ActiveLogger.info(`P2P TCP connection accepted from ${socket.remoteAddress}`);
|
|
197
|
+
let chunks = [];
|
|
198
|
+
let bufferLength = 0;
|
|
199
|
+
socket.on("data", async (data) => {
|
|
200
|
+
chunks.push(data);
|
|
201
|
+
bufferLength += data.length;
|
|
202
|
+
while (bufferLength >= 44) {
|
|
203
|
+
const header = peekBytes(chunks, 44);
|
|
204
|
+
const length = header.readUInt32BE(40);
|
|
205
|
+
if (bufferLength >= 44 + length) {
|
|
206
|
+
const fullBuffer = Buffer.concat(chunks);
|
|
207
|
+
const senderRef = fullBuffer.slice(0, 40).toString().trim();
|
|
208
|
+
const item = fullBuffer.slice(44, 44 + length);
|
|
209
|
+
const remaining = fullBuffer.slice(44 + length);
|
|
210
|
+
chunks = remaining.length > 0 ? [remaining] : [];
|
|
211
|
+
bufferLength = remaining.length;
|
|
212
|
+
const tx = await activeoptions_1.ActiveClone.deserialize(item);
|
|
213
|
+
this.processEndpoints({
|
|
214
|
+
headers: { "X-Activeledger": senderRef },
|
|
215
|
+
method: "POST",
|
|
216
|
+
url: "/a/init",
|
|
217
|
+
connection: { remoteAddress: socket.remoteAddress || "127.0.0.1" },
|
|
218
|
+
}, null, tx, senderRef, true);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
socket.on("error", (err) => {
|
|
226
|
+
activelogger_1.ActiveLogger.error(err, "P2P socket error");
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
const p2pPort = parseInt(utils_1.ActiveInterfaces.getBindingDetails("port")) + 1;
|
|
230
|
+
this.p2pServer.listen(p2pPort, () => {
|
|
231
|
+
activelogger_1.ActiveLogger.info(`P2P TCP server listening on port ${p2pPort}`);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
let db = activeoptions_1.ActiveOptions.get("db", {});
|
|
235
|
+
this.dbConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.database);
|
|
236
|
+
this.dbConnection.info();
|
|
237
|
+
this.dbErrorConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.error);
|
|
238
|
+
this.dbErrorConnection.info();
|
|
239
|
+
this.dbEventConnection = new activeoptions_1.ActiveDSConnect(db.url + "/" + db.event);
|
|
240
|
+
this.dbEventConnection.info();
|
|
241
|
+
this.hybridHosts = activeoptions_1.ActiveOptions.get("hybrid", []);
|
|
242
|
+
if (this.hybridHosts.length) {
|
|
243
|
+
for (let i = this.hybridHosts.length; i--;) {
|
|
244
|
+
const hybrid = this.hybridHosts[i];
|
|
245
|
+
hybrid.docName = activecrypto_1.ActiveCrypto.Hash.getHash(hybrid.url + hybrid.auth);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.api = (0, uWebSockets_js_1.App)();
|
|
249
|
+
this.api.any("/*", async (res, req) => {
|
|
250
|
+
res.onAborted(() => {
|
|
251
|
+
res.writable = false;
|
|
252
|
+
});
|
|
253
|
+
res.writable = true;
|
|
254
|
+
const headers = {
|
|
255
|
+
"Accept-Encoding": req.getHeader("accept-encoding"),
|
|
256
|
+
"X-Activeledger": req.getHeader("x-activeledger"),
|
|
257
|
+
"x-activeledger-encrypt": req.getHeader("x-activeledger-encrypt"),
|
|
258
|
+
"content-encoding": req.getHeader("content-encoding"),
|
|
259
|
+
"X-Bundle": req.getHeader("x-bundle"),
|
|
260
|
+
};
|
|
261
|
+
const method = req.getMethod().toUpperCase();
|
|
262
|
+
const url = req.getUrl();
|
|
263
|
+
let ipFrom = Buffer.from(res.getProxiedRemoteAddressAsText().byteLength
|
|
264
|
+
? res.getProxiedRemoteAddressAsText()
|
|
265
|
+
: res.getRemoteAddressAsText()).toString();
|
|
266
|
+
if (ipFrom.indexOf(":") !== -1) {
|
|
267
|
+
const ip6 = this.parseIp6(ipFrom);
|
|
268
|
+
ipFrom =
|
|
269
|
+
(ip6[6] >> 8) +
|
|
270
|
+
"." +
|
|
271
|
+
(ip6[6] & 0xff) +
|
|
272
|
+
"." +
|
|
273
|
+
(ip6[7] >> 8) +
|
|
274
|
+
"." +
|
|
275
|
+
(ip6[7] & 0xff);
|
|
276
|
+
}
|
|
277
|
+
if (method === "POST") {
|
|
278
|
+
let body = await this.readBuffer(res);
|
|
279
|
+
if (headers["content-encoding"] == "gzip" ||
|
|
280
|
+
(body[0] == 0x1f && body[1] == 0x8b)) {
|
|
281
|
+
try {
|
|
282
|
+
body = await activeoptions_1.ActiveGZip.ungzip(body);
|
|
283
|
+
}
|
|
284
|
+
catch (e) {
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const bodyString = (await this.makeSureNotBuffer(body));
|
|
288
|
+
let bundles;
|
|
289
|
+
if (headers["X-Bundle"]) {
|
|
290
|
+
bundles = bodyString.split(":$ALB:");
|
|
291
|
+
res.cork(() => {
|
|
292
|
+
res.writeStatus("200");
|
|
293
|
+
res.writeHeader("Content-Type", "application/json");
|
|
294
|
+
res.end("{}");
|
|
295
|
+
});
|
|
296
|
+
res.writable = false;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
bundles = [bodyString];
|
|
300
|
+
}
|
|
301
|
+
for (let i = bundles.length; i--;) {
|
|
302
|
+
if (bundles[i]) {
|
|
303
|
+
index_1.Endpoints.postConvertor(this, bundles[i], headers["x-activeledger-encrypt"] || false)
|
|
304
|
+
.then((body) => {
|
|
305
|
+
this.processEndpoints({
|
|
306
|
+
headers,
|
|
307
|
+
method,
|
|
308
|
+
url,
|
|
309
|
+
connection: {
|
|
310
|
+
remoteAddress: ipFrom,
|
|
311
|
+
},
|
|
312
|
+
}, res, body.body, body.from);
|
|
313
|
+
})
|
|
314
|
+
.catch((error) => {
|
|
315
|
+
activelogger_1.ActiveLogger.error(error, "Server POST Parser 500");
|
|
316
|
+
this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || { error: 1 }), headers["Accept-Encoding"]);
|
|
317
|
+
})
|
|
318
|
+
.finally(() => {
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
if (method === "OPTIONS") {
|
|
325
|
+
await this.writeResponse(res, 200, "{}", "", true);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
await this.processEndpoints({
|
|
329
|
+
headers,
|
|
330
|
+
method,
|
|
331
|
+
url,
|
|
332
|
+
connection: {
|
|
333
|
+
remoteAddress: ipFrom,
|
|
334
|
+
},
|
|
335
|
+
}, res);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
const cpuTotal = parseInt(activeoptions_1.ActiveOptions.get("cpus", "0")) || cpus_1.PhysicalCores.count();
|
|
340
|
+
const latestSetupMsg = this.getLatestSetup();
|
|
341
|
+
for (let i = 0; i < cpuTotal; i++) {
|
|
342
|
+
const processor = this.createProcessor(cpuTotal);
|
|
343
|
+
this.processors.push(processor);
|
|
344
|
+
processor.send(latestSetupMsg);
|
|
345
|
+
}
|
|
346
|
+
this.standbyProcess = this.createProcessor(cpuTotal);
|
|
347
|
+
this.standbyProcess.send(latestSetupMsg);
|
|
348
|
+
this.processorIterator = this.processors[Symbol.iterator]();
|
|
349
|
+
this.timerQueue();
|
|
350
|
+
}
|
|
351
|
+
readBuffer(res) {
|
|
352
|
+
return new Promise((resolve, reject) => {
|
|
353
|
+
const chunks = [];
|
|
354
|
+
res.onData((ab, isLast) => {
|
|
355
|
+
if (res.aborted) {
|
|
356
|
+
reject(new Error("Request aborted"));
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (ab.byteLength > 0) {
|
|
360
|
+
const buffer = Buffer.allocUnsafe(ab.byteLength);
|
|
361
|
+
buffer.set(new Uint8Array(ab));
|
|
362
|
+
chunks.push(buffer);
|
|
363
|
+
}
|
|
364
|
+
if (isLast) {
|
|
365
|
+
resolve(chunks.length === 0
|
|
366
|
+
? Buffer.alloc(0)
|
|
367
|
+
: chunks.length === 1
|
|
368
|
+
? chunks[0]
|
|
369
|
+
: Buffer.concat(chunks));
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
parseIp6(str) {
|
|
375
|
+
var ar = new Array();
|
|
376
|
+
for (var i = 0; i < 8; i++)
|
|
377
|
+
ar[i] = 0;
|
|
378
|
+
if (str == "::")
|
|
379
|
+
return ar;
|
|
380
|
+
var sar = str.split(":");
|
|
381
|
+
var slen = sar.length;
|
|
382
|
+
if (slen > 8)
|
|
383
|
+
slen = 8;
|
|
384
|
+
var j = 0;
|
|
385
|
+
for (var i = 0; i < slen; i++) {
|
|
386
|
+
if (i && sar[i] == "") {
|
|
387
|
+
j = 9 - slen + i;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
ar[j] = parseInt("0x0" + sar[i]);
|
|
391
|
+
j++;
|
|
392
|
+
}
|
|
393
|
+
return ar;
|
|
394
|
+
}
|
|
395
|
+
async makeSureNotBuffer(obj) {
|
|
396
|
+
if (obj.type === "Buffer" && obj.data?.length) {
|
|
397
|
+
if (obj.data[0] == 0x1f && obj.data[1] == 0x8b) {
|
|
398
|
+
return (await activeoptions_1.ActiveGZip.ungzip(Buffer.from(obj.data))).toString();
|
|
399
|
+
}
|
|
400
|
+
return Buffer.from(obj.data).toString();
|
|
401
|
+
}
|
|
402
|
+
if (Buffer.isBuffer(obj)) {
|
|
403
|
+
if (obj[0] == 0x1f && obj[1] == 0x8b) {
|
|
404
|
+
return (await activeoptions_1.ActiveGZip.ungzip(obj)).toString();
|
|
405
|
+
}
|
|
406
|
+
const tmp = obj.toString();
|
|
407
|
+
if (tmp.startsWith('{"type":"Buffer"')) {
|
|
408
|
+
const asBufferObj = JSON.parse(tmp);
|
|
409
|
+
if (asBufferObj.data[0] == 0x1f && asBufferObj.data[1] == 0x8b) {
|
|
410
|
+
return (await activeoptions_1.ActiveGZip.ungzip(Buffer.from(asBufferObj.data))).toString();
|
|
411
|
+
}
|
|
412
|
+
return Buffer.from(asBufferObj.data).toString();
|
|
413
|
+
}
|
|
414
|
+
return obj.toString();
|
|
415
|
+
}
|
|
416
|
+
return obj;
|
|
417
|
+
}
|
|
134
418
|
getLatestSetup() {
|
|
135
419
|
return {
|
|
136
420
|
type: "setup",
|
|
@@ -154,29 +438,33 @@ class Host extends home_1.Home {
|
|
|
154
438
|
pFork.stop = false;
|
|
155
439
|
let unloadHandled = false;
|
|
156
440
|
const unloadProcessorSafely = (...error) => {
|
|
157
|
-
if (unloadHandled) {
|
|
158
|
-
activelogger_1.ActiveLogger.fatal(error, "Processor Crashed - Already Shutting Down");
|
|
441
|
+
if (unloadHandled || !this.listenSocket) {
|
|
159
442
|
}
|
|
160
443
|
else {
|
|
161
444
|
pFork.stop = unloadHandled = true;
|
|
162
445
|
activelogger_1.ActiveLogger.fatal(error, "Processor Crashed");
|
|
163
446
|
this.processors.push(this.standbyProcess);
|
|
164
447
|
this.standbyProcess = this.createProcessor();
|
|
165
|
-
|
|
448
|
+
setTimeout(() => {
|
|
449
|
+
this.standbyProcess.send(this.getLatestSetup(), (e) => {
|
|
450
|
+
if (e) {
|
|
451
|
+
activelogger_1.ActiveLogger.fatal(e, "Issue with new Standby Process");
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
}, 1000);
|
|
166
455
|
activelogger_1.ActiveLogger.fatal(pFork, "Will Gracefully Shutdown in " + GRACEFUL_PROC_SHUTDOWN);
|
|
167
456
|
setTimeout(() => {
|
|
168
457
|
activelogger_1.ActiveLogger.fatal(pFork, "Starting Graceful Shutdown");
|
|
169
458
|
const pendings = Object.keys(this.processPending);
|
|
170
459
|
pendings.forEach((key) => {
|
|
171
460
|
let pending = this.processPending[key];
|
|
172
|
-
if (
|
|
461
|
+
if (pending?.pid === pFork.pid) {
|
|
173
462
|
pending.entry.$nodes[this.reference].error =
|
|
174
463
|
"(Contract Thread Error) Unknown - Try Again";
|
|
175
464
|
pending.resolve({
|
|
176
465
|
status: 200,
|
|
177
466
|
data: pending.entry,
|
|
178
467
|
});
|
|
179
|
-
this.release(pending);
|
|
180
468
|
}
|
|
181
469
|
});
|
|
182
470
|
activelogger_1.ActiveLogger.fatal(pFork, "Will Kill in " + KILL_PROC_SHUTDOWN);
|
|
@@ -194,10 +482,9 @@ class Host extends home_1.Home {
|
|
|
194
482
|
}
|
|
195
483
|
};
|
|
196
484
|
pFork.on("message", (m) => {
|
|
197
|
-
var _a;
|
|
198
485
|
const pending = this.processPending[m.data.umid];
|
|
199
486
|
if (pending) {
|
|
200
|
-
if (m.data.nodes) {
|
|
487
|
+
if (m.data.nodes && !m.data.early) {
|
|
201
488
|
pending.entry.$nodes = {
|
|
202
489
|
...pending.entry.$nodes,
|
|
203
490
|
...m.data.nodes,
|
|
@@ -216,12 +503,10 @@ class Host extends home_1.Home {
|
|
|
216
503
|
return;
|
|
217
504
|
pending.resolve({
|
|
218
505
|
status: 200,
|
|
219
|
-
data:
|
|
506
|
+
data: m.data.entry
|
|
507
|
+
? { ...pending.entry, ...m.data.entry }
|
|
508
|
+
: pending.entry,
|
|
220
509
|
});
|
|
221
|
-
this.release(pending);
|
|
222
|
-
if (m.data && this.hybridHosts.length) {
|
|
223
|
-
this.processHybridNodes(pending.entry);
|
|
224
|
-
}
|
|
225
510
|
break;
|
|
226
511
|
case "commited":
|
|
227
512
|
if (!pending)
|
|
@@ -230,9 +515,8 @@ class Host extends home_1.Home {
|
|
|
230
515
|
status: 200,
|
|
231
516
|
data: { ...pending.entry, ...m.data.entry },
|
|
232
517
|
});
|
|
233
|
-
this.release(pending);
|
|
234
518
|
if (this.hybridHosts.length) {
|
|
235
|
-
this.processHybridNodes(pending.entry,
|
|
519
|
+
this.processHybridNodes(pending.entry, m.data.entry?.$streams);
|
|
236
520
|
}
|
|
237
521
|
break;
|
|
238
522
|
case "broadcast":
|
|
@@ -244,8 +528,10 @@ class Host extends home_1.Home {
|
|
|
244
528
|
case "ready":
|
|
245
529
|
if (cpuTotal) {
|
|
246
530
|
this.cpuReady++;
|
|
247
|
-
if (!this.
|
|
248
|
-
this.
|
|
531
|
+
if (!this.listeing && this.cpuReady >= cpuTotal) {
|
|
532
|
+
this.listeing = true;
|
|
533
|
+
this.api.listen(utils_1.ActiveInterfaces.getBindingDetails("port"), (token) => {
|
|
534
|
+
this.listenSocket = token;
|
|
249
535
|
activelogger_1.ActiveLogger.info("Activeledger listening on port " +
|
|
250
536
|
utils_1.ActiveInterfaces.getBindingDetails("port"));
|
|
251
537
|
});
|
|
@@ -259,10 +545,12 @@ class Host extends home_1.Home {
|
|
|
259
545
|
status: 200,
|
|
260
546
|
data: { ...pending.entry, ...m.data.entry },
|
|
261
547
|
});
|
|
262
|
-
this.release(pending);
|
|
263
548
|
}
|
|
264
|
-
|
|
549
|
+
if (!m.data.recoverable) {
|
|
550
|
+
unloadProcessorSafely("unhandledrejection - Already Handled, Tidying up processes");
|
|
551
|
+
}
|
|
265
552
|
break;
|
|
553
|
+
case "contractData":
|
|
266
554
|
case "contractLatestVersion":
|
|
267
555
|
this.processors.forEach((processor) => {
|
|
268
556
|
processor.send(m);
|
|
@@ -279,6 +567,7 @@ class Host extends home_1.Home {
|
|
|
279
567
|
pFork.on("error", unloadProcessorSafely);
|
|
280
568
|
return pFork;
|
|
281
569
|
}
|
|
570
|
+
listeing = false;
|
|
282
571
|
reload() {
|
|
283
572
|
activeoptions_1.ActiveOptions.extendConfig()
|
|
284
573
|
.then((config) => {
|
|
@@ -307,57 +596,73 @@ class Host extends home_1.Home {
|
|
|
307
596
|
activelogger_1.ActiveLogger.info(e, "Failed to reload Neighbourhood");
|
|
308
597
|
});
|
|
309
598
|
}
|
|
310
|
-
destroy(umid) {
|
|
311
|
-
var _a;
|
|
599
|
+
destroy(umid, skipTimeout = false) {
|
|
312
600
|
if (this.processPending[umid]) {
|
|
313
601
|
this.processPending[umid].shutdown = true;
|
|
314
|
-
|
|
602
|
+
this.findProcessor(this.processPending[umid].pid)?.send({
|
|
315
603
|
type: "destory",
|
|
316
604
|
data: {
|
|
317
605
|
umid,
|
|
606
|
+
skipTimeout,
|
|
318
607
|
},
|
|
319
608
|
});
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
609
|
+
if (!skipTimeout) {
|
|
610
|
+
setTimeout(() => {
|
|
611
|
+
delete this.processPending[umid];
|
|
612
|
+
}, RELEASE_DELETE_TIMEOUT);
|
|
613
|
+
}
|
|
323
614
|
}
|
|
324
615
|
}
|
|
325
|
-
broadcast(umid, early = false) {
|
|
326
|
-
|
|
327
|
-
|
|
616
|
+
broadcast(umid, early = false, noreply = false) {
|
|
617
|
+
if (this.processPending[umid] && this.processPending[umid].broadcasting) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (this.processPending[umid]?.entry &&
|
|
328
621
|
this.processPending[umid].entry.$broadcast &&
|
|
329
622
|
this.processPending[umid].entry.$nodes &&
|
|
330
|
-
|
|
331
|
-
|
|
623
|
+
(early ||
|
|
624
|
+
(this.processPending[umid].entry.$nodes[this.reference] &&
|
|
625
|
+
"vote" in this.processPending[umid].entry.$nodes[this.reference]))) {
|
|
626
|
+
this.processPending[umid].broadcasting = true;
|
|
627
|
+
activelogger_1.ActiveLogger.debug(`Broadcasting TX ($$NR ${noreply}) : ` + umid);
|
|
332
628
|
let neighbourhood = this.neighbourhood.get();
|
|
333
629
|
let nodes = this.neighbourhood.keys();
|
|
334
|
-
let i = nodes.length;
|
|
335
630
|
let promises = [];
|
|
336
|
-
const
|
|
631
|
+
const selfEntry = this.processPending[umid].entry.$nodes[this.reference];
|
|
632
|
+
const data = selfEntry && !selfEntry.early
|
|
337
633
|
? Object.assign(this.processPending[umid].entry, {
|
|
338
634
|
$nodes: {
|
|
339
|
-
[this.reference]:
|
|
635
|
+
[this.reference]: selfEntry,
|
|
340
636
|
},
|
|
341
637
|
})
|
|
342
638
|
: Object.assign(this.processPending[umid].entry, {
|
|
343
639
|
$nodes: {},
|
|
344
640
|
});
|
|
345
641
|
if (data) {
|
|
346
|
-
|
|
642
|
+
data.$$noreply = noreply;
|
|
643
|
+
if (early) {
|
|
644
|
+
data.$$noreply = true;
|
|
645
|
+
}
|
|
646
|
+
for (let i = nodes.length; i--;) {
|
|
347
647
|
let node = neighbourhood[nodes[i]];
|
|
348
|
-
if (node.isHome &&
|
|
349
|
-
|
|
648
|
+
if (node.isHome &&
|
|
649
|
+
node.reference !==
|
|
650
|
+
this
|
|
651
|
+
.reference) {
|
|
652
|
+
promises.push(node.knock("init", data, false, 0, true));
|
|
350
653
|
}
|
|
351
654
|
}
|
|
655
|
+
Promise.all(promises)
|
|
656
|
+
.then(() => {
|
|
657
|
+
this.processPending[umid].broadcasting = false;
|
|
658
|
+
})
|
|
659
|
+
.catch(() => {
|
|
660
|
+
this.processPending[umid].broadcasting = false;
|
|
661
|
+
setTimeout(() => {
|
|
662
|
+
this.broadcastResolver(umid);
|
|
663
|
+
}, 250);
|
|
664
|
+
});
|
|
352
665
|
}
|
|
353
|
-
Promise.all(promises)
|
|
354
|
-
.then(() => {
|
|
355
|
-
})
|
|
356
|
-
.catch(() => {
|
|
357
|
-
setTimeout(() => {
|
|
358
|
-
this.broadcastResolver(umid);
|
|
359
|
-
}, 500);
|
|
360
|
-
});
|
|
361
666
|
}
|
|
362
667
|
}
|
|
363
668
|
broadcastResolver(umid) {
|
|
@@ -377,14 +682,18 @@ class Host extends home_1.Home {
|
|
|
377
682
|
},
|
|
378
683
|
reason: "Failed to rebroadcast while in memory",
|
|
379
684
|
};
|
|
380
|
-
this.dbErrorConnection.post(doc)
|
|
685
|
+
this.dbErrorConnection.post(doc).catch((error) => {
|
|
686
|
+
activelogger_1.ActiveLogger.error(error, "Failed to write rebroadcast-failure error document");
|
|
687
|
+
});
|
|
381
688
|
}
|
|
382
689
|
}
|
|
383
690
|
labelOrKey(txIO) {
|
|
384
691
|
const keys = Object.keys(txIO || {});
|
|
385
692
|
const out = [];
|
|
386
693
|
for (let i = keys.length; i--;) {
|
|
387
|
-
|
|
694
|
+
if (!txIO[keys[i]].$sigOnly) {
|
|
695
|
+
out.push(this.filterPrefix(txIO[keys[i]].$stream || keys[i]));
|
|
696
|
+
}
|
|
388
697
|
}
|
|
389
698
|
return out;
|
|
390
699
|
}
|
|
@@ -395,19 +704,27 @@ class Host extends home_1.Home {
|
|
|
395
704
|
return streamId;
|
|
396
705
|
}
|
|
397
706
|
hold(v, retries = 0) {
|
|
398
|
-
if (v
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
...this.labelOrKey(v.$tx.$
|
|
403
|
-
]
|
|
404
|
-
|
|
707
|
+
if (!v.$$labelOrKey) {
|
|
708
|
+
const outputs = this.labelOrKey(v.$tx.$o);
|
|
709
|
+
if (!v.$selfsign) {
|
|
710
|
+
v.$$labelOrKey = [
|
|
711
|
+
...new Set([...this.labelOrKey(v.$tx.$i), ...outputs]),
|
|
712
|
+
];
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
v.$$labelOrKey = outputs;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (locker_1.Locker.hold(v.$$labelOrKey, v.$umid)) {
|
|
405
719
|
const robin = this.getRobin();
|
|
406
720
|
if (!this.processPending[v.$umid].entry.$nodes)
|
|
407
|
-
this.processPending[v.$umid].entry.$nodes
|
|
721
|
+
if (!this.processPending[v.$umid].entry.$nodes) {
|
|
722
|
+
this.processPending[v.$umid].entry.$nodes = {};
|
|
723
|
+
}
|
|
408
724
|
this.processPending[v.$umid].entry.$nodes[home_1.Home.reference] = {
|
|
409
725
|
vote: false,
|
|
410
726
|
commit: false,
|
|
727
|
+
early: true
|
|
411
728
|
};
|
|
412
729
|
this.processPending[v.$umid].pid = robin.pid || 0;
|
|
413
730
|
robin.send({
|
|
@@ -417,60 +734,70 @@ class Host extends home_1.Home {
|
|
|
417
734
|
return true;
|
|
418
735
|
}
|
|
419
736
|
else {
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
entry
|
|
423
|
-
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
const internal = v.$revs ? true : false;
|
|
428
|
-
const maxRetries = internal
|
|
429
|
-
? 2
|
|
430
|
-
: activeoptions_1.ActiveOptions.get("queue_retry", 5);
|
|
431
|
-
if (retries > maxRetries) {
|
|
432
|
-
if (internal) {
|
|
433
|
-
if (!v.$nodes) {
|
|
434
|
-
v.$nodes = {};
|
|
435
|
-
}
|
|
436
|
-
v.$nodes[this.reference] = {
|
|
737
|
+
if (v.$nolock) {
|
|
738
|
+
if (v.$broadcast) {
|
|
739
|
+
this.processPending[v.$umid].entry.$nodes = {
|
|
740
|
+
[this.reference]: {
|
|
437
741
|
vote: false,
|
|
438
742
|
commit: false,
|
|
439
743
|
error: "Busy Locks",
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
this.broadcast(v.$umid, false, true);
|
|
747
|
+
activelogger_1.ActiveLogger.warn(this.processPending[v.$umid], `${v.$umid} busy lock broadcasting that fact`);
|
|
748
|
+
}
|
|
749
|
+
this.processPending[v.$umid].reject({
|
|
750
|
+
status: 100,
|
|
751
|
+
error: "Busy Locks",
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
if (retries === 0) {
|
|
756
|
+
(v.$revs
|
|
757
|
+
? this.busyLocksQueue.internal
|
|
758
|
+
: this.busyLocksQueue.external).push({
|
|
759
|
+
running: false,
|
|
760
|
+
entry: v,
|
|
761
|
+
retry: 1,
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
const internal = v.$revs ? true : false;
|
|
766
|
+
if (retries > activeoptions_1.ActiveOptions.get("queue_retry", MAX_RETRIES)) {
|
|
767
|
+
if (internal) {
|
|
768
|
+
if (!v.$nodes) {
|
|
769
|
+
v.$nodes = {};
|
|
770
|
+
}
|
|
771
|
+
v.$nodes[this.reference] = {
|
|
772
|
+
vote: false,
|
|
773
|
+
commit: false,
|
|
774
|
+
error: "IBL01",
|
|
775
|
+
};
|
|
776
|
+
if (!v.$broadcast && home_1.Home.right.reference != v.$origin) {
|
|
777
|
+
(async () => {
|
|
778
|
+
const next = await home_1.Home.right.knock("init", v);
|
|
779
|
+
this.processPending[v.$umid].resolve({
|
|
780
|
+
status: 200,
|
|
781
|
+
data: { ...v, ...next.data },
|
|
782
|
+
});
|
|
783
|
+
})();
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
this.broadcast(v.$umid, false, true);
|
|
453
787
|
this.processPending[v.$umid].resolve({
|
|
454
788
|
status: 200,
|
|
455
|
-
data:
|
|
789
|
+
data: v,
|
|
456
790
|
});
|
|
457
|
-
}
|
|
791
|
+
}
|
|
458
792
|
}
|
|
459
793
|
else {
|
|
460
|
-
this.processPending[v.$umid].
|
|
461
|
-
status:
|
|
462
|
-
|
|
794
|
+
this.processPending[v.$umid].reject({
|
|
795
|
+
status: 100,
|
|
796
|
+
error: "Busy Locks",
|
|
463
797
|
});
|
|
464
798
|
}
|
|
799
|
+
return true;
|
|
465
800
|
}
|
|
466
|
-
else {
|
|
467
|
-
this.processPending[v.$umid].reject({
|
|
468
|
-
status: 100,
|
|
469
|
-
error: "Busy Locks",
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
this.release(this.processPending[v.$umid]);
|
|
473
|
-
return true;
|
|
474
801
|
}
|
|
475
802
|
}
|
|
476
803
|
return false;
|
|
@@ -487,36 +814,68 @@ class Host extends home_1.Home {
|
|
|
487
814
|
}
|
|
488
815
|
return robin;
|
|
489
816
|
}
|
|
490
|
-
release(
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
817
|
+
release(umid) {
|
|
818
|
+
if (this.processPending[umid]) {
|
|
819
|
+
const entry = this.processPending[umid].entry;
|
|
820
|
+
locker_1.Locker.release(entry.$$labelOrKey || [
|
|
821
|
+
...this.labelOrKey(entry.$tx.$i),
|
|
822
|
+
...this.labelOrKey(entry.$tx.$o),
|
|
823
|
+
], entry.$umid);
|
|
824
|
+
setTimeout(() => {
|
|
825
|
+
if (entry) {
|
|
826
|
+
this.destroy(entry.$umid);
|
|
827
|
+
}
|
|
828
|
+
}, RELEASE_SHUTDOWN_TIMEOUT);
|
|
829
|
+
setTimeout(() => {
|
|
830
|
+
this.processQueue();
|
|
831
|
+
}, 200);
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
activelogger_1.ActiveLogger.warn(umid, "Trying to release unknown umid");
|
|
835
|
+
}
|
|
503
836
|
}
|
|
837
|
+
processingBLQ = false;
|
|
504
838
|
processQueue(next, internal = false) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
839
|
+
if (!this.processingBLQ) {
|
|
840
|
+
this.processingBLQ = true;
|
|
841
|
+
const checked = new Set();
|
|
842
|
+
if (this.busyLocksQueue.internal.length) {
|
|
843
|
+
const stillPending = [];
|
|
844
|
+
busyQueueInternal: for (let i = 0; i < this.busyLocksQueue.internal.length; i++) {
|
|
845
|
+
const labelOrKey = this.busyLocksQueue.internal[i].entry.$$labelOrKey;
|
|
846
|
+
if (labelOrKey?.length) {
|
|
847
|
+
if (labelOrKey.some((io) => checked.has(io))) {
|
|
848
|
+
continue busyQueueInternal;
|
|
849
|
+
}
|
|
850
|
+
labelOrKey.forEach((io) => checked.add(io));
|
|
851
|
+
}
|
|
852
|
+
if (!this.hold(this.busyLocksQueue.internal[i].entry, this.busyLocksQueue.internal[i].retry++)) {
|
|
853
|
+
stillPending.push(this.busyLocksQueue.internal[i]);
|
|
854
|
+
}
|
|
514
855
|
}
|
|
856
|
+
this.busyLocksQueue.internal = stillPending;
|
|
857
|
+
}
|
|
858
|
+
if (next && internal) {
|
|
859
|
+
this.hold(next);
|
|
515
860
|
}
|
|
516
|
-
|
|
861
|
+
if (this.busyLocksQueue.external.length) {
|
|
862
|
+
const stillPending = [];
|
|
863
|
+
for (let i = 0; i < this.busyLocksQueue.external.length; i++) {
|
|
864
|
+
if (!this.hold(this.busyLocksQueue.external[i].entry, this.busyLocksQueue.external[i].retry++)) {
|
|
865
|
+
stillPending.push(this.busyLocksQueue.external[i]);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
this.busyLocksQueue.external = stillPending;
|
|
869
|
+
}
|
|
870
|
+
if (next && !internal) {
|
|
871
|
+
this.hold(next);
|
|
872
|
+
}
|
|
873
|
+
this.processingBLQ = false;
|
|
517
874
|
}
|
|
518
|
-
|
|
519
|
-
|
|
875
|
+
else {
|
|
876
|
+
if (next) {
|
|
877
|
+
this.hold(next);
|
|
878
|
+
}
|
|
520
879
|
}
|
|
521
880
|
}
|
|
522
881
|
timerQueue() {
|
|
@@ -550,12 +909,12 @@ class Host extends home_1.Home {
|
|
|
550
909
|
const data = response.data;
|
|
551
910
|
if (data.status !== "ok") {
|
|
552
911
|
const updated = [
|
|
553
|
-
...(
|
|
554
|
-
...(
|
|
912
|
+
...(activityStreams?.new || []),
|
|
913
|
+
...(activityStreams?.updated || []),
|
|
555
914
|
].map((stream) => stream.id);
|
|
556
|
-
const input = tx.$tx.$i
|
|
557
|
-
|
|
558
|
-
|
|
915
|
+
const input = tx.$tx.$i ?
|
|
916
|
+
this.hybridLabelKeyId(tx.$tx.$i) :
|
|
917
|
+
[];
|
|
559
918
|
const output = tx.$tx.$o
|
|
560
919
|
? this.hybridLabelKeyId(tx.$tx.$o)
|
|
561
920
|
: [];
|
|
@@ -570,8 +929,8 @@ class Host extends home_1.Home {
|
|
|
570
929
|
}
|
|
571
930
|
}
|
|
572
931
|
const tmp = [];
|
|
573
|
-
for (
|
|
574
|
-
tmp.push(
|
|
932
|
+
for (const key of keys) {
|
|
933
|
+
tmp.push(key + ":stream");
|
|
575
934
|
}
|
|
576
935
|
keys.push(...tmp);
|
|
577
936
|
return this.dbConnection
|
|
@@ -623,15 +982,16 @@ class Host extends home_1.Home {
|
|
|
623
982
|
return streams;
|
|
624
983
|
}
|
|
625
984
|
}
|
|
626
|
-
processEndpoints(req, res, body, from) {
|
|
627
|
-
let requester = req.headers["
|
|
985
|
+
processEndpoints(req, res, body, from, isP2P = false) {
|
|
986
|
+
let requester = req.headers["X-Activeledger"] || "NA";
|
|
628
987
|
let response;
|
|
629
|
-
|
|
988
|
+
const started = Date.now();
|
|
989
|
+
let gzipAccepted = req.headers["Accept-Encoding"];
|
|
630
990
|
switch (req.method) {
|
|
631
991
|
case "GET":
|
|
632
992
|
switch (req.url) {
|
|
633
993
|
case "/a/locks":
|
|
634
|
-
return this.writeResponse(res, 200, JSON.stringify(locker_1.Locker.getLocks()), gzipAccepted);
|
|
994
|
+
return this.writeResponse(res, 200, JSON.stringify({ L: locker_1.Locker.getLocks(), Q: this.busyLocksQueue }), gzipAccepted);
|
|
635
995
|
case "/a/locks/check":
|
|
636
996
|
locker_1.Locker.checkLocks();
|
|
637
997
|
return this.writeResponse(res, 200, JSON.stringify({ checked: true }), gzipAccepted);
|
|
@@ -639,15 +999,39 @@ class Host extends home_1.Home {
|
|
|
639
999
|
response = index_1.Endpoints.status(this, requester);
|
|
640
1000
|
break;
|
|
641
1001
|
case "/a/all":
|
|
642
|
-
if (this.firewallCheck(requester, req)) {
|
|
1002
|
+
if (this.firewallCheck(requester, req.connection.remoteAddress)) {
|
|
643
1003
|
response = index_1.Endpoints.all(this.dbConnection);
|
|
644
1004
|
}
|
|
645
1005
|
else {
|
|
646
1006
|
return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
|
|
647
1007
|
}
|
|
648
1008
|
break;
|
|
1009
|
+
case "/a/admin-reload":
|
|
1010
|
+
if (!activeoptions_1.ActiveOptions.get("remote", false)) {
|
|
1011
|
+
return this.writeResponse(res, 200, JSON.stringify({
|
|
1012
|
+
status: "failed",
|
|
1013
|
+
message: "remote disabled"
|
|
1014
|
+
}), gzipAccepted);
|
|
1015
|
+
}
|
|
1016
|
+
try {
|
|
1017
|
+
activeoptions_1.ActiveOptions.parseConfig();
|
|
1018
|
+
activelogger_1.ActiveLogger.enableDebug = activeoptions_1.ActiveOptions.get("debug", false);
|
|
1019
|
+
this.reload();
|
|
1020
|
+
activelogger_1.ActiveLogger.info("Host and child processes config.json reloaded successfully via admin API");
|
|
1021
|
+
return this.writeResponse(res, 200, JSON.stringify({
|
|
1022
|
+
status: "success",
|
|
1023
|
+
build: activeoptions_1.ActiveOptions.get("build", 0),
|
|
1024
|
+
}), gzipAccepted);
|
|
1025
|
+
}
|
|
1026
|
+
catch (error) {
|
|
1027
|
+
activelogger_1.ActiveLogger.error(error, "Admin reload error");
|
|
1028
|
+
return this.writeResponse(res, 200, JSON.stringify({
|
|
1029
|
+
status: "failed",
|
|
1030
|
+
message: error.message || "Internal Error"
|
|
1031
|
+
}), gzipAccepted);
|
|
1032
|
+
}
|
|
649
1033
|
default:
|
|
650
|
-
if (this.firewallCheck(requester, req)) {
|
|
1034
|
+
if (this.firewallCheck(requester, req.connection.remoteAddress)) {
|
|
651
1035
|
if (req.url) {
|
|
652
1036
|
let match = req.url.substr(0, 7);
|
|
653
1037
|
switch (match) {
|
|
@@ -673,41 +1057,27 @@ class Host extends home_1.Home {
|
|
|
673
1057
|
case "POST":
|
|
674
1058
|
switch (req.url) {
|
|
675
1059
|
case "/":
|
|
676
|
-
response = index_1.Endpoints.ExternalInitalise(this, body, req.connection.remoteAddress || "unknown");
|
|
1060
|
+
response = index_1.Endpoints.ExternalInitalise(this, body, req.connection.remoteAddress || "unknown", this.dbConnection);
|
|
677
1061
|
break;
|
|
678
1062
|
case "/a/encrypt":
|
|
679
1063
|
response = index_1.Endpoints.ExternalEncrypt(this, body, req.headers["x-activeledger-encrypt"] ||
|
|
680
1064
|
false, this.dbConnection);
|
|
681
1065
|
break;
|
|
682
1066
|
case "/a/init":
|
|
683
|
-
if (this.firewallCheck(requester, req)) {
|
|
684
|
-
response = index_1.Endpoints.InternalInitalise(this, body);
|
|
1067
|
+
if (this.firewallCheck(requester, req.connection.remoteAddress)) {
|
|
1068
|
+
response = index_1.Endpoints.InternalInitalise(this, body, req.connection.remoteAddress, false, isP2P);
|
|
685
1069
|
}
|
|
686
1070
|
else {
|
|
687
1071
|
return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
|
|
688
1072
|
}
|
|
689
1073
|
break;
|
|
690
1074
|
case "/a/stream":
|
|
691
|
-
|
|
692
|
-
response = index_1.Endpoints.streams(this.dbConnection, body);
|
|
693
|
-
}
|
|
694
|
-
else {
|
|
695
|
-
return this.writeResponse(res, 403, "Forbidden", gzipAccepted);
|
|
696
|
-
}
|
|
1075
|
+
response = index_1.Endpoints.streams(this.dbConnection, body);
|
|
697
1076
|
break;
|
|
698
1077
|
default:
|
|
699
1078
|
return this.writeResponse(res, 404, "Not Found", gzipAccepted);
|
|
700
1079
|
}
|
|
701
1080
|
break;
|
|
702
|
-
case "OPTIONS":
|
|
703
|
-
res.writeHead(200, {
|
|
704
|
-
"Access-Control-Allow-Origin": "*",
|
|
705
|
-
"Access-Control-Allow-Methods": "GET, POST",
|
|
706
|
-
"Access-Control-Allow-Headers": req.headers["access-control-request-headers"] || "*",
|
|
707
|
-
"X-Powered-By": "Activeledger",
|
|
708
|
-
});
|
|
709
|
-
res.end();
|
|
710
|
-
return;
|
|
711
1081
|
default:
|
|
712
1082
|
return this.writeResponse(res, 404, "Not Found", gzipAccepted);
|
|
713
1083
|
}
|
|
@@ -722,31 +1092,52 @@ class Host extends home_1.Home {
|
|
|
722
1092
|
$enc: true,
|
|
723
1093
|
};
|
|
724
1094
|
}
|
|
1095
|
+
if (data.$umid) {
|
|
1096
|
+
const TT = Date.now() - started;
|
|
1097
|
+
if (TT > 5) {
|
|
1098
|
+
activelogger_1.ActiveLogger.info(`[RR] ${data.$umid ? data.$umid : "No Umid"} : S=${started}, TT=${TT}ms ${TT > 30000 ? "TTLR" : " OK"}`);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
725
1101
|
this.writeResponse(res, response.statusCode, JSON.stringify(data), gzipAccepted);
|
|
726
1102
|
})
|
|
727
1103
|
.catch((error) => {
|
|
1104
|
+
activelogger_1.ActiveLogger.error(error, "Failed to send response back");
|
|
1105
|
+
activelogger_1.ActiveLogger.info(`[RR] ERROR : S=${started}, TT=${Date.now() - started}ms`);
|
|
728
1106
|
this.writeResponse(res, error.statusCode || 500, JSON.stringify(error.content || "Something has gone wrong"), gzipAccepted);
|
|
729
1107
|
});
|
|
730
1108
|
}
|
|
731
|
-
async writeResponse(res, statusCode, content, encoding) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
"Content-Encoding": "none",
|
|
735
|
-
"Access-Control-Allow-Origin": "*",
|
|
736
|
-
"X-Powered-By": "Activeledger",
|
|
737
|
-
};
|
|
738
|
-
if (encoding == "gzip") {
|
|
739
|
-
headers["Content-Encoding"] = "gzip";
|
|
740
|
-
content = await activeoptions_1.ActiveGZip.gzip(content);
|
|
1109
|
+
async writeResponse(res, statusCode, content, encoding, cors = false) {
|
|
1110
|
+
if (!res || !res.writable) {
|
|
1111
|
+
return;
|
|
741
1112
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1113
|
+
if (content) {
|
|
1114
|
+
if (encoding == "gzip") {
|
|
1115
|
+
content = await activeoptions_1.ActiveGZip.gzip(content);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
res.cork(() => {
|
|
1119
|
+
res.writeStatus(`${statusCode}`);
|
|
1120
|
+
res.writeHeader("Access-Control-Allow-Origin", "*");
|
|
1121
|
+
res.writeHeader("X-Content-Type-Options", "nosniff");
|
|
1122
|
+
res.writeHeader("X-Frame-Options", "DENY");
|
|
1123
|
+
res.writeHeader("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload");
|
|
1124
|
+
res.writeHeader("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none';");
|
|
1125
|
+
if (cors) {
|
|
1126
|
+
res.writeHeader("Access-Control-Allow-Methods", "GET, POST");
|
|
1127
|
+
res.writeHeader("Access-Control-Allow-Headers", "*");
|
|
1128
|
+
}
|
|
1129
|
+
if (content) {
|
|
1130
|
+
res.writeHeader("Content-Type", "application/json");
|
|
1131
|
+
if (encoding == "gzip") {
|
|
1132
|
+
res.writeHeader("Content-Encoding", "gzip");
|
|
1133
|
+
}
|
|
1134
|
+
res.end(content);
|
|
1135
|
+
res.writable = false;
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
745
1138
|
}
|
|
746
|
-
firewallCheck(requester,
|
|
747
|
-
return (requester
|
|
748
|
-
this.neighbourhood.checkFirewall(req.headers["x-forwarded-for"] ||
|
|
749
|
-
req.connection.remoteAddress));
|
|
1139
|
+
firewallCheck(requester, remoteAddr) {
|
|
1140
|
+
return this.neighbourhood.checkFirewall(remoteAddr, requester);
|
|
750
1141
|
}
|
|
751
1142
|
}
|
|
752
1143
|
exports.Host = Host;
|