@andersbakken/fisk 5.0.17 → 5.0.19
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/builder/fisk-builder.js +363 -218
- package/daemon/fisk-daemon.js +5014 -197
- package/package.json +3 -1
- package/scheduler/fisk-scheduler.js +153 -123
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andersbakken/fisk",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.19",
|
|
4
4
|
"description": "Fisk, a distributed compile system",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint . --ext .ts",
|
|
7
7
|
"rollup": "rollup -c",
|
|
8
8
|
"tsc": "tsc -p .",
|
|
9
9
|
"build": "npm run clean:dist && mkdir -p dist && run-p lint rollup",
|
|
10
|
+
"verify-package-files": "node scripts/verify-package-files.js",
|
|
11
|
+
"prepublishOnly": "npm run build && npm run verify-package-files",
|
|
10
12
|
"clean:dist": "del-cli dist/*",
|
|
11
13
|
"clean:cache": "del-cli .cache/*",
|
|
12
14
|
"clean": "run-p clean:dist clean:cache"
|
|
@@ -3843,7 +3843,7 @@ class SHA1Data {
|
|
|
3843
3843
|
constructor(fileSize, node) {
|
|
3844
3844
|
this.fileSize = fileSize;
|
|
3845
3845
|
this.fileSize = fileSize;
|
|
3846
|
-
this.nodes = [node];
|
|
3846
|
+
this.nodes = new Set([node]);
|
|
3847
3847
|
}
|
|
3848
3848
|
}
|
|
3849
3849
|
|
|
@@ -3974,10 +3974,8 @@ function prettySize(bytes) {
|
|
|
3974
3974
|
function addToSHA1Map(bySHA1, sha1, fileSize, node) {
|
|
3975
3975
|
const data = bySHA1.get(sha1);
|
|
3976
3976
|
if (data) {
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
}
|
|
3980
|
-
return data.nodes.length;
|
|
3977
|
+
data.nodes.add(node);
|
|
3978
|
+
return data.nodes.size;
|
|
3981
3979
|
}
|
|
3982
3980
|
bySHA1.set(sha1, new SHA1Data(fileSize, node));
|
|
3983
3981
|
return 1;
|
|
@@ -3985,10 +3983,8 @@ function addToSHA1Map(bySHA1, sha1, fileSize, node) {
|
|
|
3985
3983
|
function removeFromSHA1Map(bySHA1, sha1, node) {
|
|
3986
3984
|
const data = bySHA1.get(sha1);
|
|
3987
3985
|
if (data) {
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
data.nodes.splice(idx, 1);
|
|
3991
|
-
if (data.nodes.length === 0) {
|
|
3986
|
+
if (data.nodes.delete(node)) {
|
|
3987
|
+
if (data.nodes.size === 0) {
|
|
3992
3988
|
bySHA1.delete(sha1);
|
|
3993
3989
|
}
|
|
3994
3990
|
}
|
|
@@ -4009,7 +4005,8 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4009
4005
|
this.hits = 0;
|
|
4010
4006
|
this.bySHA1 = new Map();
|
|
4011
4007
|
this.byNode = new Map();
|
|
4012
|
-
this.
|
|
4008
|
+
this.pendingBySHA1 = new Map();
|
|
4009
|
+
this.pendingByNode = new Map();
|
|
4013
4010
|
this.pendingTransferTimers = new Map();
|
|
4014
4011
|
this.redundancy = option.int("object-cache-redundancy", 1);
|
|
4015
4012
|
if (this.redundancy <= 0) {
|
|
@@ -4024,7 +4021,8 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4024
4021
|
for (const timer of this.pendingTransferTimers.values()) {
|
|
4025
4022
|
clearTimeout(timer);
|
|
4026
4023
|
}
|
|
4027
|
-
this.
|
|
4024
|
+
this.pendingBySHA1.clear();
|
|
4025
|
+
this.pendingByNode.clear();
|
|
4028
4026
|
this.pendingTransferTimers.clear();
|
|
4029
4027
|
this.emit("cleared");
|
|
4030
4028
|
}
|
|
@@ -4131,7 +4129,7 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4131
4129
|
// console.log(key, value);
|
|
4132
4130
|
sha1[key] = {
|
|
4133
4131
|
fileSize: prettySize(value.fileSize),
|
|
4134
|
-
nodes: value.nodes
|
|
4132
|
+
nodes: Array.from(value.nodes, (node) => node.ip + ":" + node.port)
|
|
4135
4133
|
};
|
|
4136
4134
|
});
|
|
4137
4135
|
ret.sha1 = sha1;
|
|
@@ -4171,11 +4169,15 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4171
4169
|
return;
|
|
4172
4170
|
}
|
|
4173
4171
|
const pendingCount = this.pendingCountForSha1(sha);
|
|
4174
|
-
const totalCopies = value.nodes.
|
|
4172
|
+
const totalCopies = value.nodes.size + pendingCount;
|
|
4175
4173
|
const needed = Math.min(redundancy + 1 - totalCopies, this.byNode.size - 1);
|
|
4176
4174
|
if (needed > 0) {
|
|
4177
4175
|
let firstIdx;
|
|
4178
4176
|
let found = 0;
|
|
4177
|
+
// Only materialised if we actually pick a source, since
|
|
4178
|
+
// most objects already have enough copies and never get
|
|
4179
|
+
// this far.
|
|
4180
|
+
let sources;
|
|
4179
4181
|
while (found < needed) {
|
|
4180
4182
|
if (++nodeIdx === nodes.length) {
|
|
4181
4183
|
nodeIdx = 0;
|
|
@@ -4187,7 +4189,7 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4187
4189
|
break;
|
|
4188
4190
|
}
|
|
4189
4191
|
const node = nodes[nodeIdx];
|
|
4190
|
-
if (value.nodes.
|
|
4192
|
+
if (value.nodes.has(node)) {
|
|
4191
4193
|
continue;
|
|
4192
4194
|
}
|
|
4193
4195
|
if (this.hasPendingTransfer(sha, node)) {
|
|
@@ -4215,7 +4217,10 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4215
4217
|
}
|
|
4216
4218
|
++found;
|
|
4217
4219
|
data.available -= value.fileSize;
|
|
4218
|
-
|
|
4220
|
+
if (!sources) {
|
|
4221
|
+
sources = Array.from(value.nodes);
|
|
4222
|
+
}
|
|
4223
|
+
const src = sources[roundRobinIndex++ % sources.length];
|
|
4219
4224
|
data.objects.push({ source: src.ip + ":" + src.port, sha1: sha });
|
|
4220
4225
|
if (max !== undefined && !--max) {
|
|
4221
4226
|
break;
|
|
@@ -4259,48 +4264,64 @@ class ObjectCacheManager extends require$$0__default$2["default"] {
|
|
|
4259
4264
|
}
|
|
4260
4265
|
}
|
|
4261
4266
|
addPendingTransfer(sha1, node) {
|
|
4267
|
+
let nodes = this.pendingBySHA1.get(sha1);
|
|
4268
|
+
if (!nodes) {
|
|
4269
|
+
nodes = new Set();
|
|
4270
|
+
this.pendingBySHA1.set(sha1, nodes);
|
|
4271
|
+
}
|
|
4272
|
+
nodes.add(node);
|
|
4273
|
+
let sha1s = this.pendingByNode.get(node);
|
|
4274
|
+
if (!sha1s) {
|
|
4275
|
+
sha1s = new Set();
|
|
4276
|
+
this.pendingByNode.set(node, sha1s);
|
|
4277
|
+
}
|
|
4278
|
+
sha1s.add(sha1);
|
|
4262
4279
|
const key = pendingKey(sha1, node);
|
|
4263
|
-
this.
|
|
4280
|
+
const existing = this.pendingTransferTimers.get(key);
|
|
4281
|
+
if (existing) {
|
|
4282
|
+
clearTimeout(existing);
|
|
4283
|
+
}
|
|
4264
4284
|
const timer = setTimeout(() => {
|
|
4265
|
-
this.
|
|
4266
|
-
this.pendingTransferTimers.delete(key);
|
|
4285
|
+
this.forgetPendingTransfer(sha1, node);
|
|
4267
4286
|
}, this.pendingTransferTimeoutMs);
|
|
4268
4287
|
timer.unref();
|
|
4269
4288
|
this.pendingTransferTimers.set(key, timer);
|
|
4270
4289
|
}
|
|
4271
4290
|
clearPendingTransfer(sha1, node) {
|
|
4272
|
-
const
|
|
4273
|
-
this.pendingTransfers.delete(key);
|
|
4274
|
-
const timer = this.pendingTransferTimers.get(key);
|
|
4291
|
+
const timer = this.pendingTransferTimers.get(pendingKey(sha1, node));
|
|
4275
4292
|
if (timer) {
|
|
4276
4293
|
clearTimeout(timer);
|
|
4277
|
-
this.pendingTransferTimers.delete(key);
|
|
4278
4294
|
}
|
|
4295
|
+
this.forgetPendingTransfer(sha1, node);
|
|
4296
|
+
}
|
|
4297
|
+
forgetPendingTransfer(sha1, node) {
|
|
4298
|
+
const nodes = this.pendingBySHA1.get(sha1);
|
|
4299
|
+
if (nodes && nodes.delete(node) && nodes.size === 0) {
|
|
4300
|
+
this.pendingBySHA1.delete(sha1);
|
|
4301
|
+
}
|
|
4302
|
+
const sha1s = this.pendingByNode.get(node);
|
|
4303
|
+
if (sha1s && sha1s.delete(sha1) && sha1s.size === 0) {
|
|
4304
|
+
this.pendingByNode.delete(node);
|
|
4305
|
+
}
|
|
4306
|
+
this.pendingTransferTimers.delete(pendingKey(sha1, node));
|
|
4279
4307
|
}
|
|
4280
4308
|
clearAllPendingForNode(node) {
|
|
4281
|
-
const
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
clearTimeout(timer);
|
|
4288
|
-
this.pendingTransferTimers.delete(key);
|
|
4289
|
-
}
|
|
4290
|
-
}
|
|
4309
|
+
const sha1s = this.pendingByNode.get(node);
|
|
4310
|
+
if (!sha1s) {
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
for (const sha1 of Array.from(sha1s)) {
|
|
4314
|
+
this.clearPendingTransfer(sha1, node);
|
|
4291
4315
|
}
|
|
4316
|
+
this.pendingByNode.delete(node);
|
|
4292
4317
|
}
|
|
4293
4318
|
pendingCountForSha1(sha1) {
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
if (key.startsWith(sha1 + ":")) {
|
|
4297
|
-
++count;
|
|
4298
|
-
}
|
|
4299
|
-
}
|
|
4300
|
-
return count;
|
|
4319
|
+
var _a, _b;
|
|
4320
|
+
return (_b = (_a = this.pendingBySHA1.get(sha1)) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0;
|
|
4301
4321
|
}
|
|
4302
4322
|
hasPendingTransfer(sha1, node) {
|
|
4303
|
-
|
|
4323
|
+
var _a, _b;
|
|
4324
|
+
return (_b = (_a = this.pendingBySHA1.get(sha1)) === null || _a === void 0 ? void 0 : _a.has(node)) !== null && _b !== void 0 ? _b : false;
|
|
4304
4325
|
}
|
|
4305
4326
|
}
|
|
4306
4327
|
|
|
@@ -4621,6 +4642,97 @@ class DaemonConnection extends Client {
|
|
|
4621
4642
|
}
|
|
4622
4643
|
}
|
|
4623
4644
|
|
|
4645
|
+
const Version = 5;
|
|
4646
|
+
// 6: objects now carry the client's real source path and compilation dir,
|
|
4647
|
+
// baked in at compile time instead of the builder's /compiles paths, and the
|
|
4648
|
+
// stored response no longer keeps the paths the client used to patch with.
|
|
4649
|
+
const ObjectCacheFormatVersion = 6;
|
|
4650
|
+
function cacheDir(option) {
|
|
4651
|
+
let dir = option("cache-dir");
|
|
4652
|
+
if (!dir) {
|
|
4653
|
+
dir = path__default["default"].join(require$$1__default$1["default"].homedir(), ".cache", "fisk", path__default["default"].basename(option.prefix || ""));
|
|
4654
|
+
}
|
|
4655
|
+
return dir;
|
|
4656
|
+
}
|
|
4657
|
+
function validateCache(option) {
|
|
4658
|
+
const dir = cacheDir(option);
|
|
4659
|
+
const file = path__default["default"].join(dir, "version");
|
|
4660
|
+
// console.log(dir);
|
|
4661
|
+
let version;
|
|
4662
|
+
try {
|
|
4663
|
+
version = fs$4.readFileSync(file);
|
|
4664
|
+
if (version.readUInt32BE() === Version) {
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
catch (err) {
|
|
4669
|
+
/* */
|
|
4670
|
+
}
|
|
4671
|
+
if (version) {
|
|
4672
|
+
console.log(`Wrong version. Destroying cache ${dir}`);
|
|
4673
|
+
}
|
|
4674
|
+
fs$4.removeSync(dir);
|
|
4675
|
+
fs$4.mkdirpSync(dir);
|
|
4676
|
+
const buf = Buffer.allocUnsafe(4);
|
|
4677
|
+
buf.writeUInt32BE(Version);
|
|
4678
|
+
fs$4.writeFileSync(file, buf);
|
|
4679
|
+
}
|
|
4680
|
+
function validateObjectCache(option) {
|
|
4681
|
+
const dir = cacheDir(option);
|
|
4682
|
+
const objectCacheDir = option.string("object-cache-dir") || path__default["default"].join(dir, "objectcache");
|
|
4683
|
+
const file = path__default["default"].join(objectCacheDir, "version");
|
|
4684
|
+
let version;
|
|
4685
|
+
try {
|
|
4686
|
+
version = fs$4.readFileSync(file);
|
|
4687
|
+
if (version.readUInt32BE() === ObjectCacheFormatVersion) {
|
|
4688
|
+
return;
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
catch (err) {
|
|
4692
|
+
/* */
|
|
4693
|
+
}
|
|
4694
|
+
if (version) {
|
|
4695
|
+
console.log(`Wrong object cache version. Destroying object cache ${objectCacheDir}`);
|
|
4696
|
+
}
|
|
4697
|
+
fs$4.removeSync(objectCacheDir);
|
|
4698
|
+
fs$4.mkdirpSync(objectCacheDir);
|
|
4699
|
+
const buf = Buffer.allocUnsafe(4);
|
|
4700
|
+
buf.writeUInt32BE(ObjectCacheFormatVersion);
|
|
4701
|
+
fs$4.writeFileSync(file, buf);
|
|
4702
|
+
}
|
|
4703
|
+
// The listen backlog is the depth of the kernel's accept queue. When it fills
|
|
4704
|
+
// -- which is what happens whenever the event loop stalls long enough to stop
|
|
4705
|
+
// calling accept() -- Linux does not refuse the connection, it silently drops
|
|
4706
|
+
// the SYN, and the client's first retransmit is a second later. A client with a
|
|
4707
|
+
// sub-second handshake budget sees that as a timeout with no server-side trace.
|
|
4708
|
+
// listen(2) clamps to net.core.somaxconn, so following somaxconn is both the
|
|
4709
|
+
// largest useful value and the one an operator can actually tune.
|
|
4710
|
+
function defaultBacklog() {
|
|
4711
|
+
try {
|
|
4712
|
+
return parseInt(fs$4.readFileSync("/proc/sys/net/core/somaxconn", "utf8")) || 511;
|
|
4713
|
+
}
|
|
4714
|
+
catch (err) {
|
|
4715
|
+
// Not Linux, or procfs isn't mounted. 511 is node's own default.
|
|
4716
|
+
return 511;
|
|
4717
|
+
}
|
|
4718
|
+
}
|
|
4719
|
+
// Only the builder keeps an object cache on disk. The scheduler tracks which
|
|
4720
|
+
// builder holds which sha1 in memory, and the daemon uses cacheDir purely for
|
|
4721
|
+
// the default socket path -- validating an object cache for either created a
|
|
4722
|
+
// directory they never read and, on a format bump, tried to destroy one they do
|
|
4723
|
+
// not necessarily own.
|
|
4724
|
+
function common$1(option, hasObjectCache = false) {
|
|
4725
|
+
validateCache(option);
|
|
4726
|
+
if (hasObjectCache) {
|
|
4727
|
+
validateObjectCache(option);
|
|
4728
|
+
}
|
|
4729
|
+
return {
|
|
4730
|
+
cacheDir: cacheDir.bind(undefined, option),
|
|
4731
|
+
Version,
|
|
4732
|
+
ObjectCacheFormatVersion
|
|
4733
|
+
};
|
|
4734
|
+
}
|
|
4735
|
+
|
|
4624
4736
|
/**
|
|
4625
4737
|
* Check if we're required to add a port number.
|
|
4626
4738
|
*
|
|
@@ -56177,14 +56289,7 @@ class Server extends require$$0__default$2["default"] {
|
|
|
56177
56289
|
return;
|
|
56178
56290
|
}
|
|
56179
56291
|
}
|
|
56180
|
-
|
|
56181
|
-
try {
|
|
56182
|
-
defaultBacklog = parseInt(fs__default["default"].readFileSync("/proc/sys/net/core/somaxconn", "utf8")) || 128;
|
|
56183
|
-
}
|
|
56184
|
-
catch (err) {
|
|
56185
|
-
/* */
|
|
56186
|
-
}
|
|
56187
|
-
const backlog = this.option.int("backlog", defaultBacklog);
|
|
56292
|
+
const backlog = this.option.int("backlog", defaultBacklog());
|
|
56188
56293
|
this.ws = new ws.Server({ noServer: true });
|
|
56189
56294
|
let waitingServers = 1;
|
|
56190
56295
|
const port = this.option.int("port", 8097);
|
|
@@ -56639,81 +56744,6 @@ class Server extends require$$0__default$2["default"] {
|
|
|
56639
56744
|
}
|
|
56640
56745
|
}
|
|
56641
56746
|
|
|
56642
|
-
const Version = 5;
|
|
56643
|
-
// 6: objects now carry the client's real source path and compilation dir,
|
|
56644
|
-
// baked in at compile time instead of the builder's /compiles paths, and the
|
|
56645
|
-
// stored response no longer keeps the paths the client used to patch with.
|
|
56646
|
-
const ObjectCacheFormatVersion = 6;
|
|
56647
|
-
function cacheDir(option) {
|
|
56648
|
-
let dir = option("cache-dir");
|
|
56649
|
-
if (!dir) {
|
|
56650
|
-
dir = path__default["default"].join(require$$1__default$1["default"].homedir(), ".cache", "fisk", path__default["default"].basename(option.prefix || ""));
|
|
56651
|
-
}
|
|
56652
|
-
return dir;
|
|
56653
|
-
}
|
|
56654
|
-
function validateCache(option) {
|
|
56655
|
-
const dir = cacheDir(option);
|
|
56656
|
-
const file = path__default["default"].join(dir, "version");
|
|
56657
|
-
// console.log(dir);
|
|
56658
|
-
let version;
|
|
56659
|
-
try {
|
|
56660
|
-
version = fs$4.readFileSync(file);
|
|
56661
|
-
if (version.readUInt32BE() === Version) {
|
|
56662
|
-
return;
|
|
56663
|
-
}
|
|
56664
|
-
}
|
|
56665
|
-
catch (err) {
|
|
56666
|
-
/* */
|
|
56667
|
-
}
|
|
56668
|
-
if (version) {
|
|
56669
|
-
console.log(`Wrong version. Destroying cache ${dir}`);
|
|
56670
|
-
}
|
|
56671
|
-
fs$4.removeSync(dir);
|
|
56672
|
-
fs$4.mkdirpSync(dir);
|
|
56673
|
-
const buf = Buffer.allocUnsafe(4);
|
|
56674
|
-
buf.writeUInt32BE(Version);
|
|
56675
|
-
fs$4.writeFileSync(file, buf);
|
|
56676
|
-
}
|
|
56677
|
-
function validateObjectCache(option) {
|
|
56678
|
-
const dir = cacheDir(option);
|
|
56679
|
-
const objectCacheDir = option.string("object-cache-dir") || path__default["default"].join(dir, "objectcache");
|
|
56680
|
-
const file = path__default["default"].join(objectCacheDir, "version");
|
|
56681
|
-
let version;
|
|
56682
|
-
try {
|
|
56683
|
-
version = fs$4.readFileSync(file);
|
|
56684
|
-
if (version.readUInt32BE() === ObjectCacheFormatVersion) {
|
|
56685
|
-
return;
|
|
56686
|
-
}
|
|
56687
|
-
}
|
|
56688
|
-
catch (err) {
|
|
56689
|
-
/* */
|
|
56690
|
-
}
|
|
56691
|
-
if (version) {
|
|
56692
|
-
console.log(`Wrong object cache version. Destroying object cache ${objectCacheDir}`);
|
|
56693
|
-
}
|
|
56694
|
-
fs$4.removeSync(objectCacheDir);
|
|
56695
|
-
fs$4.mkdirpSync(objectCacheDir);
|
|
56696
|
-
const buf = Buffer.allocUnsafe(4);
|
|
56697
|
-
buf.writeUInt32BE(ObjectCacheFormatVersion);
|
|
56698
|
-
fs$4.writeFileSync(file, buf);
|
|
56699
|
-
}
|
|
56700
|
-
// Only the builder keeps an object cache on disk. The scheduler tracks which
|
|
56701
|
-
// builder holds which sha1 in memory, and the daemon uses cacheDir purely for
|
|
56702
|
-
// the default socket path -- validating an object cache for either created a
|
|
56703
|
-
// directory they never read and, on a format bump, tried to destroy one they do
|
|
56704
|
-
// not necessarily own.
|
|
56705
|
-
function common$1(option, hasObjectCache = false) {
|
|
56706
|
-
validateCache(option);
|
|
56707
|
-
if (hasObjectCache) {
|
|
56708
|
-
validateObjectCache(option);
|
|
56709
|
-
}
|
|
56710
|
-
return {
|
|
56711
|
-
cacheDir: cacheDir.bind(undefined, option),
|
|
56712
|
-
Version,
|
|
56713
|
-
ObjectCacheFormatVersion
|
|
56714
|
-
};
|
|
56715
|
-
}
|
|
56716
|
-
|
|
56717
56747
|
var bytesExports = requireBytes();
|
|
56718
56748
|
var bytes = /*@__PURE__*/getDefaultExportFromCjs(bytesExports);
|
|
56719
56749
|
|