@malloy-publisher/server 0.0.197 → 0.0.198
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/README.docker.md +47 -0
- package/dist/app/api-doc.yaml +3 -20
- package/dist/app/assets/{EnvironmentPage-BVkQH_xQ.js → EnvironmentPage-C7rtH4mC.js} +1 -1
- package/dist/app/assets/{HomePage-BgH9UkjK.js → HomePage-DwkH7OrS.js} +1 -1
- package/dist/app/assets/{MainPage-DiBxABem.js → MainPage-D38LtZDV.js} +1 -1
- package/dist/app/assets/{ModelPage-oS70fj83.js → ModelPage-DOol8Mz7.js} +1 -1
- package/dist/app/assets/{PackagePage-F_qLDAdv.js → PackagePage-0tgzA_kO.js} +1 -1
- package/dist/app/assets/{RouteError-WqpffppN.js → RouteError-BaMsOSly.js} +1 -1
- package/dist/app/assets/{WorkbookPage-_YmC-ebR.js → WorkbookPage-Cx4SePkx.js} +1 -1
- package/dist/app/assets/{core-B8L9xCYT.es-BcRLJTnC.js → core-CbsC6R_Y.es-Cwf6asf3.js} +1 -1
- package/dist/app/assets/{index-rg8Ok8nl.js → index-DL6BZTuw.js} +1 -1
- package/dist/app/assets/{index-C3XPaTaS.js → index-DNofXMxi.js} +1 -1
- package/dist/app/assets/{index-BMViiwtJ.js → index-U38AyjJL.js} +3 -3
- package/dist/app/assets/{index.umd-CCAfKkxY.js → index.umd-B68wGGkM.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/server.mjs +812 -450
- package/package.json +1 -1
- package/src/config.spec.ts +81 -0
- package/src/config.ts +126 -0
- package/src/controller/package.controller.ts +70 -29
- package/src/errors.ts +13 -0
- package/src/health.ts +0 -26
- package/src/mcp/tools/discovery_tools.ts +6 -2
- package/src/path_safety.spec.ts +158 -0
- package/src/path_safety.ts +140 -0
- package/src/server.ts +13 -0
- package/src/service/environment.ts +614 -198
- package/src/service/environment_admission.spec.ts +180 -0
- package/src/service/environment_store.spec.ts +0 -19
- package/src/service/environment_store.ts +24 -21
- package/src/service/manifest_service.spec.ts +7 -2
- package/src/service/manifest_service.ts +8 -2
- package/src/service/materialization_service.ts +14 -3
- package/src/service/package_memory_governor.spec.ts +173 -0
- package/src/service/package_memory_governor.ts +233 -0
- package/src/service/package_race.spec.ts +208 -0
package/dist/server.mjs
CHANGED
|
@@ -196989,26 +196989,26 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
196989
196989
|
}
|
|
196990
196990
|
mkdirSync(folder);
|
|
196991
196991
|
};
|
|
196992
|
-
Utils.prototype.writeFileTo = function(
|
|
196992
|
+
Utils.prototype.writeFileTo = function(path3, content, overwrite, attr) {
|
|
196993
196993
|
const self2 = this;
|
|
196994
|
-
if (self2.fs.existsSync(
|
|
196994
|
+
if (self2.fs.existsSync(path3)) {
|
|
196995
196995
|
if (!overwrite)
|
|
196996
196996
|
return false;
|
|
196997
|
-
var stat4 = self2.fs.statSync(
|
|
196997
|
+
var stat4 = self2.fs.statSync(path3);
|
|
196998
196998
|
if (stat4.isDirectory()) {
|
|
196999
196999
|
return false;
|
|
197000
197000
|
}
|
|
197001
197001
|
}
|
|
197002
|
-
var folder = pth.dirname(
|
|
197002
|
+
var folder = pth.dirname(path3);
|
|
197003
197003
|
if (!self2.fs.existsSync(folder)) {
|
|
197004
197004
|
self2.makeDir(folder);
|
|
197005
197005
|
}
|
|
197006
197006
|
var fd;
|
|
197007
197007
|
try {
|
|
197008
|
-
fd = self2.fs.openSync(
|
|
197008
|
+
fd = self2.fs.openSync(path3, "w", 438);
|
|
197009
197009
|
} catch (e) {
|
|
197010
|
-
self2.fs.chmodSync(
|
|
197011
|
-
fd = self2.fs.openSync(
|
|
197010
|
+
self2.fs.chmodSync(path3, 438);
|
|
197011
|
+
fd = self2.fs.openSync(path3, "w", 438);
|
|
197012
197012
|
}
|
|
197013
197013
|
if (fd) {
|
|
197014
197014
|
try {
|
|
@@ -197017,33 +197017,33 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197017
197017
|
self2.fs.closeSync(fd);
|
|
197018
197018
|
}
|
|
197019
197019
|
}
|
|
197020
|
-
self2.fs.chmodSync(
|
|
197020
|
+
self2.fs.chmodSync(path3, attr || 438);
|
|
197021
197021
|
return true;
|
|
197022
197022
|
};
|
|
197023
|
-
Utils.prototype.writeFileToAsync = function(
|
|
197023
|
+
Utils.prototype.writeFileToAsync = function(path3, content, overwrite, attr, callback) {
|
|
197024
197024
|
if (typeof attr === "function") {
|
|
197025
197025
|
callback = attr;
|
|
197026
197026
|
attr = undefined;
|
|
197027
197027
|
}
|
|
197028
197028
|
const self2 = this;
|
|
197029
|
-
self2.fs.exists(
|
|
197029
|
+
self2.fs.exists(path3, function(exist) {
|
|
197030
197030
|
if (exist && !overwrite)
|
|
197031
197031
|
return callback(false);
|
|
197032
|
-
self2.fs.stat(
|
|
197032
|
+
self2.fs.stat(path3, function(err, stat4) {
|
|
197033
197033
|
if (exist && stat4.isDirectory()) {
|
|
197034
197034
|
return callback(false);
|
|
197035
197035
|
}
|
|
197036
|
-
var folder = pth.dirname(
|
|
197036
|
+
var folder = pth.dirname(path3);
|
|
197037
197037
|
self2.fs.exists(folder, function(exists) {
|
|
197038
197038
|
if (!exists)
|
|
197039
197039
|
self2.makeDir(folder);
|
|
197040
|
-
self2.fs.open(
|
|
197040
|
+
self2.fs.open(path3, "w", 438, function(err2, fd) {
|
|
197041
197041
|
if (err2) {
|
|
197042
|
-
self2.fs.chmod(
|
|
197043
|
-
self2.fs.open(
|
|
197042
|
+
self2.fs.chmod(path3, 438, function() {
|
|
197043
|
+
self2.fs.open(path3, "w", 438, function(err3, fd2) {
|
|
197044
197044
|
self2.fs.write(fd2, content, 0, content.length, 0, function() {
|
|
197045
197045
|
self2.fs.close(fd2, function() {
|
|
197046
|
-
self2.fs.chmod(
|
|
197046
|
+
self2.fs.chmod(path3, attr || 438, function() {
|
|
197047
197047
|
callback(true);
|
|
197048
197048
|
});
|
|
197049
197049
|
});
|
|
@@ -197053,13 +197053,13 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197053
197053
|
} else if (fd) {
|
|
197054
197054
|
self2.fs.write(fd, content, 0, content.length, 0, function() {
|
|
197055
197055
|
self2.fs.close(fd, function() {
|
|
197056
|
-
self2.fs.chmod(
|
|
197056
|
+
self2.fs.chmod(path3, attr || 438, function() {
|
|
197057
197057
|
callback(true);
|
|
197058
197058
|
});
|
|
197059
197059
|
});
|
|
197060
197060
|
});
|
|
197061
197061
|
} else {
|
|
197062
|
-
self2.fs.chmod(
|
|
197062
|
+
self2.fs.chmod(path3, attr || 438, function() {
|
|
197063
197063
|
callback(true);
|
|
197064
197064
|
});
|
|
197065
197065
|
}
|
|
@@ -197068,7 +197068,7 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197068
197068
|
});
|
|
197069
197069
|
});
|
|
197070
197070
|
};
|
|
197071
|
-
Utils.prototype.findFiles = function(
|
|
197071
|
+
Utils.prototype.findFiles = function(path3) {
|
|
197072
197072
|
const self2 = this;
|
|
197073
197073
|
function findSync(dir, pattern, recursive) {
|
|
197074
197074
|
if (typeof pattern === "boolean") {
|
|
@@ -197077,17 +197077,17 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197077
197077
|
}
|
|
197078
197078
|
let files = [];
|
|
197079
197079
|
self2.fs.readdirSync(dir).forEach(function(file) {
|
|
197080
|
-
const
|
|
197081
|
-
const stat4 = self2.fs.statSync(
|
|
197082
|
-
if (!pattern || pattern.test(
|
|
197083
|
-
files.push(pth.normalize(
|
|
197080
|
+
const path4 = pth.join(dir, file);
|
|
197081
|
+
const stat4 = self2.fs.statSync(path4);
|
|
197082
|
+
if (!pattern || pattern.test(path4)) {
|
|
197083
|
+
files.push(pth.normalize(path4) + (stat4.isDirectory() ? self2.sep : ""));
|
|
197084
197084
|
}
|
|
197085
197085
|
if (stat4.isDirectory() && recursive)
|
|
197086
|
-
files = files.concat(findSync(
|
|
197086
|
+
files = files.concat(findSync(path4, pattern, recursive));
|
|
197087
197087
|
});
|
|
197088
197088
|
return files;
|
|
197089
197089
|
}
|
|
197090
|
-
return findSync(
|
|
197090
|
+
return findSync(path3, undefined, true);
|
|
197091
197091
|
};
|
|
197092
197092
|
Utils.prototype.findFilesAsync = function(dir, cb) {
|
|
197093
197093
|
const self2 = this;
|
|
@@ -197147,16 +197147,16 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197147
197147
|
return "UNSUPPORTED (" + method + ")";
|
|
197148
197148
|
}
|
|
197149
197149
|
};
|
|
197150
|
-
Utils.canonical = function(
|
|
197151
|
-
if (!
|
|
197150
|
+
Utils.canonical = function(path3) {
|
|
197151
|
+
if (!path3)
|
|
197152
197152
|
return "";
|
|
197153
|
-
const safeSuffix = pth.posix.normalize("/" +
|
|
197153
|
+
const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
|
|
197154
197154
|
return pth.join(".", safeSuffix);
|
|
197155
197155
|
};
|
|
197156
|
-
Utils.zipnamefix = function(
|
|
197157
|
-
if (!
|
|
197156
|
+
Utils.zipnamefix = function(path3) {
|
|
197157
|
+
if (!path3)
|
|
197158
197158
|
return "";
|
|
197159
|
-
const safeSuffix = pth.posix.normalize("/" +
|
|
197159
|
+
const safeSuffix = pth.posix.normalize("/" + path3.split("\\").join("/"));
|
|
197160
197160
|
return pth.posix.join(".", safeSuffix);
|
|
197161
197161
|
};
|
|
197162
197162
|
Utils.findLast = function(arr, callback) {
|
|
@@ -197174,9 +197174,9 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197174
197174
|
prefix = pth.resolve(pth.normalize(prefix));
|
|
197175
197175
|
var parts = name.split("/");
|
|
197176
197176
|
for (var i = 0, l = parts.length;i < l; i++) {
|
|
197177
|
-
var
|
|
197178
|
-
if (
|
|
197179
|
-
return
|
|
197177
|
+
var path3 = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
|
197178
|
+
if (path3.indexOf(prefix) === 0) {
|
|
197179
|
+
return path3;
|
|
197180
197180
|
}
|
|
197181
197181
|
}
|
|
197182
197182
|
return pth.normalize(pth.join(prefix, pth.basename(name)));
|
|
@@ -197214,8 +197214,8 @@ var require_utils74 = __commonJS((exports, module) => {
|
|
|
197214
197214
|
// ../../node_modules/adm-zip/util/fattr.js
|
|
197215
197215
|
var require_fattr = __commonJS((exports, module) => {
|
|
197216
197216
|
var pth = __require("path");
|
|
197217
|
-
module.exports = function(
|
|
197218
|
-
var _path =
|
|
197217
|
+
module.exports = function(path3, { fs: fs2 }) {
|
|
197218
|
+
var _path = path3 || "", _obj = newAttr(), _stat = null;
|
|
197219
197219
|
function newAttr() {
|
|
197220
197220
|
return {
|
|
197221
197221
|
directory: false,
|
|
@@ -198545,8 +198545,8 @@ var require_adm_zip = __commonJS((exports, module) => {
|
|
|
198545
198545
|
return null;
|
|
198546
198546
|
}
|
|
198547
198547
|
function fixPath(zipPath) {
|
|
198548
|
-
const { join:
|
|
198549
|
-
return
|
|
198548
|
+
const { join: join3, normalize: normalize2, sep } = pth.posix;
|
|
198549
|
+
return join3(".", normalize2(sep + zipPath.split("\\").join(sep) + sep));
|
|
198550
198550
|
}
|
|
198551
198551
|
function filenameFilter(filterfn) {
|
|
198552
198552
|
if (filterfn instanceof RegExp) {
|
|
@@ -199074,10 +199074,10 @@ var require_src122 = __commonJS((exports) => {
|
|
|
199074
199074
|
var fs_1 = __require("fs");
|
|
199075
199075
|
var debug_1 = __importDefault(require_src5());
|
|
199076
199076
|
var log = debug_1.default("@kwsites/file-exists");
|
|
199077
|
-
function check(
|
|
199078
|
-
log(`checking %s`,
|
|
199077
|
+
function check(path3, isFile2, isDirectory) {
|
|
199078
|
+
log(`checking %s`, path3);
|
|
199079
199079
|
try {
|
|
199080
|
-
const stat4 = fs_1.statSync(
|
|
199080
|
+
const stat4 = fs_1.statSync(path3);
|
|
199081
199081
|
if (stat4.isFile() && isFile2) {
|
|
199082
199082
|
log(`[OK] path represents a file`);
|
|
199083
199083
|
return true;
|
|
@@ -199097,8 +199097,8 @@ var require_src122 = __commonJS((exports) => {
|
|
|
199097
199097
|
throw e;
|
|
199098
199098
|
}
|
|
199099
199099
|
}
|
|
199100
|
-
function exists(
|
|
199101
|
-
return check(
|
|
199100
|
+
function exists(path3, type = exports.READABLE) {
|
|
199101
|
+
return check(path3, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
199102
199102
|
}
|
|
199103
199103
|
exports.exists = exists;
|
|
199104
199104
|
exports.FILE = 1;
|
|
@@ -199984,12 +199984,12 @@ var require_recursive_readdir = __commonJS((exports, module) => {
|
|
|
199984
199984
|
ignores = [];
|
|
199985
199985
|
}
|
|
199986
199986
|
if (!callback) {
|
|
199987
|
-
return new Promise(function(
|
|
199987
|
+
return new Promise(function(resolve4, reject) {
|
|
199988
199988
|
readdir3(path7, ignores || [], function(err, data) {
|
|
199989
199989
|
if (err) {
|
|
199990
199990
|
reject(err);
|
|
199991
199991
|
} else {
|
|
199992
|
-
|
|
199992
|
+
resolve4(data);
|
|
199993
199993
|
}
|
|
199994
199994
|
});
|
|
199995
199995
|
});
|
|
@@ -200771,7 +200771,7 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
200771
200771
|
target.fragment = relative4.fragment;
|
|
200772
200772
|
return target;
|
|
200773
200773
|
}
|
|
200774
|
-
function
|
|
200774
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
200775
200775
|
var schemelessOptions = assign({ scheme: "null" }, options);
|
|
200776
200776
|
return serialize(resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true), schemelessOptions);
|
|
200777
200777
|
}
|
|
@@ -201039,7 +201039,7 @@ var require_uri_all = __commonJS((exports, module) => {
|
|
|
201039
201039
|
exports2.removeDotSegments = removeDotSegments;
|
|
201040
201040
|
exports2.serialize = serialize;
|
|
201041
201041
|
exports2.resolveComponents = resolveComponents;
|
|
201042
|
-
exports2.resolve =
|
|
201042
|
+
exports2.resolve = resolve4;
|
|
201043
201043
|
exports2.normalize = normalize2;
|
|
201044
201044
|
exports2.equal = equal;
|
|
201045
201045
|
exports2.escapeComponent = escapeComponent;
|
|
@@ -201405,20 +201405,20 @@ var require_resolve2 = __commonJS((exports, module) => {
|
|
|
201405
201405
|
var util5 = require_util13();
|
|
201406
201406
|
var SchemaObject = require_schema_obj();
|
|
201407
201407
|
var traverse = require_json_schema_traverse();
|
|
201408
|
-
module.exports =
|
|
201409
|
-
|
|
201410
|
-
|
|
201411
|
-
|
|
201412
|
-
|
|
201413
|
-
|
|
201414
|
-
|
|
201415
|
-
function
|
|
201408
|
+
module.exports = resolve4;
|
|
201409
|
+
resolve4.normalizeId = normalizeId;
|
|
201410
|
+
resolve4.fullPath = getFullPath;
|
|
201411
|
+
resolve4.url = resolveUrl;
|
|
201412
|
+
resolve4.ids = resolveIds;
|
|
201413
|
+
resolve4.inlineRef = inlineRef;
|
|
201414
|
+
resolve4.schema = resolveSchema;
|
|
201415
|
+
function resolve4(compile, root, ref) {
|
|
201416
201416
|
var refVal = this._refs[ref];
|
|
201417
201417
|
if (typeof refVal == "string") {
|
|
201418
201418
|
if (this._refs[refVal])
|
|
201419
201419
|
refVal = this._refs[refVal];
|
|
201420
201420
|
else
|
|
201421
|
-
return
|
|
201421
|
+
return resolve4.call(this, compile, root, refVal);
|
|
201422
201422
|
}
|
|
201423
201423
|
refVal = refVal || this._schemas[ref];
|
|
201424
201424
|
if (refVal instanceof SchemaObject) {
|
|
@@ -201641,7 +201641,7 @@ var require_resolve2 = __commonJS((exports, module) => {
|
|
|
201641
201641
|
|
|
201642
201642
|
// ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/compile/error_classes.js
|
|
201643
201643
|
var require_error_classes = __commonJS((exports, module) => {
|
|
201644
|
-
var
|
|
201644
|
+
var resolve4 = require_resolve2();
|
|
201645
201645
|
module.exports = {
|
|
201646
201646
|
Validation: errorSubclass(ValidationError),
|
|
201647
201647
|
MissingRef: errorSubclass(MissingRefError)
|
|
@@ -201656,8 +201656,8 @@ var require_error_classes = __commonJS((exports, module) => {
|
|
|
201656
201656
|
};
|
|
201657
201657
|
function MissingRefError(baseId, ref, message) {
|
|
201658
201658
|
this.message = message || MissingRefError.message(baseId, ref);
|
|
201659
|
-
this.missingRef =
|
|
201660
|
-
this.missingSchema =
|
|
201659
|
+
this.missingRef = resolve4.url(baseId, ref);
|
|
201660
|
+
this.missingSchema = resolve4.normalizeId(resolve4.fullPath(this.missingRef));
|
|
201661
201661
|
}
|
|
201662
201662
|
function errorSubclass(Subclass) {
|
|
201663
201663
|
Subclass.prototype = Object.create(Error.prototype);
|
|
@@ -202199,7 +202199,7 @@ var require_validate4 = __commonJS((exports, module) => {
|
|
|
202199
202199
|
|
|
202200
202200
|
// ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/compile/index.js
|
|
202201
202201
|
var require_compile2 = __commonJS((exports, module) => {
|
|
202202
|
-
var
|
|
202202
|
+
var resolve4 = require_resolve2();
|
|
202203
202203
|
var util5 = require_util13();
|
|
202204
202204
|
var errorClasses = require_error_classes();
|
|
202205
202205
|
var stableStringify = require_fast_json_stable_stringify();
|
|
@@ -202259,7 +202259,7 @@ var require_compile2 = __commonJS((exports, module) => {
|
|
|
202259
202259
|
RULES,
|
|
202260
202260
|
validate: validateGenerator,
|
|
202261
202261
|
util: util5,
|
|
202262
|
-
resolve:
|
|
202262
|
+
resolve: resolve4,
|
|
202263
202263
|
resolveRef,
|
|
202264
202264
|
usePattern,
|
|
202265
202265
|
useDefault,
|
|
@@ -202298,7 +202298,7 @@ var require_compile2 = __commonJS((exports, module) => {
|
|
|
202298
202298
|
return validate;
|
|
202299
202299
|
}
|
|
202300
202300
|
function resolveRef(baseId2, ref, isRoot) {
|
|
202301
|
-
ref =
|
|
202301
|
+
ref = resolve4.url(baseId2, ref);
|
|
202302
202302
|
var refIndex = refs[ref];
|
|
202303
202303
|
var _refVal, refCode;
|
|
202304
202304
|
if (refIndex !== undefined) {
|
|
@@ -202315,11 +202315,11 @@ var require_compile2 = __commonJS((exports, module) => {
|
|
|
202315
202315
|
}
|
|
202316
202316
|
}
|
|
202317
202317
|
refCode = addLocalRef(ref);
|
|
202318
|
-
var v2 =
|
|
202318
|
+
var v2 = resolve4.call(self2, localCompile, root, ref);
|
|
202319
202319
|
if (v2 === undefined) {
|
|
202320
202320
|
var localSchema = localRefs && localRefs[ref];
|
|
202321
202321
|
if (localSchema) {
|
|
202322
|
-
v2 =
|
|
202322
|
+
v2 = resolve4.inlineRef(localSchema, opts.inlineRefs) ? localSchema : compile.call(self2, localSchema, root, localRefs, baseId2);
|
|
202323
202323
|
}
|
|
202324
202324
|
}
|
|
202325
202325
|
if (v2 === undefined) {
|
|
@@ -205836,7 +205836,7 @@ var require_data2 = __commonJS((exports, module) => {
|
|
|
205836
205836
|
// ../../node_modules/@modelcontextprotocol/sdk/node_modules/ajv/lib/ajv.js
|
|
205837
205837
|
var require_ajv = __commonJS((exports, module) => {
|
|
205838
205838
|
var compileSchema = require_compile2();
|
|
205839
|
-
var
|
|
205839
|
+
var resolve4 = require_resolve2();
|
|
205840
205840
|
var Cache = require_cache();
|
|
205841
205841
|
var SchemaObject = require_schema_obj();
|
|
205842
205842
|
var stableStringify = require_fast_json_stable_stringify();
|
|
@@ -205928,7 +205928,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
205928
205928
|
var id = this._getId(schema);
|
|
205929
205929
|
if (id !== undefined && typeof id != "string")
|
|
205930
205930
|
throw new Error("schema id must be string");
|
|
205931
|
-
key =
|
|
205931
|
+
key = resolve4.normalizeId(key || id);
|
|
205932
205932
|
checkUnique(this, key);
|
|
205933
205933
|
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
|
|
205934
205934
|
return this;
|
|
@@ -205974,7 +205974,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
205974
205974
|
}
|
|
205975
205975
|
}
|
|
205976
205976
|
function _getSchemaFragment(self2, ref) {
|
|
205977
|
-
var res =
|
|
205977
|
+
var res = resolve4.schema.call(self2, { schema: {} }, ref);
|
|
205978
205978
|
if (res) {
|
|
205979
205979
|
var { schema, root, baseId } = res;
|
|
205980
205980
|
var v = compileSchema.call(self2, schema, root, undefined, baseId);
|
|
@@ -205990,7 +205990,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
205990
205990
|
}
|
|
205991
205991
|
}
|
|
205992
205992
|
function _getSchemaObj(self2, keyRef) {
|
|
205993
|
-
keyRef =
|
|
205993
|
+
keyRef = resolve4.normalizeId(keyRef);
|
|
205994
205994
|
return self2._schemas[keyRef] || self2._refs[keyRef] || self2._fragments[keyRef];
|
|
205995
205995
|
}
|
|
205996
205996
|
function removeSchema(schemaKeyRef) {
|
|
@@ -206018,7 +206018,7 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
206018
206018
|
this._cache.del(cacheKey);
|
|
206019
206019
|
var id = this._getId(schemaKeyRef);
|
|
206020
206020
|
if (id) {
|
|
206021
|
-
id =
|
|
206021
|
+
id = resolve4.normalizeId(id);
|
|
206022
206022
|
delete this._schemas[id];
|
|
206023
206023
|
delete this._refs[id];
|
|
206024
206024
|
}
|
|
@@ -206043,14 +206043,14 @@ var require_ajv = __commonJS((exports, module) => {
|
|
|
206043
206043
|
if (cached)
|
|
206044
206044
|
return cached;
|
|
206045
206045
|
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
|
|
206046
|
-
var id =
|
|
206046
|
+
var id = resolve4.normalizeId(this._getId(schema));
|
|
206047
206047
|
if (id && shouldAddSchema)
|
|
206048
206048
|
checkUnique(this, id);
|
|
206049
206049
|
var willValidate = this._opts.validateSchema !== false && !skipValidation;
|
|
206050
206050
|
var recursiveMeta;
|
|
206051
|
-
if (willValidate && !(recursiveMeta = id && id ==
|
|
206051
|
+
if (willValidate && !(recursiveMeta = id && id == resolve4.normalizeId(schema.$schema)))
|
|
206052
206052
|
this.validateSchema(schema, true);
|
|
206053
|
-
var localRefs =
|
|
206053
|
+
var localRefs = resolve4.ids.call(this, schema);
|
|
206054
206054
|
var schemaObj = new SchemaObject({
|
|
206055
206055
|
id,
|
|
206056
206056
|
schema,
|
|
@@ -209093,7 +209093,7 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209093
209093
|
}
|
|
209094
209094
|
path12 = url2.path;
|
|
209095
209095
|
}
|
|
209096
|
-
var
|
|
209096
|
+
var isAbsolute4 = exports.isAbsolute(path12);
|
|
209097
209097
|
var parts = path12.split(/\/+/);
|
|
209098
209098
|
for (var part, up = 0, i = parts.length - 1;i >= 0; i--) {
|
|
209099
209099
|
part = parts[i];
|
|
@@ -209113,7 +209113,7 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209113
209113
|
}
|
|
209114
209114
|
path12 = parts.join("/");
|
|
209115
209115
|
if (path12 === "") {
|
|
209116
|
-
path12 =
|
|
209116
|
+
path12 = isAbsolute4 ? "/" : ".";
|
|
209117
209117
|
}
|
|
209118
209118
|
if (url2) {
|
|
209119
209119
|
url2.path = path12;
|
|
@@ -209122,7 +209122,7 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209122
209122
|
return path12;
|
|
209123
209123
|
}
|
|
209124
209124
|
exports.normalize = normalize2;
|
|
209125
|
-
function
|
|
209125
|
+
function join8(aRoot, aPath) {
|
|
209126
209126
|
if (aRoot === "") {
|
|
209127
209127
|
aRoot = ".";
|
|
209128
209128
|
}
|
|
@@ -209154,7 +209154,7 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209154
209154
|
}
|
|
209155
209155
|
return joined;
|
|
209156
209156
|
}
|
|
209157
|
-
exports.join =
|
|
209157
|
+
exports.join = join8;
|
|
209158
209158
|
exports.isAbsolute = function(aPath) {
|
|
209159
209159
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
209160
209160
|
};
|
|
@@ -209327,7 +209327,7 @@ var require_util14 = __commonJS((exports) => {
|
|
|
209327
209327
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
209328
209328
|
}
|
|
209329
209329
|
}
|
|
209330
|
-
sourceURL =
|
|
209330
|
+
sourceURL = join8(urlGenerate(parsed), sourceURL);
|
|
209331
209331
|
}
|
|
209332
209332
|
return normalize2(sourceURL);
|
|
209333
209333
|
}
|
|
@@ -217008,6 +217008,8 @@ function internalErrorToHttpError(error) {
|
|
|
217008
217008
|
return httpError(409, error.message);
|
|
217009
217009
|
} else if (error instanceof InvalidStateTransitionError) {
|
|
217010
217010
|
return httpError(409, error.message);
|
|
217011
|
+
} else if (error instanceof ServiceUnavailableError) {
|
|
217012
|
+
return httpError(503, error.message);
|
|
217011
217013
|
} else {
|
|
217012
217014
|
return httpError(500, error.message);
|
|
217013
217015
|
}
|
|
@@ -217100,6 +217102,12 @@ class InvalidStateTransitionError extends Error {
|
|
|
217100
217102
|
}
|
|
217101
217103
|
}
|
|
217102
217104
|
|
|
217105
|
+
class ServiceUnavailableError extends Error {
|
|
217106
|
+
constructor(message) {
|
|
217107
|
+
super(message);
|
|
217108
|
+
}
|
|
217109
|
+
}
|
|
217110
|
+
|
|
217103
217111
|
// src/service/connection.ts
|
|
217104
217112
|
import"@malloydata/db-bigquery";
|
|
217105
217113
|
import"@malloydata/db-databricks";
|
|
@@ -223161,7 +223169,6 @@ class ModelController {
|
|
|
223161
223169
|
}
|
|
223162
223170
|
|
|
223163
223171
|
// src/controller/package.controller.ts
|
|
223164
|
-
import * as path3 from "path";
|
|
223165
223172
|
class PackageController {
|
|
223166
223173
|
environmentStore;
|
|
223167
223174
|
manifestService;
|
|
@@ -223175,11 +223182,20 @@ class PackageController {
|
|
|
223175
223182
|
}
|
|
223176
223183
|
async getPackage(environmentName, packageName, reload) {
|
|
223177
223184
|
const environment = await this.environmentStore.getEnvironment(environmentName, false);
|
|
223178
|
-
|
|
223179
|
-
|
|
223180
|
-
|
|
223181
|
-
|
|
223185
|
+
if (reload) {
|
|
223186
|
+
let location;
|
|
223187
|
+
try {
|
|
223188
|
+
const cached = await environment.getPackage(packageName, false);
|
|
223189
|
+
location = cached.getPackageMetadata().location;
|
|
223190
|
+
} catch {}
|
|
223191
|
+
if (location) {
|
|
223192
|
+
const reinstalled = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, location, stagingPath));
|
|
223193
|
+
return reinstalled.getPackageMetadata();
|
|
223194
|
+
}
|
|
223195
|
+
const _package2 = await environment.getPackage(packageName, true);
|
|
223196
|
+
return _package2.getPackageMetadata();
|
|
223182
223197
|
}
|
|
223198
|
+
const _package = await environment.getPackage(packageName, false);
|
|
223183
223199
|
return _package.getPackageMetadata();
|
|
223184
223200
|
}
|
|
223185
223201
|
async addPackage(environmentName, body, options) {
|
|
@@ -223189,14 +223205,18 @@ class PackageController {
|
|
|
223189
223205
|
if (!body.name) {
|
|
223190
223206
|
throw new BadRequestError("Package name is required");
|
|
223191
223207
|
}
|
|
223208
|
+
const packageName = body.name;
|
|
223192
223209
|
const environment = await this.environmentStore.getEnvironment(environmentName, false);
|
|
223210
|
+
let result;
|
|
223193
223211
|
if (body.location) {
|
|
223194
|
-
|
|
223212
|
+
const bodyLocation = body.location;
|
|
223213
|
+
result = await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath));
|
|
223214
|
+
} else {
|
|
223215
|
+
result = await environment.addPackage(packageName);
|
|
223195
223216
|
}
|
|
223196
|
-
|
|
223197
|
-
await this.environmentStore.addPackageToDatabase(environmentName, body.name);
|
|
223217
|
+
await this.environmentStore.addPackageToDatabase(environmentName, packageName);
|
|
223198
223218
|
if (options?.autoLoadManifest === true) {
|
|
223199
|
-
await this.tryLoadExistingManifest(environmentName,
|
|
223219
|
+
await this.tryLoadExistingManifest(environmentName, packageName);
|
|
223200
223220
|
}
|
|
223201
223221
|
return result;
|
|
223202
223222
|
}
|
|
@@ -223238,24 +223258,24 @@ class PackageController {
|
|
|
223238
223258
|
}
|
|
223239
223259
|
const environment = await this.environmentStore.getEnvironment(environmentName, false);
|
|
223240
223260
|
if (body.location) {
|
|
223241
|
-
|
|
223261
|
+
const bodyLocation = body.location;
|
|
223262
|
+
await environment.installPackage(packageName, (stagingPath) => this.downloadInto(environmentName, packageName, bodyLocation, stagingPath));
|
|
223242
223263
|
}
|
|
223243
223264
|
const result = await environment.updatePackage(packageName, body);
|
|
223244
223265
|
await this.environmentStore.addPackageToDatabase(environmentName, packageName);
|
|
223245
223266
|
return result;
|
|
223246
223267
|
}
|
|
223247
|
-
async
|
|
223248
|
-
const absoluteTargetPath = path3.join(this.environmentStore.serverRootPath, PUBLISHER_DATA_DIR, environmentName, packageName);
|
|
223268
|
+
async downloadInto(environmentName, packageName, packageLocation, targetPath) {
|
|
223249
223269
|
const isCompressedFile = packageLocation.endsWith(".zip");
|
|
223250
223270
|
if (packageLocation.startsWith("https://") || packageLocation.startsWith("git@")) {
|
|
223251
|
-
await this.environmentStore.downloadGitHubDirectory(packageLocation,
|
|
223271
|
+
await this.environmentStore.downloadGitHubDirectory(packageLocation, targetPath);
|
|
223252
223272
|
} else if (packageLocation.startsWith("gs://")) {
|
|
223253
|
-
await this.environmentStore.downloadGcsDirectory(packageLocation, environmentName,
|
|
223273
|
+
await this.environmentStore.downloadGcsDirectory(packageLocation, environmentName, targetPath, isCompressedFile);
|
|
223254
223274
|
} else if (packageLocation.startsWith("s3://")) {
|
|
223255
|
-
await this.environmentStore.downloadS3Directory(packageLocation, environmentName,
|
|
223275
|
+
await this.environmentStore.downloadS3Directory(packageLocation, environmentName, targetPath, isCompressedFile);
|
|
223256
223276
|
}
|
|
223257
223277
|
if (packageLocation.startsWith("/")) {
|
|
223258
|
-
await this.environmentStore.mountLocalDirectory(packageLocation,
|
|
223278
|
+
await this.environmentStore.mountLocalDirectory(packageLocation, targetPath, environmentName, packageName);
|
|
223259
223279
|
}
|
|
223260
223280
|
}
|
|
223261
223281
|
}
|
|
@@ -223369,7 +223389,7 @@ class ReaddirpStream extends Readable2 {
|
|
|
223369
223389
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
223370
223390
|
const statMethod = opts.lstat ? lstat : stat;
|
|
223371
223391
|
if (wantBigintFsStats) {
|
|
223372
|
-
this._stat = (
|
|
223392
|
+
this._stat = (path3) => statMethod(path3, { bigint: true });
|
|
223373
223393
|
} else {
|
|
223374
223394
|
this._stat = statMethod;
|
|
223375
223395
|
}
|
|
@@ -223394,8 +223414,8 @@ class ReaddirpStream extends Readable2 {
|
|
|
223394
223414
|
const par = this.parent;
|
|
223395
223415
|
const fil = par && par.files;
|
|
223396
223416
|
if (fil && fil.length > 0) {
|
|
223397
|
-
const { path:
|
|
223398
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
223417
|
+
const { path: path3, depth } = par;
|
|
223418
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path3));
|
|
223399
223419
|
const awaited = await Promise.all(slice);
|
|
223400
223420
|
for (const entry of awaited) {
|
|
223401
223421
|
if (!entry)
|
|
@@ -223435,20 +223455,20 @@ class ReaddirpStream extends Readable2 {
|
|
|
223435
223455
|
this.reading = false;
|
|
223436
223456
|
}
|
|
223437
223457
|
}
|
|
223438
|
-
async _exploreDir(
|
|
223458
|
+
async _exploreDir(path3, depth) {
|
|
223439
223459
|
let files;
|
|
223440
223460
|
try {
|
|
223441
|
-
files = await readdir(
|
|
223461
|
+
files = await readdir(path3, this._rdOptions);
|
|
223442
223462
|
} catch (error) {
|
|
223443
223463
|
this._onError(error);
|
|
223444
223464
|
}
|
|
223445
|
-
return { files, depth, path:
|
|
223465
|
+
return { files, depth, path: path3 };
|
|
223446
223466
|
}
|
|
223447
|
-
async _formatEntry(dirent,
|
|
223467
|
+
async _formatEntry(dirent, path3) {
|
|
223448
223468
|
let entry;
|
|
223449
223469
|
const basename = this._isDirent ? dirent.name : dirent;
|
|
223450
223470
|
try {
|
|
223451
|
-
const fullPath = presolve(pjoin(
|
|
223471
|
+
const fullPath = presolve(pjoin(path3, basename));
|
|
223452
223472
|
entry = { path: prelative(this._root, fullPath), fullPath, basename };
|
|
223453
223473
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
223454
223474
|
} catch (err) {
|
|
@@ -223847,16 +223867,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
223847
223867
|
};
|
|
223848
223868
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
223849
223869
|
var FsWatchInstances = new Map;
|
|
223850
|
-
function createFsWatchInstance(
|
|
223870
|
+
function createFsWatchInstance(path3, options, listener, errHandler, emitRaw) {
|
|
223851
223871
|
const handleEvent = (rawEvent, evPath) => {
|
|
223852
|
-
listener(
|
|
223853
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
223854
|
-
if (evPath &&
|
|
223855
|
-
fsWatchBroadcast(sysPath.resolve(
|
|
223872
|
+
listener(path3);
|
|
223873
|
+
emitRaw(rawEvent, evPath, { watchedPath: path3 });
|
|
223874
|
+
if (evPath && path3 !== evPath) {
|
|
223875
|
+
fsWatchBroadcast(sysPath.resolve(path3, evPath), KEY_LISTENERS, sysPath.join(path3, evPath));
|
|
223856
223876
|
}
|
|
223857
223877
|
};
|
|
223858
223878
|
try {
|
|
223859
|
-
return fs_watch(
|
|
223879
|
+
return fs_watch(path3, {
|
|
223860
223880
|
persistent: options.persistent
|
|
223861
223881
|
}, handleEvent);
|
|
223862
223882
|
} catch (error) {
|
|
@@ -223872,12 +223892,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
223872
223892
|
listener(val1, val2, val3);
|
|
223873
223893
|
});
|
|
223874
223894
|
};
|
|
223875
|
-
var setFsWatchListener = (
|
|
223895
|
+
var setFsWatchListener = (path3, fullPath, options, handlers) => {
|
|
223876
223896
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
223877
223897
|
let cont = FsWatchInstances.get(fullPath);
|
|
223878
223898
|
let watcher;
|
|
223879
223899
|
if (!options.persistent) {
|
|
223880
|
-
watcher = createFsWatchInstance(
|
|
223900
|
+
watcher = createFsWatchInstance(path3, options, listener, errHandler, rawEmitter);
|
|
223881
223901
|
if (!watcher)
|
|
223882
223902
|
return;
|
|
223883
223903
|
return watcher.close.bind(watcher);
|
|
@@ -223887,7 +223907,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
|
|
|
223887
223907
|
addAndConvert(cont, KEY_ERR, errHandler);
|
|
223888
223908
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
223889
223909
|
} else {
|
|
223890
|
-
watcher = createFsWatchInstance(
|
|
223910
|
+
watcher = createFsWatchInstance(path3, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
|
|
223891
223911
|
if (!watcher)
|
|
223892
223912
|
return;
|
|
223893
223913
|
watcher.on(EV.ERROR, async (error) => {
|
|
@@ -223896,7 +223916,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
|
|
|
223896
223916
|
cont.watcherUnusable = true;
|
|
223897
223917
|
if (isWindows && error.code === "EPERM") {
|
|
223898
223918
|
try {
|
|
223899
|
-
const fd = await open(
|
|
223919
|
+
const fd = await open(path3, "r");
|
|
223900
223920
|
await fd.close();
|
|
223901
223921
|
broadcastErr(error);
|
|
223902
223922
|
} catch (err) {}
|
|
@@ -223926,7 +223946,7 @@ var setFsWatchListener = (path4, fullPath, options, handlers) => {
|
|
|
223926
223946
|
};
|
|
223927
223947
|
};
|
|
223928
223948
|
var FsWatchFileInstances = new Map;
|
|
223929
|
-
var setFsWatchFileListener = (
|
|
223949
|
+
var setFsWatchFileListener = (path3, fullPath, options, handlers) => {
|
|
223930
223950
|
const { listener, rawEmitter } = handlers;
|
|
223931
223951
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
223932
223952
|
const copts = cont && cont.options;
|
|
@@ -223948,7 +223968,7 @@ var setFsWatchFileListener = (path4, fullPath, options, handlers) => {
|
|
|
223948
223968
|
});
|
|
223949
223969
|
const currmtime = curr.mtimeMs;
|
|
223950
223970
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
223951
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
223971
|
+
foreach(cont.listeners, (listener2) => listener2(path3, curr));
|
|
223952
223972
|
}
|
|
223953
223973
|
})
|
|
223954
223974
|
};
|
|
@@ -223971,13 +223991,13 @@ class NodeFsHandler {
|
|
|
223971
223991
|
this.fsw = fsW;
|
|
223972
223992
|
this._boundHandleError = (error) => fsW._handleError(error);
|
|
223973
223993
|
}
|
|
223974
|
-
_watchWithNodeFs(
|
|
223994
|
+
_watchWithNodeFs(path3, listener) {
|
|
223975
223995
|
const opts = this.fsw.options;
|
|
223976
|
-
const directory = sysPath.dirname(
|
|
223977
|
-
const basename2 = sysPath.basename(
|
|
223996
|
+
const directory = sysPath.dirname(path3);
|
|
223997
|
+
const basename2 = sysPath.basename(path3);
|
|
223978
223998
|
const parent = this.fsw._getWatchedDir(directory);
|
|
223979
223999
|
parent.add(basename2);
|
|
223980
|
-
const absolutePath = sysPath.resolve(
|
|
224000
|
+
const absolutePath = sysPath.resolve(path3);
|
|
223981
224001
|
const options = {
|
|
223982
224002
|
persistent: opts.persistent
|
|
223983
224003
|
};
|
|
@@ -223987,12 +224007,12 @@ class NodeFsHandler {
|
|
|
223987
224007
|
if (opts.usePolling) {
|
|
223988
224008
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
223989
224009
|
options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
|
|
223990
|
-
closer = setFsWatchFileListener(
|
|
224010
|
+
closer = setFsWatchFileListener(path3, absolutePath, options, {
|
|
223991
224011
|
listener,
|
|
223992
224012
|
rawEmitter: this.fsw._emitRaw
|
|
223993
224013
|
});
|
|
223994
224014
|
} else {
|
|
223995
|
-
closer = setFsWatchListener(
|
|
224015
|
+
closer = setFsWatchListener(path3, absolutePath, options, {
|
|
223996
224016
|
listener,
|
|
223997
224017
|
errHandler: this._boundHandleError,
|
|
223998
224018
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -224010,7 +224030,7 @@ class NodeFsHandler {
|
|
|
224010
224030
|
let prevStats = stats;
|
|
224011
224031
|
if (parent.has(basename2))
|
|
224012
224032
|
return;
|
|
224013
|
-
const listener = async (
|
|
224033
|
+
const listener = async (path3, newStats) => {
|
|
224014
224034
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
224015
224035
|
return;
|
|
224016
224036
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -224024,11 +224044,11 @@ class NodeFsHandler {
|
|
|
224024
224044
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
224025
224045
|
}
|
|
224026
224046
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
224027
|
-
this.fsw._closeFile(
|
|
224047
|
+
this.fsw._closeFile(path3);
|
|
224028
224048
|
prevStats = newStats2;
|
|
224029
224049
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
224030
224050
|
if (closer2)
|
|
224031
|
-
this.fsw._addPathCloser(
|
|
224051
|
+
this.fsw._addPathCloser(path3, closer2);
|
|
224032
224052
|
} else {
|
|
224033
224053
|
prevStats = newStats2;
|
|
224034
224054
|
}
|
|
@@ -224052,7 +224072,7 @@ class NodeFsHandler {
|
|
|
224052
224072
|
}
|
|
224053
224073
|
return closer;
|
|
224054
224074
|
}
|
|
224055
|
-
async _handleSymlink(entry, directory,
|
|
224075
|
+
async _handleSymlink(entry, directory, path3, item) {
|
|
224056
224076
|
if (this.fsw.closed) {
|
|
224057
224077
|
return;
|
|
224058
224078
|
}
|
|
@@ -224062,7 +224082,7 @@ class NodeFsHandler {
|
|
|
224062
224082
|
this.fsw._incrReadyCount();
|
|
224063
224083
|
let linkPath;
|
|
224064
224084
|
try {
|
|
224065
|
-
linkPath = await fsrealpath(
|
|
224085
|
+
linkPath = await fsrealpath(path3);
|
|
224066
224086
|
} catch (e) {
|
|
224067
224087
|
this.fsw._emitReady();
|
|
224068
224088
|
return true;
|
|
@@ -224072,12 +224092,12 @@ class NodeFsHandler {
|
|
|
224072
224092
|
if (dir.has(item)) {
|
|
224073
224093
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
224074
224094
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
224075
|
-
this.fsw._emit(EV.CHANGE,
|
|
224095
|
+
this.fsw._emit(EV.CHANGE, path3, entry.stats);
|
|
224076
224096
|
}
|
|
224077
224097
|
} else {
|
|
224078
224098
|
dir.add(item);
|
|
224079
224099
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
224080
|
-
this.fsw._emit(EV.ADD,
|
|
224100
|
+
this.fsw._emit(EV.ADD, path3, entry.stats);
|
|
224081
224101
|
}
|
|
224082
224102
|
this.fsw._emitReady();
|
|
224083
224103
|
return true;
|
|
@@ -224106,9 +224126,9 @@ class NodeFsHandler {
|
|
|
224106
224126
|
return;
|
|
224107
224127
|
}
|
|
224108
224128
|
const item = entry.path;
|
|
224109
|
-
let
|
|
224129
|
+
let path3 = sysPath.join(directory, item);
|
|
224110
224130
|
current.add(item);
|
|
224111
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
224131
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path3, item)) {
|
|
224112
224132
|
return;
|
|
224113
224133
|
}
|
|
224114
224134
|
if (this.fsw.closed) {
|
|
@@ -224117,8 +224137,8 @@ class NodeFsHandler {
|
|
|
224117
224137
|
}
|
|
224118
224138
|
if (item === target || !target && !previous.has(item)) {
|
|
224119
224139
|
this.fsw._incrReadyCount();
|
|
224120
|
-
|
|
224121
|
-
this._addToNodeFs(
|
|
224140
|
+
path3 = sysPath.join(dir, sysPath.relative(dir, path3));
|
|
224141
|
+
this._addToNodeFs(path3, initialAdd, wh, depth + 1);
|
|
224122
224142
|
}
|
|
224123
224143
|
}).on(EV.ERROR, this._boundHandleError);
|
|
224124
224144
|
return new Promise((resolve2, reject) => {
|
|
@@ -224167,13 +224187,13 @@ class NodeFsHandler {
|
|
|
224167
224187
|
}
|
|
224168
224188
|
return closer;
|
|
224169
224189
|
}
|
|
224170
|
-
async _addToNodeFs(
|
|
224190
|
+
async _addToNodeFs(path3, initialAdd, priorWh, depth, target) {
|
|
224171
224191
|
const ready = this.fsw._emitReady;
|
|
224172
|
-
if (this.fsw._isIgnored(
|
|
224192
|
+
if (this.fsw._isIgnored(path3) || this.fsw.closed) {
|
|
224173
224193
|
ready();
|
|
224174
224194
|
return false;
|
|
224175
224195
|
}
|
|
224176
|
-
const wh = this.fsw._getWatchHelpers(
|
|
224196
|
+
const wh = this.fsw._getWatchHelpers(path3);
|
|
224177
224197
|
if (priorWh) {
|
|
224178
224198
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
224179
224199
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -224189,8 +224209,8 @@ class NodeFsHandler {
|
|
|
224189
224209
|
const follow = this.fsw.options.followSymlinks;
|
|
224190
224210
|
let closer;
|
|
224191
224211
|
if (stats.isDirectory()) {
|
|
224192
|
-
const absPath = sysPath.resolve(
|
|
224193
|
-
const targetPath = follow ? await fsrealpath(
|
|
224212
|
+
const absPath = sysPath.resolve(path3);
|
|
224213
|
+
const targetPath = follow ? await fsrealpath(path3) : path3;
|
|
224194
224214
|
if (this.fsw.closed)
|
|
224195
224215
|
return;
|
|
224196
224216
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -224200,29 +224220,29 @@ class NodeFsHandler {
|
|
|
224200
224220
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
224201
224221
|
}
|
|
224202
224222
|
} else if (stats.isSymbolicLink()) {
|
|
224203
|
-
const targetPath = follow ? await fsrealpath(
|
|
224223
|
+
const targetPath = follow ? await fsrealpath(path3) : path3;
|
|
224204
224224
|
if (this.fsw.closed)
|
|
224205
224225
|
return;
|
|
224206
224226
|
const parent = sysPath.dirname(wh.watchPath);
|
|
224207
224227
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
224208
224228
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
224209
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
224229
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path3, wh, targetPath);
|
|
224210
224230
|
if (this.fsw.closed)
|
|
224211
224231
|
return;
|
|
224212
224232
|
if (targetPath !== undefined) {
|
|
224213
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(
|
|
224233
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path3), targetPath);
|
|
224214
224234
|
}
|
|
224215
224235
|
} else {
|
|
224216
224236
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
224217
224237
|
}
|
|
224218
224238
|
ready();
|
|
224219
224239
|
if (closer)
|
|
224220
|
-
this.fsw._addPathCloser(
|
|
224240
|
+
this.fsw._addPathCloser(path3, closer);
|
|
224221
224241
|
return false;
|
|
224222
224242
|
} catch (error) {
|
|
224223
224243
|
if (this.fsw._handleError(error)) {
|
|
224224
224244
|
ready();
|
|
224225
|
-
return
|
|
224245
|
+
return path3;
|
|
224226
224246
|
}
|
|
224227
224247
|
}
|
|
224228
224248
|
}
|
|
@@ -224266,26 +224286,26 @@ function createPattern(matcher) {
|
|
|
224266
224286
|
}
|
|
224267
224287
|
return () => false;
|
|
224268
224288
|
}
|
|
224269
|
-
function normalizePath(
|
|
224270
|
-
if (typeof
|
|
224289
|
+
function normalizePath(path3) {
|
|
224290
|
+
if (typeof path3 !== "string")
|
|
224271
224291
|
throw new Error("string expected");
|
|
224272
|
-
|
|
224273
|
-
|
|
224292
|
+
path3 = sysPath2.normalize(path3);
|
|
224293
|
+
path3 = path3.replace(/\\/g, "/");
|
|
224274
224294
|
let prepend = false;
|
|
224275
|
-
if (
|
|
224295
|
+
if (path3.startsWith("//"))
|
|
224276
224296
|
prepend = true;
|
|
224277
224297
|
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
224278
|
-
while (
|
|
224279
|
-
|
|
224298
|
+
while (path3.match(DOUBLE_SLASH_RE2))
|
|
224299
|
+
path3 = path3.replace(DOUBLE_SLASH_RE2, "/");
|
|
224280
224300
|
if (prepend)
|
|
224281
|
-
|
|
224282
|
-
return
|
|
224301
|
+
path3 = "/" + path3;
|
|
224302
|
+
return path3;
|
|
224283
224303
|
}
|
|
224284
224304
|
function matchPatterns(patterns, testString, stats) {
|
|
224285
|
-
const
|
|
224305
|
+
const path3 = normalizePath(testString);
|
|
224286
224306
|
for (let index = 0;index < patterns.length; index++) {
|
|
224287
224307
|
const pattern = patterns[index];
|
|
224288
|
-
if (pattern(
|
|
224308
|
+
if (pattern(path3, stats)) {
|
|
224289
224309
|
return true;
|
|
224290
224310
|
}
|
|
224291
224311
|
}
|
|
@@ -224325,19 +224345,19 @@ var toUnix = (string) => {
|
|
|
224325
224345
|
}
|
|
224326
224346
|
return str;
|
|
224327
224347
|
};
|
|
224328
|
-
var normalizePathToUnix = (
|
|
224329
|
-
var normalizeIgnored = (cwd = "") => (
|
|
224330
|
-
if (typeof
|
|
224331
|
-
return normalizePathToUnix(sysPath2.isAbsolute(
|
|
224348
|
+
var normalizePathToUnix = (path3) => toUnix(sysPath2.normalize(toUnix(path3)));
|
|
224349
|
+
var normalizeIgnored = (cwd = "") => (path3) => {
|
|
224350
|
+
if (typeof path3 === "string") {
|
|
224351
|
+
return normalizePathToUnix(sysPath2.isAbsolute(path3) ? path3 : sysPath2.join(cwd, path3));
|
|
224332
224352
|
} else {
|
|
224333
|
-
return
|
|
224353
|
+
return path3;
|
|
224334
224354
|
}
|
|
224335
224355
|
};
|
|
224336
|
-
var getAbsolutePath = (
|
|
224337
|
-
if (sysPath2.isAbsolute(
|
|
224338
|
-
return
|
|
224356
|
+
var getAbsolutePath = (path3, cwd) => {
|
|
224357
|
+
if (sysPath2.isAbsolute(path3)) {
|
|
224358
|
+
return path3;
|
|
224339
224359
|
}
|
|
224340
|
-
return sysPath2.join(cwd,
|
|
224360
|
+
return sysPath2.join(cwd, path3);
|
|
224341
224361
|
};
|
|
224342
224362
|
var EMPTY_SET = Object.freeze(new Set);
|
|
224343
224363
|
|
|
@@ -224394,10 +224414,10 @@ var STAT_METHOD_F = "stat";
|
|
|
224394
224414
|
var STAT_METHOD_L = "lstat";
|
|
224395
224415
|
|
|
224396
224416
|
class WatchHelper {
|
|
224397
|
-
constructor(
|
|
224417
|
+
constructor(path3, follow, fsw) {
|
|
224398
224418
|
this.fsw = fsw;
|
|
224399
|
-
const watchPath =
|
|
224400
|
-
this.path =
|
|
224419
|
+
const watchPath = path3;
|
|
224420
|
+
this.path = path3 = path3.replace(REPLACER_RE, "");
|
|
224401
224421
|
this.watchPath = watchPath;
|
|
224402
224422
|
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
224403
224423
|
this.dirParts = [];
|
|
@@ -224510,20 +224530,20 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224510
224530
|
this._closePromise = undefined;
|
|
224511
224531
|
let paths = unifyPaths(paths_);
|
|
224512
224532
|
if (cwd) {
|
|
224513
|
-
paths = paths.map((
|
|
224514
|
-
const absPath = getAbsolutePath(
|
|
224533
|
+
paths = paths.map((path3) => {
|
|
224534
|
+
const absPath = getAbsolutePath(path3, cwd);
|
|
224515
224535
|
return absPath;
|
|
224516
224536
|
});
|
|
224517
224537
|
}
|
|
224518
|
-
paths.forEach((
|
|
224519
|
-
this._removeIgnoredPath(
|
|
224538
|
+
paths.forEach((path3) => {
|
|
224539
|
+
this._removeIgnoredPath(path3);
|
|
224520
224540
|
});
|
|
224521
224541
|
this._userIgnored = undefined;
|
|
224522
224542
|
if (!this._readyCount)
|
|
224523
224543
|
this._readyCount = 0;
|
|
224524
224544
|
this._readyCount += paths.length;
|
|
224525
|
-
Promise.all(paths.map(async (
|
|
224526
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
224545
|
+
Promise.all(paths.map(async (path3) => {
|
|
224546
|
+
const res = await this._nodeFsHandler._addToNodeFs(path3, !_internal, undefined, 0, _origAdd);
|
|
224527
224547
|
if (res)
|
|
224528
224548
|
this._emitReady();
|
|
224529
224549
|
return res;
|
|
@@ -224542,17 +224562,17 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224542
224562
|
return this;
|
|
224543
224563
|
const paths = unifyPaths(paths_);
|
|
224544
224564
|
const { cwd } = this.options;
|
|
224545
|
-
paths.forEach((
|
|
224546
|
-
if (!sysPath2.isAbsolute(
|
|
224565
|
+
paths.forEach((path3) => {
|
|
224566
|
+
if (!sysPath2.isAbsolute(path3) && !this._closers.has(path3)) {
|
|
224547
224567
|
if (cwd)
|
|
224548
|
-
|
|
224549
|
-
|
|
224568
|
+
path3 = sysPath2.join(cwd, path3);
|
|
224569
|
+
path3 = sysPath2.resolve(path3);
|
|
224550
224570
|
}
|
|
224551
|
-
this._closePath(
|
|
224552
|
-
this._addIgnoredPath(
|
|
224553
|
-
if (this._watched.has(
|
|
224571
|
+
this._closePath(path3);
|
|
224572
|
+
this._addIgnoredPath(path3);
|
|
224573
|
+
if (this._watched.has(path3)) {
|
|
224554
224574
|
this._addIgnoredPath({
|
|
224555
|
-
path:
|
|
224575
|
+
path: path3,
|
|
224556
224576
|
recursive: true
|
|
224557
224577
|
});
|
|
224558
224578
|
}
|
|
@@ -224601,38 +224621,38 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224601
224621
|
if (event !== EVENTS.ERROR)
|
|
224602
224622
|
this.emit(EVENTS.ALL, event, ...args);
|
|
224603
224623
|
}
|
|
224604
|
-
async _emit(event,
|
|
224624
|
+
async _emit(event, path3, stats) {
|
|
224605
224625
|
if (this.closed)
|
|
224606
224626
|
return;
|
|
224607
224627
|
const opts = this.options;
|
|
224608
224628
|
if (isWindows)
|
|
224609
|
-
|
|
224629
|
+
path3 = sysPath2.normalize(path3);
|
|
224610
224630
|
if (opts.cwd)
|
|
224611
|
-
|
|
224612
|
-
const args = [
|
|
224631
|
+
path3 = sysPath2.relative(opts.cwd, path3);
|
|
224632
|
+
const args = [path3];
|
|
224613
224633
|
if (stats != null)
|
|
224614
224634
|
args.push(stats);
|
|
224615
224635
|
const awf = opts.awaitWriteFinish;
|
|
224616
224636
|
let pw;
|
|
224617
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
224637
|
+
if (awf && (pw = this._pendingWrites.get(path3))) {
|
|
224618
224638
|
pw.lastChange = new Date;
|
|
224619
224639
|
return this;
|
|
224620
224640
|
}
|
|
224621
224641
|
if (opts.atomic) {
|
|
224622
224642
|
if (event === EVENTS.UNLINK) {
|
|
224623
|
-
this._pendingUnlinks.set(
|
|
224643
|
+
this._pendingUnlinks.set(path3, [event, ...args]);
|
|
224624
224644
|
setTimeout(() => {
|
|
224625
|
-
this._pendingUnlinks.forEach((entry,
|
|
224645
|
+
this._pendingUnlinks.forEach((entry, path4) => {
|
|
224626
224646
|
this.emit(...entry);
|
|
224627
224647
|
this.emit(EVENTS.ALL, ...entry);
|
|
224628
|
-
this._pendingUnlinks.delete(
|
|
224648
|
+
this._pendingUnlinks.delete(path4);
|
|
224629
224649
|
});
|
|
224630
224650
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
224631
224651
|
return this;
|
|
224632
224652
|
}
|
|
224633
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
224653
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path3)) {
|
|
224634
224654
|
event = EVENTS.CHANGE;
|
|
224635
|
-
this._pendingUnlinks.delete(
|
|
224655
|
+
this._pendingUnlinks.delete(path3);
|
|
224636
224656
|
}
|
|
224637
224657
|
}
|
|
224638
224658
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -224650,16 +224670,16 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224650
224670
|
this.emitWithAll(event, args);
|
|
224651
224671
|
}
|
|
224652
224672
|
};
|
|
224653
|
-
this._awaitWriteFinish(
|
|
224673
|
+
this._awaitWriteFinish(path3, awf.stabilityThreshold, event, awfEmit);
|
|
224654
224674
|
return this;
|
|
224655
224675
|
}
|
|
224656
224676
|
if (event === EVENTS.CHANGE) {
|
|
224657
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
224677
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path3, 50);
|
|
224658
224678
|
if (isThrottled)
|
|
224659
224679
|
return this;
|
|
224660
224680
|
}
|
|
224661
224681
|
if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
224662
|
-
const fullPath = opts.cwd ? sysPath2.join(opts.cwd,
|
|
224682
|
+
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path3) : path3;
|
|
224663
224683
|
let stats2;
|
|
224664
224684
|
try {
|
|
224665
224685
|
stats2 = await stat3(fullPath);
|
|
@@ -224678,23 +224698,23 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224678
224698
|
}
|
|
224679
224699
|
return error || this.closed;
|
|
224680
224700
|
}
|
|
224681
|
-
_throttle(actionType,
|
|
224701
|
+
_throttle(actionType, path3, timeout) {
|
|
224682
224702
|
if (!this._throttled.has(actionType)) {
|
|
224683
224703
|
this._throttled.set(actionType, new Map);
|
|
224684
224704
|
}
|
|
224685
224705
|
const action = this._throttled.get(actionType);
|
|
224686
224706
|
if (!action)
|
|
224687
224707
|
throw new Error("invalid throttle");
|
|
224688
|
-
const actionPath = action.get(
|
|
224708
|
+
const actionPath = action.get(path3);
|
|
224689
224709
|
if (actionPath) {
|
|
224690
224710
|
actionPath.count++;
|
|
224691
224711
|
return false;
|
|
224692
224712
|
}
|
|
224693
224713
|
let timeoutObject;
|
|
224694
224714
|
const clear = () => {
|
|
224695
|
-
const item = action.get(
|
|
224715
|
+
const item = action.get(path3);
|
|
224696
224716
|
const count = item ? item.count : 0;
|
|
224697
|
-
action.delete(
|
|
224717
|
+
action.delete(path3);
|
|
224698
224718
|
clearTimeout(timeoutObject);
|
|
224699
224719
|
if (item)
|
|
224700
224720
|
clearTimeout(item.timeoutObject);
|
|
@@ -224702,50 +224722,50 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224702
224722
|
};
|
|
224703
224723
|
timeoutObject = setTimeout(clear, timeout);
|
|
224704
224724
|
const thr = { timeoutObject, clear, count: 0 };
|
|
224705
|
-
action.set(
|
|
224725
|
+
action.set(path3, thr);
|
|
224706
224726
|
return thr;
|
|
224707
224727
|
}
|
|
224708
224728
|
_incrReadyCount() {
|
|
224709
224729
|
return this._readyCount++;
|
|
224710
224730
|
}
|
|
224711
|
-
_awaitWriteFinish(
|
|
224731
|
+
_awaitWriteFinish(path3, threshold, event, awfEmit) {
|
|
224712
224732
|
const awf = this.options.awaitWriteFinish;
|
|
224713
224733
|
if (typeof awf !== "object")
|
|
224714
224734
|
return;
|
|
224715
224735
|
const pollInterval = awf.pollInterval;
|
|
224716
224736
|
let timeoutHandler;
|
|
224717
|
-
let fullPath =
|
|
224718
|
-
if (this.options.cwd && !sysPath2.isAbsolute(
|
|
224719
|
-
fullPath = sysPath2.join(this.options.cwd,
|
|
224737
|
+
let fullPath = path3;
|
|
224738
|
+
if (this.options.cwd && !sysPath2.isAbsolute(path3)) {
|
|
224739
|
+
fullPath = sysPath2.join(this.options.cwd, path3);
|
|
224720
224740
|
}
|
|
224721
224741
|
const now = new Date;
|
|
224722
224742
|
const writes = this._pendingWrites;
|
|
224723
224743
|
function awaitWriteFinishFn(prevStat) {
|
|
224724
224744
|
statcb(fullPath, (err, curStat) => {
|
|
224725
|
-
if (err || !writes.has(
|
|
224745
|
+
if (err || !writes.has(path3)) {
|
|
224726
224746
|
if (err && err.code !== "ENOENT")
|
|
224727
224747
|
awfEmit(err);
|
|
224728
224748
|
return;
|
|
224729
224749
|
}
|
|
224730
224750
|
const now2 = Number(new Date);
|
|
224731
224751
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
224732
|
-
writes.get(
|
|
224752
|
+
writes.get(path3).lastChange = now2;
|
|
224733
224753
|
}
|
|
224734
|
-
const pw = writes.get(
|
|
224754
|
+
const pw = writes.get(path3);
|
|
224735
224755
|
const df = now2 - pw.lastChange;
|
|
224736
224756
|
if (df >= threshold) {
|
|
224737
|
-
writes.delete(
|
|
224757
|
+
writes.delete(path3);
|
|
224738
224758
|
awfEmit(undefined, curStat);
|
|
224739
224759
|
} else {
|
|
224740
224760
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
224741
224761
|
}
|
|
224742
224762
|
});
|
|
224743
224763
|
}
|
|
224744
|
-
if (!writes.has(
|
|
224745
|
-
writes.set(
|
|
224764
|
+
if (!writes.has(path3)) {
|
|
224765
|
+
writes.set(path3, {
|
|
224746
224766
|
lastChange: now,
|
|
224747
224767
|
cancelWait: () => {
|
|
224748
|
-
writes.delete(
|
|
224768
|
+
writes.delete(path3);
|
|
224749
224769
|
clearTimeout(timeoutHandler);
|
|
224750
224770
|
return event;
|
|
224751
224771
|
}
|
|
@@ -224753,8 +224773,8 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224753
224773
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
|
|
224754
224774
|
}
|
|
224755
224775
|
}
|
|
224756
|
-
_isIgnored(
|
|
224757
|
-
if (this.options.atomic && DOT_RE.test(
|
|
224776
|
+
_isIgnored(path3, stats) {
|
|
224777
|
+
if (this.options.atomic && DOT_RE.test(path3))
|
|
224758
224778
|
return true;
|
|
224759
224779
|
if (!this._userIgnored) {
|
|
224760
224780
|
const { cwd } = this.options;
|
|
@@ -224764,13 +224784,13 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224764
224784
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
224765
224785
|
this._userIgnored = anymatch(list, undefined);
|
|
224766
224786
|
}
|
|
224767
|
-
return this._userIgnored(
|
|
224787
|
+
return this._userIgnored(path3, stats);
|
|
224768
224788
|
}
|
|
224769
|
-
_isntIgnored(
|
|
224770
|
-
return !this._isIgnored(
|
|
224789
|
+
_isntIgnored(path3, stat4) {
|
|
224790
|
+
return !this._isIgnored(path3, stat4);
|
|
224771
224791
|
}
|
|
224772
|
-
_getWatchHelpers(
|
|
224773
|
-
return new WatchHelper(
|
|
224792
|
+
_getWatchHelpers(path3) {
|
|
224793
|
+
return new WatchHelper(path3, this.options.followSymlinks, this);
|
|
224774
224794
|
}
|
|
224775
224795
|
_getWatchedDir(directory) {
|
|
224776
224796
|
const dir = sysPath2.resolve(directory);
|
|
@@ -224784,57 +224804,57 @@ class FSWatcher extends EventEmitter2 {
|
|
|
224784
224804
|
return Boolean(Number(stats.mode) & 256);
|
|
224785
224805
|
}
|
|
224786
224806
|
_remove(directory, item, isDirectory) {
|
|
224787
|
-
const
|
|
224788
|
-
const fullPath = sysPath2.resolve(
|
|
224789
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
224790
|
-
if (!this._throttle("remove",
|
|
224807
|
+
const path3 = sysPath2.join(directory, item);
|
|
224808
|
+
const fullPath = sysPath2.resolve(path3);
|
|
224809
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path3) || this._watched.has(fullPath);
|
|
224810
|
+
if (!this._throttle("remove", path3, 100))
|
|
224791
224811
|
return;
|
|
224792
224812
|
if (!isDirectory && this._watched.size === 1) {
|
|
224793
224813
|
this.add(directory, item, true);
|
|
224794
224814
|
}
|
|
224795
|
-
const wp = this._getWatchedDir(
|
|
224815
|
+
const wp = this._getWatchedDir(path3);
|
|
224796
224816
|
const nestedDirectoryChildren = wp.getChildren();
|
|
224797
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
224817
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path3, nested));
|
|
224798
224818
|
const parent = this._getWatchedDir(directory);
|
|
224799
224819
|
const wasTracked = parent.has(item);
|
|
224800
224820
|
parent.remove(item);
|
|
224801
224821
|
if (this._symlinkPaths.has(fullPath)) {
|
|
224802
224822
|
this._symlinkPaths.delete(fullPath);
|
|
224803
224823
|
}
|
|
224804
|
-
let relPath =
|
|
224824
|
+
let relPath = path3;
|
|
224805
224825
|
if (this.options.cwd)
|
|
224806
|
-
relPath = sysPath2.relative(this.options.cwd,
|
|
224826
|
+
relPath = sysPath2.relative(this.options.cwd, path3);
|
|
224807
224827
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
224808
224828
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
224809
224829
|
if (event === EVENTS.ADD)
|
|
224810
224830
|
return;
|
|
224811
224831
|
}
|
|
224812
|
-
this._watched.delete(
|
|
224832
|
+
this._watched.delete(path3);
|
|
224813
224833
|
this._watched.delete(fullPath);
|
|
224814
224834
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
224815
|
-
if (wasTracked && !this._isIgnored(
|
|
224816
|
-
this._emit(eventName,
|
|
224817
|
-
this._closePath(
|
|
224835
|
+
if (wasTracked && !this._isIgnored(path3))
|
|
224836
|
+
this._emit(eventName, path3);
|
|
224837
|
+
this._closePath(path3);
|
|
224818
224838
|
}
|
|
224819
|
-
_closePath(
|
|
224820
|
-
this._closeFile(
|
|
224821
|
-
const dir = sysPath2.dirname(
|
|
224822
|
-
this._getWatchedDir(dir).remove(sysPath2.basename(
|
|
224839
|
+
_closePath(path3) {
|
|
224840
|
+
this._closeFile(path3);
|
|
224841
|
+
const dir = sysPath2.dirname(path3);
|
|
224842
|
+
this._getWatchedDir(dir).remove(sysPath2.basename(path3));
|
|
224823
224843
|
}
|
|
224824
|
-
_closeFile(
|
|
224825
|
-
const closers = this._closers.get(
|
|
224844
|
+
_closeFile(path3) {
|
|
224845
|
+
const closers = this._closers.get(path3);
|
|
224826
224846
|
if (!closers)
|
|
224827
224847
|
return;
|
|
224828
224848
|
closers.forEach((closer) => closer());
|
|
224829
|
-
this._closers.delete(
|
|
224849
|
+
this._closers.delete(path3);
|
|
224830
224850
|
}
|
|
224831
|
-
_addPathCloser(
|
|
224851
|
+
_addPathCloser(path3, closer) {
|
|
224832
224852
|
if (!closer)
|
|
224833
224853
|
return;
|
|
224834
|
-
let list = this._closers.get(
|
|
224854
|
+
let list = this._closers.get(path3);
|
|
224835
224855
|
if (!list) {
|
|
224836
224856
|
list = [];
|
|
224837
|
-
this._closers.set(
|
|
224857
|
+
this._closers.set(path3, list);
|
|
224838
224858
|
}
|
|
224839
224859
|
list.push(closer);
|
|
224840
224860
|
}
|
|
@@ -225080,7 +225100,7 @@ class Mutex {
|
|
|
225080
225100
|
}
|
|
225081
225101
|
|
|
225082
225102
|
// src/service/environment_store.ts
|
|
225083
|
-
import
|
|
225103
|
+
import crypto5 from "crypto";
|
|
225084
225104
|
import * as fs7 from "fs";
|
|
225085
225105
|
import * as path10 from "path";
|
|
225086
225106
|
|
|
@@ -225120,8 +225140,8 @@ function pathspec(...paths) {
|
|
|
225120
225140
|
cache.set(key, paths);
|
|
225121
225141
|
return key;
|
|
225122
225142
|
}
|
|
225123
|
-
function isPathSpec(
|
|
225124
|
-
return
|
|
225143
|
+
function isPathSpec(path3) {
|
|
225144
|
+
return path3 instanceof String && cache.has(path3);
|
|
225125
225145
|
}
|
|
225126
225146
|
function toPaths(pathSpec) {
|
|
225127
225147
|
return cache.get(pathSpec) || [];
|
|
@@ -225207,8 +225227,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = `
|
|
|
225207
225227
|
function forEachLineWithContent(input, callback) {
|
|
225208
225228
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
225209
225229
|
}
|
|
225210
|
-
function folderExists(
|
|
225211
|
-
return import_file_exists.exists(
|
|
225230
|
+
function folderExists(path3) {
|
|
225231
|
+
return import_file_exists.exists(path3, import_file_exists.FOLDER);
|
|
225212
225232
|
}
|
|
225213
225233
|
function append2(target, item) {
|
|
225214
225234
|
if (Array.isArray(target)) {
|
|
@@ -225589,8 +225609,8 @@ function checkIsRepoRootTask() {
|
|
|
225589
225609
|
commands,
|
|
225590
225610
|
format: "utf-8",
|
|
225591
225611
|
onError,
|
|
225592
|
-
parser(
|
|
225593
|
-
return /^\.(git)?$/.test(
|
|
225612
|
+
parser(path3) {
|
|
225613
|
+
return /^\.(git)?$/.test(path3.trim());
|
|
225594
225614
|
}
|
|
225595
225615
|
};
|
|
225596
225616
|
}
|
|
@@ -226001,11 +226021,11 @@ function parseGrep(grep) {
|
|
|
226001
226021
|
const paths = /* @__PURE__ */ new Set;
|
|
226002
226022
|
const results = {};
|
|
226003
226023
|
forEachLineWithContent(grep, (input) => {
|
|
226004
|
-
const [
|
|
226005
|
-
paths.add(
|
|
226006
|
-
(results[
|
|
226024
|
+
const [path3, line, preview] = input.split(NULL);
|
|
226025
|
+
paths.add(path3);
|
|
226026
|
+
(results[path3] = results[path3] || []).push({
|
|
226007
226027
|
line: asNumber(line),
|
|
226008
|
-
path:
|
|
226028
|
+
path: path3,
|
|
226009
226029
|
preview
|
|
226010
226030
|
});
|
|
226011
226031
|
});
|
|
@@ -226667,14 +226687,14 @@ var init_hash_object = __esm({
|
|
|
226667
226687
|
init_task();
|
|
226668
226688
|
}
|
|
226669
226689
|
});
|
|
226670
|
-
function parseInit(bare,
|
|
226690
|
+
function parseInit(bare, path3, text) {
|
|
226671
226691
|
const response = String(text).trim();
|
|
226672
226692
|
let result;
|
|
226673
226693
|
if (result = initResponseRegex.exec(response)) {
|
|
226674
|
-
return new InitSummary(bare,
|
|
226694
|
+
return new InitSummary(bare, path3, false, result[1]);
|
|
226675
226695
|
}
|
|
226676
226696
|
if (result = reInitResponseRegex.exec(response)) {
|
|
226677
|
-
return new InitSummary(bare,
|
|
226697
|
+
return new InitSummary(bare, path3, true, result[1]);
|
|
226678
226698
|
}
|
|
226679
226699
|
let gitDir = "";
|
|
226680
226700
|
const tokens = response.split(" ");
|
|
@@ -226685,7 +226705,7 @@ function parseInit(bare, path4, text) {
|
|
|
226685
226705
|
break;
|
|
226686
226706
|
}
|
|
226687
226707
|
}
|
|
226688
|
-
return new InitSummary(bare,
|
|
226708
|
+
return new InitSummary(bare, path3, /^re/i.test(response), gitDir);
|
|
226689
226709
|
}
|
|
226690
226710
|
var InitSummary;
|
|
226691
226711
|
var initResponseRegex;
|
|
@@ -226693,9 +226713,9 @@ var reInitResponseRegex;
|
|
|
226693
226713
|
var init_InitSummary = __esm({
|
|
226694
226714
|
"src/lib/responses/InitSummary.ts"() {
|
|
226695
226715
|
InitSummary = class {
|
|
226696
|
-
constructor(bare,
|
|
226716
|
+
constructor(bare, path3, existing, gitDir) {
|
|
226697
226717
|
this.bare = bare;
|
|
226698
|
-
this.path =
|
|
226718
|
+
this.path = path3;
|
|
226699
226719
|
this.existing = existing;
|
|
226700
226720
|
this.gitDir = gitDir;
|
|
226701
226721
|
}
|
|
@@ -226707,7 +226727,7 @@ var init_InitSummary = __esm({
|
|
|
226707
226727
|
function hasBareCommand(command) {
|
|
226708
226728
|
return command.includes(bareCommand);
|
|
226709
226729
|
}
|
|
226710
|
-
function initTask(bare = false,
|
|
226730
|
+
function initTask(bare = false, path3, customArgs) {
|
|
226711
226731
|
const commands = ["init", ...customArgs];
|
|
226712
226732
|
if (bare && !hasBareCommand(commands)) {
|
|
226713
226733
|
commands.splice(1, 0, bareCommand);
|
|
@@ -226716,7 +226736,7 @@ function initTask(bare = false, path4, customArgs) {
|
|
|
226716
226736
|
commands,
|
|
226717
226737
|
format: "utf-8",
|
|
226718
226738
|
parser(text) {
|
|
226719
|
-
return parseInit(commands.includes("--bare"),
|
|
226739
|
+
return parseInit(commands.includes("--bare"), path3, text);
|
|
226720
226740
|
}
|
|
226721
226741
|
};
|
|
226722
226742
|
}
|
|
@@ -227431,12 +227451,12 @@ var init_FileStatusSummary = __esm({
|
|
|
227431
227451
|
"src/lib/responses/FileStatusSummary.ts"() {
|
|
227432
227452
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
227433
227453
|
FileStatusSummary = class {
|
|
227434
|
-
constructor(
|
|
227435
|
-
this.path =
|
|
227454
|
+
constructor(path3, index, working_dir) {
|
|
227455
|
+
this.path = path3;
|
|
227436
227456
|
this.index = index;
|
|
227437
227457
|
this.working_dir = working_dir;
|
|
227438
227458
|
if (index === "R" || working_dir === "R") {
|
|
227439
|
-
const detail = fromPathRegex.exec(
|
|
227459
|
+
const detail = fromPathRegex.exec(path3) || [null, path3, path3];
|
|
227440
227460
|
this.from = detail[2] || "";
|
|
227441
227461
|
this.path = detail[1] || "";
|
|
227442
227462
|
}
|
|
@@ -227467,14 +227487,14 @@ function splitLine(result, lineStr) {
|
|
|
227467
227487
|
default:
|
|
227468
227488
|
return;
|
|
227469
227489
|
}
|
|
227470
|
-
function data(index, workingDir,
|
|
227490
|
+
function data(index, workingDir, path3) {
|
|
227471
227491
|
const raw = `${index}${workingDir}`;
|
|
227472
227492
|
const handler = parsers6.get(raw);
|
|
227473
227493
|
if (handler) {
|
|
227474
|
-
handler(result,
|
|
227494
|
+
handler(result, path3);
|
|
227475
227495
|
}
|
|
227476
227496
|
if (raw !== "##" && raw !== "!!") {
|
|
227477
|
-
result.files.push(new FileStatusSummary(
|
|
227497
|
+
result.files.push(new FileStatusSummary(path3, index, workingDir));
|
|
227478
227498
|
}
|
|
227479
227499
|
}
|
|
227480
227500
|
}
|
|
@@ -227705,8 +227725,8 @@ var init_simple_git_api = __esm({
|
|
|
227705
227725
|
}
|
|
227706
227726
|
return this._runTask(configurationErrorTask("Git.cwd: workingDirectory must be supplied as a string"), next);
|
|
227707
227727
|
}
|
|
227708
|
-
hashObject(
|
|
227709
|
-
return this._runTask(hashObjectTask(
|
|
227728
|
+
hashObject(path3, write) {
|
|
227729
|
+
return this._runTask(hashObjectTask(path3, write === true), trailingFunctionArgument(arguments));
|
|
227710
227730
|
}
|
|
227711
227731
|
init(bare) {
|
|
227712
227732
|
return this._runTask(initTask(bare === true, this._executor.cwd, getTrailingOptions(arguments)), trailingFunctionArgument(arguments));
|
|
@@ -228283,8 +228303,8 @@ __export2(sub_module_exports, {
|
|
|
228283
228303
|
subModuleTask: () => subModuleTask,
|
|
228284
228304
|
updateSubModuleTask: () => updateSubModuleTask
|
|
228285
228305
|
});
|
|
228286
|
-
function addSubModuleTask(repo,
|
|
228287
|
-
return subModuleTask(["add", repo,
|
|
228306
|
+
function addSubModuleTask(repo, path3) {
|
|
228307
|
+
return subModuleTask(["add", repo, path3]);
|
|
228288
228308
|
}
|
|
228289
228309
|
function initSubModuleTask(customArgs) {
|
|
228290
228310
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -228552,8 +228572,8 @@ var require_git = __commonJS2({
|
|
|
228552
228572
|
}
|
|
228553
228573
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
228554
228574
|
};
|
|
228555
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
228556
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
228575
|
+
Git2.prototype.submoduleAdd = function(repo, path3, then) {
|
|
228576
|
+
return this._runTask(addSubModuleTask2(repo, path3), trailingFunctionArgument2(arguments));
|
|
228557
228577
|
};
|
|
228558
228578
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
228559
228579
|
return this._runTask(updateSubModuleTask2(getTrailingOptions2(arguments, true)), trailingFunctionArgument2(arguments));
|
|
@@ -229069,9 +229089,9 @@ import { Writable } from "stream";
|
|
|
229069
229089
|
|
|
229070
229090
|
// src/config.ts
|
|
229071
229091
|
import fs2 from "fs";
|
|
229072
|
-
import
|
|
229092
|
+
import path3 from "path";
|
|
229073
229093
|
import { fileURLToPath } from "url";
|
|
229074
|
-
var BUNDLED_DEFAULT_CONFIG_PATH =
|
|
229094
|
+
var BUNDLED_DEFAULT_CONFIG_PATH = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "default-publisher.config.json");
|
|
229075
229095
|
function resolvePublisherConfigPath(serverRoot) {
|
|
229076
229096
|
const explicitPath = process.env.PUBLISHER_CONFIG_PATH;
|
|
229077
229097
|
if (explicitPath && explicitPath.length > 0) {
|
|
@@ -229080,7 +229100,7 @@ function resolvePublisherConfigPath(serverRoot) {
|
|
|
229080
229100
|
}
|
|
229081
229101
|
return { path: explicitPath, isBundledDefault: false };
|
|
229082
229102
|
}
|
|
229083
|
-
const serverRootPath =
|
|
229103
|
+
const serverRootPath = path3.join(serverRoot, PUBLISHER_CONFIG_NAME);
|
|
229084
229104
|
if (fs2.existsSync(serverRootPath)) {
|
|
229085
229105
|
return { path: serverRootPath, isBundledDefault: false };
|
|
229086
229106
|
}
|
|
@@ -229089,6 +229109,73 @@ function resolvePublisherConfigPath(serverRoot) {
|
|
|
229089
229109
|
}
|
|
229090
229110
|
return null;
|
|
229091
229111
|
}
|
|
229112
|
+
var DEFAULT_HIGH_WATER_FRACTION = 0.8;
|
|
229113
|
+
var DEFAULT_LOW_WATER_FRACTION = 0.7;
|
|
229114
|
+
var DEFAULT_CHECK_INTERVAL_MS = 5000;
|
|
229115
|
+
var MIN_CHECK_INTERVAL_MS = 100;
|
|
229116
|
+
function parseIntEnv(name) {
|
|
229117
|
+
const raw = process.env[name];
|
|
229118
|
+
if (raw === undefined || raw.trim() === "")
|
|
229119
|
+
return;
|
|
229120
|
+
const value = Number.parseInt(raw, 10);
|
|
229121
|
+
if (!Number.isFinite(value) || String(value) !== raw.trim()) {
|
|
229122
|
+
throw new Error(`Invalid value for ${name}: expected a base-10 integer, got "${raw}"`);
|
|
229123
|
+
}
|
|
229124
|
+
return value;
|
|
229125
|
+
}
|
|
229126
|
+
function parseFloatEnv(name) {
|
|
229127
|
+
const raw = process.env[name];
|
|
229128
|
+
if (raw === undefined || raw.trim() === "")
|
|
229129
|
+
return;
|
|
229130
|
+
const value = Number.parseFloat(raw);
|
|
229131
|
+
if (!Number.isFinite(value)) {
|
|
229132
|
+
throw new Error(`Invalid value for ${name}: expected a finite number, got "${raw}"`);
|
|
229133
|
+
}
|
|
229134
|
+
return value;
|
|
229135
|
+
}
|
|
229136
|
+
function parseBoolEnv(name) {
|
|
229137
|
+
const raw = process.env[name];
|
|
229138
|
+
if (raw === undefined || raw.trim() === "")
|
|
229139
|
+
return;
|
|
229140
|
+
const normalised = raw.trim().toLowerCase();
|
|
229141
|
+
if (["1", "true", "yes", "on"].includes(normalised))
|
|
229142
|
+
return true;
|
|
229143
|
+
if (["0", "false", "no", "off"].includes(normalised))
|
|
229144
|
+
return false;
|
|
229145
|
+
throw new Error(`Invalid value for ${name}: expected a boolean (true/false), got "${raw}"`);
|
|
229146
|
+
}
|
|
229147
|
+
var getMemoryGovernorConfig = () => {
|
|
229148
|
+
const maxMemoryBytes = parseIntEnv("PUBLISHER_MAX_MEMORY_BYTES");
|
|
229149
|
+
if (maxMemoryBytes === undefined || maxMemoryBytes === 0) {
|
|
229150
|
+
return null;
|
|
229151
|
+
}
|
|
229152
|
+
if (maxMemoryBytes < 0) {
|
|
229153
|
+
throw new Error(`PUBLISHER_MAX_MEMORY_BYTES must be a positive integer (got ${maxMemoryBytes})`);
|
|
229154
|
+
}
|
|
229155
|
+
const highWaterFraction = parseFloatEnv("PUBLISHER_MEMORY_HIGH_WATER_FRACTION") ?? DEFAULT_HIGH_WATER_FRACTION;
|
|
229156
|
+
const lowWaterFraction = parseFloatEnv("PUBLISHER_MEMORY_LOW_WATER_FRACTION") ?? DEFAULT_LOW_WATER_FRACTION;
|
|
229157
|
+
const checkIntervalMs = parseIntEnv("PUBLISHER_MEMORY_CHECK_INTERVAL_MS") ?? DEFAULT_CHECK_INTERVAL_MS;
|
|
229158
|
+
const backpressureEnabled = parseBoolEnv("PUBLISHER_MEMORY_BACKPRESSURE") ?? true;
|
|
229159
|
+
if (highWaterFraction <= 0 || highWaterFraction >= 1) {
|
|
229160
|
+
throw new Error(`PUBLISHER_MEMORY_HIGH_WATER_FRACTION must be in (0, 1) (got ${highWaterFraction})`);
|
|
229161
|
+
}
|
|
229162
|
+
if (lowWaterFraction <= 0 || lowWaterFraction >= 1) {
|
|
229163
|
+
throw new Error(`PUBLISHER_MEMORY_LOW_WATER_FRACTION must be in (0, 1) (got ${lowWaterFraction})`);
|
|
229164
|
+
}
|
|
229165
|
+
if (lowWaterFraction >= highWaterFraction) {
|
|
229166
|
+
throw new Error(`PUBLISHER_MEMORY_LOW_WATER_FRACTION (${lowWaterFraction}) must be strictly less than PUBLISHER_MEMORY_HIGH_WATER_FRACTION (${highWaterFraction})`);
|
|
229167
|
+
}
|
|
229168
|
+
if (checkIntervalMs < MIN_CHECK_INTERVAL_MS) {
|
|
229169
|
+
throw new Error(`PUBLISHER_MEMORY_CHECK_INTERVAL_MS must be >= ${MIN_CHECK_INTERVAL_MS} (got ${checkIntervalMs})`);
|
|
229170
|
+
}
|
|
229171
|
+
return {
|
|
229172
|
+
maxMemoryBytes,
|
|
229173
|
+
highWaterFraction,
|
|
229174
|
+
lowWaterFraction,
|
|
229175
|
+
checkIntervalMs,
|
|
229176
|
+
backpressureEnabled
|
|
229177
|
+
};
|
|
229178
|
+
};
|
|
229092
229179
|
function substituteEnvVars(value) {
|
|
229093
229180
|
const envVarPattern = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
229094
229181
|
return value.replace(envVarPattern, (_match, varName) => {
|
|
@@ -229128,7 +229215,7 @@ var getPublisherConfig = (serverRoot) => {
|
|
|
229128
229215
|
}
|
|
229129
229216
|
const publisherConfigPath = resolved.path;
|
|
229130
229217
|
if (resolved.isBundledDefault) {
|
|
229131
|
-
logger.info(`No publisher.config.json found at ${
|
|
229218
|
+
logger.info(`No publisher.config.json found at ${path3.join(serverRoot, PUBLISHER_CONFIG_NAME)}; falling back to bundled DuckDB-only default. Pass --config <path> or place a config in the server root to override.`);
|
|
229132
229219
|
}
|
|
229133
229220
|
let rawConfig;
|
|
229134
229221
|
try {
|
|
@@ -229274,15 +229361,6 @@ function markReady() {
|
|
|
229274
229361
|
logger.error("Service is already draining - cannot mark as ready");
|
|
229275
229362
|
}
|
|
229276
229363
|
}
|
|
229277
|
-
function markDegraded() {
|
|
229278
|
-
if (operationalState !== "draining") {
|
|
229279
|
-
operationalState = "degraded";
|
|
229280
|
-
ready = false;
|
|
229281
|
-
logger.warn("Service marked as degraded; one or more environments failed to initialize. Readiness probe will fail until the config is fixed and the process restarts.");
|
|
229282
|
-
} else {
|
|
229283
|
-
logger.error("Service is already draining - cannot mark as degraded");
|
|
229284
|
-
}
|
|
229285
|
-
}
|
|
229286
229364
|
function markNotReady() {
|
|
229287
229365
|
ready = false;
|
|
229288
229366
|
logger.info("Service marked as not ready - readiness probe will fail");
|
|
@@ -229366,7 +229444,7 @@ import * as crypto3 from "crypto";
|
|
|
229366
229444
|
|
|
229367
229445
|
// src/storage/duckdb/DuckDBConnection.ts
|
|
229368
229446
|
import duckdb from "duckdb";
|
|
229369
|
-
import * as
|
|
229447
|
+
import * as path4 from "path";
|
|
229370
229448
|
|
|
229371
229449
|
class DuckDBConnection2 {
|
|
229372
229450
|
db = null;
|
|
@@ -229374,7 +229452,7 @@ class DuckDBConnection2 {
|
|
|
229374
229452
|
dbPath;
|
|
229375
229453
|
mutex = new Mutex;
|
|
229376
229454
|
constructor(dbPath) {
|
|
229377
|
-
this.dbPath = dbPath ||
|
|
229455
|
+
this.dbPath = dbPath || path4.join(process.cwd(), "publisher.db");
|
|
229378
229456
|
}
|
|
229379
229457
|
async initialize() {
|
|
229380
229458
|
return new Promise((resolve3, reject) => {
|
|
@@ -230523,9 +230601,62 @@ class StorageManager {
|
|
|
230523
230601
|
|
|
230524
230602
|
// src/service/environment.ts
|
|
230525
230603
|
import { MalloyError as MalloyError3, Runtime as Runtime2 } from "@malloydata/malloy";
|
|
230604
|
+
import crypto4 from "crypto";
|
|
230526
230605
|
import * as fs6 from "fs";
|
|
230527
230606
|
import * as path9 from "path";
|
|
230528
230607
|
|
|
230608
|
+
// src/path_safety.ts
|
|
230609
|
+
import * as path5 from "path";
|
|
230610
|
+
var SAFE_NAME_RE = /^(?!\.\.?$)(?!\.)[A-Za-z0-9._-]{1,255}$/;
|
|
230611
|
+
var MAX_MODEL_PATH_LEN = 1024;
|
|
230612
|
+
var SAFE_ENVIRONMENT_PATH_RE = /^(?:\/|[A-Za-z]:[\\/])[\x20-\x7E]*$/;
|
|
230613
|
+
var MAX_ENVIRONMENT_PATH_LEN = 4096;
|
|
230614
|
+
function assertSafePackageName(packageName) {
|
|
230615
|
+
if (typeof packageName !== "string" || !SAFE_NAME_RE.test(packageName)) {
|
|
230616
|
+
throw new BadRequestError(`Invalid package name: must be 1-255 characters of letters, digits, "-", "_", or "." and must not start with "."`);
|
|
230617
|
+
}
|
|
230618
|
+
}
|
|
230619
|
+
function assertSafeRelativeModelPath(modelPath) {
|
|
230620
|
+
if (typeof modelPath !== "string" || modelPath.length === 0 || modelPath.length > MAX_MODEL_PATH_LEN || modelPath.includes("\x00") || modelPath.includes("\\") || path5.isAbsolute(modelPath) || modelPath.startsWith("/")) {
|
|
230621
|
+
throw new BadRequestError(`Invalid model path`);
|
|
230622
|
+
}
|
|
230623
|
+
const segments = modelPath.split("/");
|
|
230624
|
+
for (const segment of segments) {
|
|
230625
|
+
if (segment === "" || segment === "." || segment === "..") {
|
|
230626
|
+
throw new BadRequestError(`Invalid model path`);
|
|
230627
|
+
}
|
|
230628
|
+
if (segment.startsWith(".")) {
|
|
230629
|
+
throw new BadRequestError(`Invalid model path`);
|
|
230630
|
+
}
|
|
230631
|
+
}
|
|
230632
|
+
}
|
|
230633
|
+
function assertSafeEnvironmentPath(environmentPath) {
|
|
230634
|
+
if (typeof environmentPath !== "string") {
|
|
230635
|
+
throw new BadRequestError(`Invalid environment path: must be a string`);
|
|
230636
|
+
}
|
|
230637
|
+
if (environmentPath.length === 0 || environmentPath.length > MAX_ENVIRONMENT_PATH_LEN) {
|
|
230638
|
+
throw new BadRequestError(`Invalid environment path: bad length`);
|
|
230639
|
+
}
|
|
230640
|
+
if (environmentPath.indexOf("\x00") !== -1) {
|
|
230641
|
+
throw new BadRequestError(`Invalid environment path: contains NUL byte`);
|
|
230642
|
+
}
|
|
230643
|
+
if (environmentPath.indexOf("..") !== -1) {
|
|
230644
|
+
throw new BadRequestError(`Invalid environment path: contains ".." traversal segment`);
|
|
230645
|
+
}
|
|
230646
|
+
if (!SAFE_ENVIRONMENT_PATH_RE.test(environmentPath)) {
|
|
230647
|
+
throw new BadRequestError(`Invalid environment path: must be an absolute path of printable ASCII characters`);
|
|
230648
|
+
}
|
|
230649
|
+
}
|
|
230650
|
+
function safeJoinUnderRoot(root, ...segments) {
|
|
230651
|
+
const resolvedRoot = path5.resolve(root);
|
|
230652
|
+
const joined = path5.resolve(resolvedRoot, ...segments);
|
|
230653
|
+
const rootWithSep = resolvedRoot.endsWith(path5.sep) ? resolvedRoot : resolvedRoot + path5.sep;
|
|
230654
|
+
if (joined !== resolvedRoot && !joined.startsWith(rootWithSep)) {
|
|
230655
|
+
throw new BadRequestError(`Resolved path is outside of root`);
|
|
230656
|
+
}
|
|
230657
|
+
return joined;
|
|
230658
|
+
}
|
|
230659
|
+
|
|
230529
230660
|
// src/utils.ts
|
|
230530
230661
|
import * as fs3 from "fs";
|
|
230531
230662
|
import * as path6 from "path";
|
|
@@ -231707,6 +231838,8 @@ class Package {
|
|
|
231707
231838
|
}
|
|
231708
231839
|
|
|
231709
231840
|
// src/service/environment.ts
|
|
231841
|
+
var STAGING_DIR_NAME = ".staging";
|
|
231842
|
+
var RETIRED_DIR_NAME = ".retired";
|
|
231710
231843
|
var RETIRED_CONNECTION_DRAIN_MS = 30000;
|
|
231711
231844
|
|
|
231712
231845
|
class Environment {
|
|
@@ -231720,7 +231853,9 @@ class Environment {
|
|
|
231720
231853
|
environmentPath;
|
|
231721
231854
|
environmentName;
|
|
231722
231855
|
metadata;
|
|
231856
|
+
memoryGovernor = null;
|
|
231723
231857
|
constructor(environmentName, environmentPath, malloyConfig, apiConnections) {
|
|
231858
|
+
assertSafeEnvironmentPath(environmentPath);
|
|
231724
231859
|
this.environmentName = environmentName;
|
|
231725
231860
|
this.environmentPath = environmentPath;
|
|
231726
231861
|
this.malloyConfig = malloyConfig;
|
|
@@ -231777,6 +231912,7 @@ class Environment {
|
|
|
231777
231912
|
apiConnections: malloyConfig.apiConnections
|
|
231778
231913
|
});
|
|
231779
231914
|
const environment = new Environment(environmentName, environmentPath, malloyConfig, malloyConfig.apiConnections);
|
|
231915
|
+
await Environment.sweepStaleInstallDirs(environmentPath);
|
|
231780
231916
|
return environment;
|
|
231781
231917
|
}
|
|
231782
231918
|
async reloadEnvironmentMetadata() {
|
|
@@ -231793,46 +231929,50 @@ class Environment {
|
|
|
231793
231929
|
return this.metadata;
|
|
231794
231930
|
}
|
|
231795
231931
|
async compileSource(packageName, modelName, source, includeSql = false) {
|
|
231796
|
-
|
|
231797
|
-
|
|
231798
|
-
|
|
231799
|
-
|
|
231800
|
-
|
|
231801
|
-
|
|
231802
|
-
|
|
231803
|
-
|
|
231804
|
-
|
|
231932
|
+
assertSafePackageName(packageName);
|
|
231933
|
+
assertSafeRelativeModelPath(modelName);
|
|
231934
|
+
return this.withPackageLock(packageName, async () => {
|
|
231935
|
+
const modelPath = safeJoinUnderRoot(this.environmentPath, packageName, modelName);
|
|
231936
|
+
const modelDir = path9.dirname(modelPath);
|
|
231937
|
+
const virtualUri = `file://${path9.join(modelDir, "__compile_check.malloy")}`;
|
|
231938
|
+
const virtualUrl = new URL(virtualUri);
|
|
231939
|
+
let modelContent = "";
|
|
231940
|
+
try {
|
|
231941
|
+
modelContent = await fs6.promises.readFile(modelPath, "utf8");
|
|
231942
|
+
} catch {}
|
|
231943
|
+
const fullSource = modelContent ? `${modelContent}
|
|
231805
231944
|
${source}` : source;
|
|
231806
|
-
|
|
231807
|
-
|
|
231808
|
-
|
|
231809
|
-
|
|
231945
|
+
const interceptingReader = {
|
|
231946
|
+
readURL: async (url2) => {
|
|
231947
|
+
if (url2.toString() === virtualUri) {
|
|
231948
|
+
return fullSource;
|
|
231949
|
+
}
|
|
231950
|
+
return URL_READER.readURL(url2);
|
|
231951
|
+
}
|
|
231952
|
+
};
|
|
231953
|
+
const pkg = await this._loadOrGetPackageLocked(packageName);
|
|
231954
|
+
const runtime = new Runtime2({
|
|
231955
|
+
urlReader: interceptingReader,
|
|
231956
|
+
config: pkg.getMalloyConfig()
|
|
231957
|
+
});
|
|
231958
|
+
try {
|
|
231959
|
+
const modelMaterializer = runtime.loadModel(virtualUrl);
|
|
231960
|
+
const model = await modelMaterializer.getModel();
|
|
231961
|
+
let sql;
|
|
231962
|
+
if (includeSql) {
|
|
231963
|
+
try {
|
|
231964
|
+
const queryMaterializer = modelMaterializer.loadFinalQuery();
|
|
231965
|
+
sql = await queryMaterializer.getSQL();
|
|
231966
|
+
} catch {}
|
|
231810
231967
|
}
|
|
231811
|
-
return
|
|
231968
|
+
return { problems: model.problems, sql };
|
|
231969
|
+
} catch (error) {
|
|
231970
|
+
if (error instanceof MalloyError3) {
|
|
231971
|
+
return { problems: error.problems };
|
|
231972
|
+
}
|
|
231973
|
+
throw error;
|
|
231812
231974
|
}
|
|
231813
|
-
};
|
|
231814
|
-
const pkg = await this.getPackage(packageName);
|
|
231815
|
-
const runtime = new Runtime2({
|
|
231816
|
-
urlReader: interceptingReader,
|
|
231817
|
-
config: pkg.getMalloyConfig()
|
|
231818
231975
|
});
|
|
231819
|
-
try {
|
|
231820
|
-
const modelMaterializer = runtime.loadModel(virtualUrl);
|
|
231821
|
-
const model = await modelMaterializer.getModel();
|
|
231822
|
-
let sql;
|
|
231823
|
-
if (includeSql) {
|
|
231824
|
-
try {
|
|
231825
|
-
const queryMaterializer = modelMaterializer.loadFinalQuery();
|
|
231826
|
-
sql = await queryMaterializer.getSQL();
|
|
231827
|
-
} catch {}
|
|
231828
|
-
}
|
|
231829
|
-
return { problems: model.problems, sql };
|
|
231830
|
-
} catch (error) {
|
|
231831
|
-
if (error instanceof MalloyError3) {
|
|
231832
|
-
return { problems: error.problems };
|
|
231833
|
-
}
|
|
231834
|
-
throw error;
|
|
231835
|
-
}
|
|
231836
231976
|
}
|
|
231837
231977
|
listApiConnections() {
|
|
231838
231978
|
return this.apiConnections;
|
|
@@ -231916,85 +232056,190 @@ ${source}` : source;
|
|
|
231916
232056
|
}
|
|
231917
232057
|
return packageMutex;
|
|
231918
232058
|
}
|
|
231919
|
-
async
|
|
232059
|
+
async withPackageLock(packageName, fn) {
|
|
232060
|
+
assertSafePackageName(packageName);
|
|
232061
|
+
return this.getOrCreatePackageMutex(packageName).runExclusive(fn);
|
|
232062
|
+
}
|
|
232063
|
+
allocateStagingPath(packageName) {
|
|
232064
|
+
return safeJoinUnderRoot(this.environmentPath, STAGING_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
|
|
232065
|
+
}
|
|
232066
|
+
allocateRetiredPath(packageName) {
|
|
232067
|
+
return safeJoinUnderRoot(this.environmentPath, RETIRED_DIR_NAME, `${packageName}-${crypto4.randomUUID()}`);
|
|
232068
|
+
}
|
|
232069
|
+
static async sweepStaleInstallDirs(environmentPath) {
|
|
232070
|
+
assertSafeEnvironmentPath(environmentPath);
|
|
232071
|
+
for (const dirName of [STAGING_DIR_NAME, RETIRED_DIR_NAME]) {
|
|
232072
|
+
const dir = safeJoinUnderRoot(environmentPath, dirName);
|
|
232073
|
+
if (dir.indexOf("..") !== -1)
|
|
232074
|
+
continue;
|
|
232075
|
+
if (path9.basename(dir) !== dirName)
|
|
232076
|
+
continue;
|
|
232077
|
+
try {
|
|
232078
|
+
await fs6.promises.rm(dir, { recursive: true, force: true });
|
|
232079
|
+
} catch (err) {
|
|
232080
|
+
logger.warn(`Failed to sweep stale ${dirName} dir at ${dir}`, {
|
|
232081
|
+
error: err
|
|
232082
|
+
});
|
|
232083
|
+
}
|
|
232084
|
+
}
|
|
232085
|
+
}
|
|
232086
|
+
setMemoryGovernor(governor) {
|
|
232087
|
+
this.memoryGovernor = governor;
|
|
232088
|
+
}
|
|
232089
|
+
assertCanAdmitNewPackage(packageName, reason, allowAdmission) {
|
|
232090
|
+
if (allowAdmission)
|
|
232091
|
+
return;
|
|
232092
|
+
if (!this.memoryGovernor?.isBackpressured())
|
|
232093
|
+
return;
|
|
232094
|
+
throw new ServiceUnavailableError(`Publisher is under memory pressure and cannot ${reason} (package "${packageName}", environment "${this.environmentName}"). Retry after the server's memory usage drops below the configured low-water mark.`);
|
|
232095
|
+
}
|
|
232096
|
+
async getPackage(packageName, reload = false, options = {}) {
|
|
232097
|
+
assertSafePackageName(packageName);
|
|
231920
232098
|
const _package = this.packages.get(packageName);
|
|
231921
232099
|
if (_package !== undefined && !reload) {
|
|
231922
232100
|
return _package;
|
|
231923
232101
|
}
|
|
231924
|
-
|
|
231925
|
-
|
|
231926
|
-
|
|
231927
|
-
|
|
231928
|
-
|
|
231929
|
-
|
|
231930
|
-
|
|
231931
|
-
logger.debug(`Package ${packageName} loaded by another request`);
|
|
231932
|
-
return existingPackage;
|
|
231933
|
-
}
|
|
232102
|
+
this.assertCanAdmitNewPackage(packageName, reload ? "reload a package" : "load a package", options.allowAdmission === true);
|
|
232103
|
+
return this.withPackageLock(packageName, () => this._loadOrGetPackageLocked(packageName, reload));
|
|
232104
|
+
}
|
|
232105
|
+
async _loadOrGetPackageLocked(packageName, reload = false) {
|
|
232106
|
+
const existingPackage = this.packages.get(packageName);
|
|
232107
|
+
if (existingPackage !== undefined && !reload) {
|
|
232108
|
+
return existingPackage;
|
|
231934
232109
|
}
|
|
231935
|
-
|
|
231936
|
-
|
|
231937
|
-
|
|
231938
|
-
|
|
231939
|
-
|
|
231940
|
-
|
|
231941
|
-
|
|
231942
|
-
logger.debug(`Loading package ${packageName}...`);
|
|
231943
|
-
const packagePath = path9.join(this.environmentPath, packageName);
|
|
231944
|
-
const _package2 = await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig);
|
|
231945
|
-
if (existingPackage !== undefined && reload) {
|
|
231946
|
-
this.retireConnectionGeneration(`package ${packageName}`, () => existingPackage.getMalloyConfig().releaseConnections());
|
|
231947
|
-
}
|
|
231948
|
-
this.packages.set(packageName, _package2);
|
|
231949
|
-
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
231950
|
-
logger.debug(`Successfully loaded package ${packageName}`);
|
|
231951
|
-
return _package2;
|
|
231952
|
-
} catch (error) {
|
|
231953
|
-
logger.error(`Failed to load package ${packageName}`, { error });
|
|
231954
|
-
this.packages.delete(packageName);
|
|
231955
|
-
this.packageStatuses.delete(packageName);
|
|
231956
|
-
throw error;
|
|
232110
|
+
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
232111
|
+
try {
|
|
232112
|
+
logger.debug(`Loading package ${packageName}...`);
|
|
232113
|
+
const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
232114
|
+
const _package = await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig);
|
|
232115
|
+
if (existingPackage !== undefined && reload) {
|
|
232116
|
+
this.retireConnectionGeneration(`package ${packageName}`, () => existingPackage.getMalloyConfig().releaseConnections());
|
|
231957
232117
|
}
|
|
231958
|
-
|
|
232118
|
+
this.packages.set(packageName, _package);
|
|
232119
|
+
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
232120
|
+
logger.debug(`Successfully loaded package ${packageName}`);
|
|
232121
|
+
return _package;
|
|
232122
|
+
} catch (error) {
|
|
232123
|
+
logger.error(`Failed to load package ${packageName}`, { error });
|
|
232124
|
+
this.packages.delete(packageName);
|
|
232125
|
+
this.packageStatuses.delete(packageName);
|
|
232126
|
+
throw error;
|
|
232127
|
+
}
|
|
231959
232128
|
}
|
|
231960
|
-
async addPackage(packageName) {
|
|
231961
|
-
|
|
232129
|
+
async addPackage(packageName, options = {}) {
|
|
232130
|
+
assertSafePackageName(packageName);
|
|
232131
|
+
const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
231962
232132
|
if (!await fs6.promises.access(packagePath).then(() => true).catch(() => false) || !(await fs6.promises.stat(packagePath))?.isDirectory()) {
|
|
231963
232133
|
throw new PackageNotFoundError(`Package ${packageName} not found`);
|
|
231964
232134
|
}
|
|
232135
|
+
this.assertCanAdmitNewPackage(packageName, "add a new package", options.allowAdmission === true);
|
|
231965
232136
|
logger.info(`Adding package ${packageName} to environment ${this.environmentName}`, {
|
|
231966
232137
|
packagePath,
|
|
231967
232138
|
malloyConfig: this.malloyConfig.malloyConfig
|
|
231968
232139
|
});
|
|
231969
|
-
|
|
231970
|
-
|
|
231971
|
-
|
|
231972
|
-
|
|
231973
|
-
|
|
231974
|
-
|
|
231975
|
-
|
|
231976
|
-
|
|
232140
|
+
return this.withPackageLock(packageName, () => this._addPackageLocked(packageName));
|
|
232141
|
+
}
|
|
232142
|
+
async _addPackageLocked(packageName) {
|
|
232143
|
+
const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
232144
|
+
const existingPackage = this.packages.get(packageName);
|
|
232145
|
+
if (existingPackage !== undefined) {
|
|
232146
|
+
return existingPackage;
|
|
232147
|
+
}
|
|
232148
|
+
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
232149
|
+
try {
|
|
232150
|
+
this.packages.set(packageName, await Package.create(this.environmentName, packageName, packagePath, () => this.malloyConfig.malloyConfig));
|
|
232151
|
+
} catch (error) {
|
|
232152
|
+
logger.error("Error adding package", { error });
|
|
232153
|
+
this.deletePackageStatus(packageName);
|
|
232154
|
+
throw error;
|
|
231977
232155
|
}
|
|
231978
|
-
|
|
231979
|
-
|
|
231980
|
-
|
|
231981
|
-
|
|
232156
|
+
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
232157
|
+
return this.packages.get(packageName);
|
|
232158
|
+
}
|
|
232159
|
+
async installPackage(packageName, downloader) {
|
|
232160
|
+
assertSafePackageName(packageName);
|
|
232161
|
+
const stagingPath = this.allocateStagingPath(packageName);
|
|
232162
|
+
await fs6.promises.mkdir(path9.dirname(stagingPath), { recursive: true });
|
|
232163
|
+
try {
|
|
232164
|
+
await downloader(stagingPath);
|
|
232165
|
+
} catch (err) {
|
|
232166
|
+
await fs6.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
|
|
232167
|
+
throw err;
|
|
232168
|
+
}
|
|
232169
|
+
return this.withPackageLock(packageName, async () => {
|
|
232170
|
+
const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
232171
|
+
let retiredPath;
|
|
232172
|
+
const oldPackage = this.packages.get(packageName);
|
|
232173
|
+
const oldExistsOnDisk = await fs6.promises.access(canonicalPath).then(() => true).catch(() => false);
|
|
232174
|
+
if (oldExistsOnDisk) {
|
|
232175
|
+
retiredPath = this.allocateRetiredPath(packageName);
|
|
232176
|
+
await fs6.promises.mkdir(path9.dirname(retiredPath), {
|
|
232177
|
+
recursive: true
|
|
232178
|
+
});
|
|
232179
|
+
await fs6.promises.rename(canonicalPath, retiredPath);
|
|
231982
232180
|
}
|
|
231983
|
-
|
|
232181
|
+
let newPackage;
|
|
231984
232182
|
try {
|
|
231985
|
-
|
|
231986
|
-
|
|
231987
|
-
|
|
232183
|
+
await fs6.promises.rename(stagingPath, canonicalPath);
|
|
232184
|
+
this.setPackageStatus(packageName, "loading" /* LOADING */);
|
|
232185
|
+
newPackage = await Package.create(this.environmentName, packageName, canonicalPath, () => this.malloyConfig.malloyConfig);
|
|
232186
|
+
} catch (err) {
|
|
232187
|
+
await fs6.promises.rm(canonicalPath, { recursive: true, force: true }).catch(() => {});
|
|
232188
|
+
if (retiredPath) {
|
|
232189
|
+
try {
|
|
232190
|
+
await fs6.promises.rename(retiredPath, canonicalPath);
|
|
232191
|
+
} catch (restoreErr) {
|
|
232192
|
+
logger.error("Failed to restore retired package after install rollback", {
|
|
232193
|
+
error: restoreErr,
|
|
232194
|
+
retiredPath,
|
|
232195
|
+
canonicalPath
|
|
232196
|
+
});
|
|
232197
|
+
}
|
|
232198
|
+
}
|
|
232199
|
+
await fs6.promises.rm(stagingPath, { recursive: true, force: true }).catch(() => {});
|
|
231988
232200
|
this.deletePackageStatus(packageName);
|
|
231989
|
-
throw
|
|
232201
|
+
throw err;
|
|
231990
232202
|
}
|
|
232203
|
+
this.packages.set(packageName, newPackage);
|
|
231991
232204
|
this.setPackageStatus(packageName, "serving" /* SERVING */);
|
|
231992
|
-
|
|
232205
|
+
if (oldPackage) {
|
|
232206
|
+
this.retireConnectionGeneration(`package ${packageName}`, () => oldPackage.getMalloyConfig().releaseConnections());
|
|
232207
|
+
}
|
|
232208
|
+
if (retiredPath) {
|
|
232209
|
+
const pathToClean = retiredPath;
|
|
232210
|
+
setImmediate(() => {
|
|
232211
|
+
fs6.promises.rm(pathToClean, { recursive: true, force: true }).catch((err) => {
|
|
232212
|
+
logger.warn(`Failed to clean up retired package directory ${pathToClean}`, { error: err });
|
|
232213
|
+
});
|
|
232214
|
+
});
|
|
232215
|
+
}
|
|
232216
|
+
return newPackage;
|
|
232217
|
+
});
|
|
232218
|
+
}
|
|
232219
|
+
async reloadAllModelsForPackage(packageName, manifest) {
|
|
232220
|
+
assertSafePackageName(packageName);
|
|
232221
|
+
return this.withPackageLock(packageName, async () => {
|
|
232222
|
+
const pkg = this.packages.get(packageName);
|
|
232223
|
+
if (!pkg) {
|
|
232224
|
+
throw new PackageNotFoundError(`Package ${packageName} is not loaded`);
|
|
232225
|
+
}
|
|
232226
|
+
await pkg.reloadAllModels(manifest);
|
|
232227
|
+
});
|
|
232228
|
+
}
|
|
232229
|
+
async getModelFileText(packageName, modelPath) {
|
|
232230
|
+
assertSafePackageName(packageName);
|
|
232231
|
+
assertSafeRelativeModelPath(modelPath);
|
|
232232
|
+
return this.withPackageLock(packageName, async () => {
|
|
232233
|
+
const pkg = this.packages.get(packageName);
|
|
232234
|
+
if (!pkg) {
|
|
232235
|
+
throw new PackageNotFoundError(`Package ${packageName} is not loaded`);
|
|
232236
|
+
}
|
|
232237
|
+
return pkg.getModelFileText(modelPath);
|
|
231993
232238
|
});
|
|
231994
232239
|
}
|
|
231995
232240
|
async writePackageManifest(packageName, metadata) {
|
|
231996
|
-
const packagePath =
|
|
231997
|
-
const manifestPath =
|
|
232241
|
+
const packagePath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
232242
|
+
const manifestPath = safeJoinUnderRoot(packagePath, "publisher.json");
|
|
231998
232243
|
try {
|
|
231999
232244
|
let existingManifest = {};
|
|
232000
232245
|
try {
|
|
@@ -232016,24 +232261,27 @@ ${source}` : source;
|
|
|
232016
232261
|
}
|
|
232017
232262
|
}
|
|
232018
232263
|
async updatePackage(packageName, body) {
|
|
232019
|
-
|
|
232020
|
-
|
|
232021
|
-
|
|
232022
|
-
|
|
232023
|
-
|
|
232024
|
-
|
|
232025
|
-
|
|
232026
|
-
|
|
232027
|
-
|
|
232028
|
-
|
|
232029
|
-
|
|
232030
|
-
|
|
232031
|
-
|
|
232032
|
-
|
|
232033
|
-
|
|
232034
|
-
|
|
232264
|
+
assertSafePackageName(packageName);
|
|
232265
|
+
return this.withPackageLock(packageName, async () => {
|
|
232266
|
+
const _package = this.packages.get(packageName);
|
|
232267
|
+
if (!_package) {
|
|
232268
|
+
throw new PackageNotFoundError(`Package ${packageName} not found`);
|
|
232269
|
+
}
|
|
232270
|
+
if (body.name) {
|
|
232271
|
+
_package.setName(body.name);
|
|
232272
|
+
}
|
|
232273
|
+
_package.setPackageMetadata({
|
|
232274
|
+
name: body.name,
|
|
232275
|
+
description: body.description,
|
|
232276
|
+
resource: body.resource,
|
|
232277
|
+
location: body.location
|
|
232278
|
+
});
|
|
232279
|
+
await this.writePackageManifest(packageName, {
|
|
232280
|
+
name: packageName,
|
|
232281
|
+
description: body.description
|
|
232282
|
+
});
|
|
232283
|
+
return _package.getPackageMetadata();
|
|
232035
232284
|
});
|
|
232036
|
-
return _package.getPackageMetadata();
|
|
232037
232285
|
}
|
|
232038
232286
|
getPackageStatus(packageName) {
|
|
232039
232287
|
return this.packageStatuses.get(packageName);
|
|
@@ -232050,35 +232298,49 @@ ${source}` : source;
|
|
|
232050
232298
|
this.packageStatuses.delete(packageName);
|
|
232051
232299
|
}
|
|
232052
232300
|
async deletePackage(packageName) {
|
|
232053
|
-
|
|
232054
|
-
|
|
232055
|
-
|
|
232056
|
-
|
|
232057
|
-
|
|
232058
|
-
|
|
232059
|
-
|
|
232060
|
-
|
|
232061
|
-
|
|
232062
|
-
|
|
232063
|
-
|
|
232064
|
-
|
|
232065
|
-
|
|
232066
|
-
|
|
232067
|
-
|
|
232068
|
-
|
|
232069
|
-
|
|
232070
|
-
|
|
232071
|
-
|
|
232072
|
-
|
|
232073
|
-
|
|
232074
|
-
|
|
232075
|
-
|
|
232076
|
-
|
|
232077
|
-
|
|
232078
|
-
|
|
232079
|
-
|
|
232080
|
-
|
|
232081
|
-
|
|
232301
|
+
assertSafePackageName(packageName);
|
|
232302
|
+
return this.withPackageLock(packageName, async () => {
|
|
232303
|
+
const _package = this.packages.get(packageName);
|
|
232304
|
+
if (!_package) {
|
|
232305
|
+
return;
|
|
232306
|
+
}
|
|
232307
|
+
const packageStatus = this.packageStatuses.get(packageName);
|
|
232308
|
+
if (packageStatus?.status === "loading" /* LOADING */) {
|
|
232309
|
+
logger.error("Package loading. Can't unload.", {
|
|
232310
|
+
environmentName: this.environmentName,
|
|
232311
|
+
packageName
|
|
232312
|
+
});
|
|
232313
|
+
throw new Error("Package loading. Can't unload. " + this.environmentName + " " + packageName);
|
|
232314
|
+
} else if (packageStatus?.status === "serving" /* SERVING */) {
|
|
232315
|
+
this.setPackageStatus(packageName, "unloading" /* UNLOADING */);
|
|
232316
|
+
}
|
|
232317
|
+
this.retireConnectionGeneration(`package ${packageName}`, () => _package.getMalloyConfig().releaseConnections());
|
|
232318
|
+
const canonicalPath = safeJoinUnderRoot(this.environmentPath, packageName);
|
|
232319
|
+
const retiredPath = this.allocateRetiredPath(packageName);
|
|
232320
|
+
let renamed = false;
|
|
232321
|
+
try {
|
|
232322
|
+
await fs6.promises.mkdir(path9.dirname(retiredPath), {
|
|
232323
|
+
recursive: true
|
|
232324
|
+
});
|
|
232325
|
+
await fs6.promises.rename(canonicalPath, retiredPath);
|
|
232326
|
+
renamed = true;
|
|
232327
|
+
} catch (err) {
|
|
232328
|
+
logger.error("Error renaming package directory to retired during unload", {
|
|
232329
|
+
error: err,
|
|
232330
|
+
environmentName: this.environmentName,
|
|
232331
|
+
packageName
|
|
232332
|
+
});
|
|
232333
|
+
}
|
|
232334
|
+
this.packages.delete(packageName);
|
|
232335
|
+
this.packageStatuses.delete(packageName);
|
|
232336
|
+
if (renamed) {
|
|
232337
|
+
setImmediate(() => {
|
|
232338
|
+
fs6.promises.rm(retiredPath, { recursive: true, force: true }).catch((err) => {
|
|
232339
|
+
logger.warn(`Failed to clean up retired package directory ${retiredPath}`, { error: err });
|
|
232340
|
+
});
|
|
232341
|
+
});
|
|
232342
|
+
}
|
|
232343
|
+
});
|
|
232082
232344
|
}
|
|
232083
232345
|
updateConnections(malloyConfig, _apiConnections, afterPreviousRelease) {
|
|
232084
232346
|
const previousMalloyConfig = this.malloyConfig;
|
|
@@ -232199,12 +232461,12 @@ class EnvironmentStore {
|
|
|
232199
232461
|
publisherConfigIsFrozen;
|
|
232200
232462
|
finishedInitialization;
|
|
232201
232463
|
isInitialized = false;
|
|
232202
|
-
failedEnvironments = [];
|
|
232203
232464
|
storageManager;
|
|
232204
232465
|
s3Client = new import_client_s32.S3({
|
|
232205
232466
|
followRegionRedirects: true
|
|
232206
232467
|
});
|
|
232207
232468
|
gcsClient;
|
|
232469
|
+
memoryGovernor = null;
|
|
232208
232470
|
constructor(serverRootPath) {
|
|
232209
232471
|
this.serverRootPath = serverRootPath;
|
|
232210
232472
|
this.gcsClient = new Storage;
|
|
@@ -232217,6 +232479,12 @@ class EnvironmentStore {
|
|
|
232217
232479
|
this.storageManager = new StorageManager(storageConfig);
|
|
232218
232480
|
this.finishedInitialization = this.initialize();
|
|
232219
232481
|
}
|
|
232482
|
+
setMemoryGovernor(governor) {
|
|
232483
|
+
this.memoryGovernor = governor;
|
|
232484
|
+
for (const env of this.environments.values()) {
|
|
232485
|
+
env.setMemoryGovernor(governor);
|
|
232486
|
+
}
|
|
232487
|
+
}
|
|
232220
232488
|
async addConfiguredEnvironment(environment) {
|
|
232221
232489
|
try {
|
|
232222
232490
|
await this.addEnvironment({
|
|
@@ -232232,10 +232500,6 @@ class EnvironmentStore {
|
|
|
232232
232500
|
logEnvironmentInitializationError(environmentName, error) {
|
|
232233
232501
|
const label = environmentName ? ` "${environmentName}"` : "";
|
|
232234
232502
|
logger.error(`Error initializing environment${label}; skipping environment`, this.extractErrorDataFromError(error));
|
|
232235
|
-
this.failedEnvironments.push({
|
|
232236
|
-
name: environmentName ?? "<unknown>",
|
|
232237
|
-
error: error instanceof Error ? error.message : String(error)
|
|
232238
|
-
});
|
|
232239
232503
|
}
|
|
232240
232504
|
async initialize() {
|
|
232241
232505
|
const reInit = process.env.INITIALIZE_STORAGE === "true";
|
|
@@ -232281,6 +232545,7 @@ class EnvironmentStore {
|
|
|
232281
232545
|
resource: `${API_PREFIX}/connections/${conn.name}`,
|
|
232282
232546
|
...conn.config
|
|
232283
232547
|
})));
|
|
232548
|
+
environmentInstance.setMemoryGovernor(this.memoryGovernor);
|
|
232284
232549
|
const packages = await repository.listPackages(dbEnvironment.id);
|
|
232285
232550
|
packages.forEach((pkg) => {
|
|
232286
232551
|
environmentInstance.setPackageStatus(pkg.name, "serving" /* SERVING */);
|
|
@@ -232298,11 +232563,7 @@ class EnvironmentStore {
|
|
|
232298
232563
|
}
|
|
232299
232564
|
}
|
|
232300
232565
|
this.isInitialized = true;
|
|
232301
|
-
|
|
232302
|
-
markDegraded();
|
|
232303
|
-
} else {
|
|
232304
|
-
markReady();
|
|
232305
|
-
}
|
|
232566
|
+
markReady();
|
|
232306
232567
|
const initializationDuration = performance.now() - initialTime;
|
|
232307
232568
|
logger.info(`Environment store successfully initialized in ${formatDuration(initializationDuration)}`);
|
|
232308
232569
|
} catch (error) {
|
|
@@ -232538,12 +232799,7 @@ class EnvironmentStore {
|
|
|
232538
232799
|
environments: [],
|
|
232539
232800
|
initialized: this.isInitialized,
|
|
232540
232801
|
frozenConfig: isPublisherConfigFrozen(this.serverRootPath),
|
|
232541
|
-
operationalState: getOperationalState()
|
|
232542
|
-
...this.failedEnvironments.length > 0 && {
|
|
232543
|
-
failedEnvironments: [
|
|
232544
|
-
...this.failedEnvironments
|
|
232545
|
-
]
|
|
232546
|
-
}
|
|
232802
|
+
operationalState: getOperationalState()
|
|
232547
232803
|
};
|
|
232548
232804
|
const environments = await this.listEnvironments(true);
|
|
232549
232805
|
await Promise.all(environments.map(async (environment) => {
|
|
@@ -232641,6 +232897,7 @@ class EnvironmentStore {
|
|
|
232641
232897
|
absoluteEnvironmentPath = await this.scaffoldEnvironment(environment);
|
|
232642
232898
|
}
|
|
232643
232899
|
const newEnvironment = await Environment.create(environmentName, absoluteEnvironmentPath, environment.connections || []);
|
|
232900
|
+
newEnvironment.setMemoryGovernor(this.memoryGovernor);
|
|
232644
232901
|
if (!newEnvironment.metadata)
|
|
232645
232902
|
newEnvironment.metadata = {};
|
|
232646
232903
|
newEnvironment.metadata.location = absoluteEnvironmentPath;
|
|
@@ -232806,7 +233063,7 @@ class EnvironmentStore {
|
|
|
232806
233063
|
});
|
|
232807
233064
|
}
|
|
232808
233065
|
for (const [groupedLocation, packagesForLocation] of locationGroups) {
|
|
232809
|
-
const locationHash =
|
|
233066
|
+
const locationHash = crypto5.createHash("sha256").update(groupedLocation).digest("hex").substring(0, 16);
|
|
232810
233067
|
const tempDownloadPath = `${absoluteTargetPath}/.temp_${locationHash}`;
|
|
232811
233068
|
await fs7.promises.mkdir(tempDownloadPath, { recursive: true });
|
|
232812
233069
|
logger.info(`Created temporary directory: ${tempDownloadPath}`);
|
|
@@ -232995,9 +233252,9 @@ class EnvironmentStore {
|
|
|
232995
233252
|
}
|
|
232996
233253
|
const file = fs7.createWriteStream(zipFilePath);
|
|
232997
233254
|
item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
|
|
232998
|
-
await new Promise((
|
|
233255
|
+
await new Promise((resolve4, reject) => {
|
|
232999
233256
|
file.on("error", reject);
|
|
233000
|
-
file.on("finish",
|
|
233257
|
+
file.on("finish", resolve4);
|
|
233001
233258
|
});
|
|
233002
233259
|
await this.unzipEnvironment(zipFilePath);
|
|
233003
233260
|
logger.info(`Downloaded S3 zip file ${s3Path} to ${absoluteDirPath}`);
|
|
@@ -233035,9 +233292,9 @@ class EnvironmentStore {
|
|
|
233035
233292
|
}
|
|
233036
233293
|
const file = fs7.createWriteStream(absoluteFilePath);
|
|
233037
233294
|
item.Body.transformToWebStream().pipeTo(Writable.toWeb(file));
|
|
233038
|
-
await new Promise((
|
|
233295
|
+
await new Promise((resolve4, reject) => {
|
|
233039
233296
|
file.on("error", reject);
|
|
233040
|
-
file.on("finish",
|
|
233297
|
+
file.on("finish", resolve4);
|
|
233041
233298
|
});
|
|
233042
233299
|
}));
|
|
233043
233300
|
logger.info(`Downloaded S3 directory ${s3Path} to ${absoluteDirPath}`);
|
|
@@ -233070,14 +233327,14 @@ class EnvironmentStore {
|
|
|
233070
233327
|
});
|
|
233071
233328
|
await fs7.promises.mkdir(absoluteDirPath, { recursive: true });
|
|
233072
233329
|
const repoUrl = `https://github.com/${owner}/${repoName}`;
|
|
233073
|
-
await new Promise((
|
|
233330
|
+
await new Promise((resolve4, reject) => {
|
|
233074
233331
|
esm_default2().clone(repoUrl, absoluteDirPath, {}, (err) => {
|
|
233075
233332
|
if (err) {
|
|
233076
233333
|
const errorData = this.extractErrorDataFromError(err);
|
|
233077
233334
|
logger.error(`Failed to clone GitHub repository "${repoUrl}"`, errorData);
|
|
233078
233335
|
reject(err);
|
|
233079
233336
|
}
|
|
233080
|
-
|
|
233337
|
+
resolve4();
|
|
233081
233338
|
});
|
|
233082
233339
|
});
|
|
233083
233340
|
if (!cleanPackagePath) {
|
|
@@ -233473,7 +233730,7 @@ class Protocol {
|
|
|
233473
233730
|
}
|
|
233474
233731
|
request(request, resultSchema, options) {
|
|
233475
233732
|
const { relatedRequestId, resumptionToken, onresumptiontoken } = options !== null && options !== undefined ? options : {};
|
|
233476
|
-
return new Promise((
|
|
233733
|
+
return new Promise((resolve4, reject) => {
|
|
233477
233734
|
var _a2, _b, _c, _d, _e, _f;
|
|
233478
233735
|
if (!this._transport) {
|
|
233479
233736
|
reject(new Error("Not connected"));
|
|
@@ -233524,7 +233781,7 @@ class Protocol {
|
|
|
233524
233781
|
}
|
|
233525
233782
|
try {
|
|
233526
233783
|
const result = resultSchema.parse(response.result);
|
|
233527
|
-
|
|
233784
|
+
resolve4(result);
|
|
233528
233785
|
} catch (error) {
|
|
233529
233786
|
reject(error);
|
|
233530
233787
|
}
|
|
@@ -236926,7 +237183,7 @@ function registerTools(mcpServer, environmentStore) {
|
|
|
236926
237183
|
console.log("model not found", modelPath, "in ", pkg.listModels());
|
|
236927
237184
|
throw new Error(`Model not found: ${modelPath}`);
|
|
236928
237185
|
}
|
|
236929
|
-
const fileText = await
|
|
237186
|
+
const fileText = await environment.getModelFileText(packageName, modelPath);
|
|
236930
237187
|
console.log(`[MCP LOG] Successfully retrieved model text for ${modelPath}`);
|
|
236931
237188
|
return {
|
|
236932
237189
|
content: [
|
|
@@ -237766,8 +238023,8 @@ class ManifestService {
|
|
|
237766
238023
|
async reloadManifest(environmentId, packageName, environmentName) {
|
|
237767
238024
|
const manifest = await this.getManifest(environmentId, packageName);
|
|
237768
238025
|
const environment = await this.environmentStore.getEnvironment(environmentName, false);
|
|
237769
|
-
|
|
237770
|
-
await
|
|
238026
|
+
await environment.getPackage(packageName, false);
|
|
238027
|
+
await environment.reloadAllModelsForPackage(packageName, manifest.entries);
|
|
237771
238028
|
logger.info("Reloaded manifest and recompiled models", {
|
|
237772
238029
|
environmentId,
|
|
237773
238030
|
packageName,
|
|
@@ -238088,8 +238345,8 @@ class MaterializationService {
|
|
|
238088
238345
|
if (metadata.autoLoadManifest) {
|
|
238089
238346
|
const updatedManifest = await this.manifestService.getManifest(environmentId, packageName);
|
|
238090
238347
|
const environment = await this.environmentStore.getEnvironment(environmentName, false);
|
|
238091
|
-
|
|
238092
|
-
await
|
|
238348
|
+
await environment.getPackage(packageName, false);
|
|
238349
|
+
await environment.reloadAllModelsForPackage(packageName, updatedManifest.entries);
|
|
238093
238350
|
}
|
|
238094
238351
|
await this.transitionExecution(executionId, "SUCCESS", {
|
|
238095
238352
|
completedAt: new Date,
|
|
@@ -238179,7 +238436,7 @@ class MaterializationService {
|
|
|
238179
238436
|
manifest.loadText(JSON.stringify(existingManifest));
|
|
238180
238437
|
const existingEntries = await this.manifestService.listEntries(environmentId, packageName);
|
|
238181
238438
|
const knownMaterializedTables = new Set(existingEntries.map((e) => manifestTableKey(e.connectionName, e.tableName)));
|
|
238182
|
-
const { graphs, sources, connectionDigests, connections } = await this.compilePackageBuildPlan(pkg, signal);
|
|
238439
|
+
const { graphs, sources, connectionDigests, connections } = await environment.withPackageLock(packageName, () => this.compilePackageBuildPlan(pkg, signal));
|
|
238183
238440
|
if (graphs.length === 0) {
|
|
238184
238441
|
logger.info("No persist sources to build");
|
|
238185
238442
|
return { sourcesBuilt: 0, sourcesSkipped: 0 };
|
|
@@ -238384,6 +238641,107 @@ class MaterializationService {
|
|
|
238384
238641
|
}
|
|
238385
238642
|
}
|
|
238386
238643
|
|
|
238644
|
+
// src/service/package_memory_governor.ts
|
|
238645
|
+
var import_api4 = __toESM(require_src(), 1);
|
|
238646
|
+
var DEFAULT_RSS_SAMPLER = () => process.memoryUsage().rss;
|
|
238647
|
+
|
|
238648
|
+
class PackageMemoryGovernor {
|
|
238649
|
+
config;
|
|
238650
|
+
rssSampler;
|
|
238651
|
+
highWaterBytes;
|
|
238652
|
+
lowWaterBytes;
|
|
238653
|
+
timer = null;
|
|
238654
|
+
backpressured = false;
|
|
238655
|
+
lastSampledRss = 0;
|
|
238656
|
+
lastSampledAt = null;
|
|
238657
|
+
backpressureActivationsCounter;
|
|
238658
|
+
constructor(config, rssSampler) {
|
|
238659
|
+
this.config = config;
|
|
238660
|
+
this.rssSampler = rssSampler ?? DEFAULT_RSS_SAMPLER;
|
|
238661
|
+
this.highWaterBytes = Math.floor(config.maxMemoryBytes * config.highWaterFraction);
|
|
238662
|
+
this.lowWaterBytes = Math.floor(config.maxMemoryBytes * config.lowWaterFraction);
|
|
238663
|
+
const meter2 = import_api4.metrics.getMeter("publisher");
|
|
238664
|
+
meter2.createObservableGauge("publisher_process_rss_bytes", {
|
|
238665
|
+
description: "Current resident set size of the publisher process in bytes",
|
|
238666
|
+
unit: "By"
|
|
238667
|
+
}).addCallback((observation) => {
|
|
238668
|
+
observation.observe(this.rssSampler());
|
|
238669
|
+
});
|
|
238670
|
+
meter2.createObservableGauge("publisher_memory_backpressure_active", {
|
|
238671
|
+
description: "1 when the publisher is rejecting new package loads to stay under PUBLISHER_MAX_MEMORY_BYTES; 0 otherwise"
|
|
238672
|
+
}).addCallback((observation) => {
|
|
238673
|
+
observation.observe(this.backpressured ? 1 : 0);
|
|
238674
|
+
});
|
|
238675
|
+
this.backpressureActivationsCounter = meter2.createCounter("publisher_memory_backpressure_activations_total", {
|
|
238676
|
+
description: "Number of times the memory governor has activated back-pressure"
|
|
238677
|
+
});
|
|
238678
|
+
meter2.createObservableGauge("publisher_memory_max_bytes", {
|
|
238679
|
+
description: "Configured PUBLISHER_MAX_MEMORY_BYTES",
|
|
238680
|
+
unit: "By"
|
|
238681
|
+
}).addCallback((observation) => observation.observe(this.config.maxMemoryBytes));
|
|
238682
|
+
meter2.createObservableGauge("publisher_memory_high_water_bytes", {
|
|
238683
|
+
description: "RSS threshold at which back-pressure activates",
|
|
238684
|
+
unit: "By"
|
|
238685
|
+
}).addCallback((observation) => observation.observe(this.highWaterBytes));
|
|
238686
|
+
meter2.createObservableGauge("publisher_memory_low_water_bytes", {
|
|
238687
|
+
description: "RSS threshold at which back-pressure clears",
|
|
238688
|
+
unit: "By"
|
|
238689
|
+
}).addCallback((observation) => observation.observe(this.lowWaterBytes));
|
|
238690
|
+
}
|
|
238691
|
+
start() {
|
|
238692
|
+
if (this.timer !== null)
|
|
238693
|
+
return;
|
|
238694
|
+
this.tick();
|
|
238695
|
+
this.timer = setInterval(() => this.tick(), this.config.checkIntervalMs);
|
|
238696
|
+
this.timer.unref?.();
|
|
238697
|
+
logger.info(`PackageMemoryGovernor started (max=${this.config.maxMemoryBytes}B, high=${this.highWaterBytes}B, low=${this.lowWaterBytes}B, interval=${this.config.checkIntervalMs}ms, backpressure=${this.config.backpressureEnabled})`);
|
|
238698
|
+
}
|
|
238699
|
+
stop() {
|
|
238700
|
+
if (this.timer !== null) {
|
|
238701
|
+
clearInterval(this.timer);
|
|
238702
|
+
this.timer = null;
|
|
238703
|
+
}
|
|
238704
|
+
this.backpressured = false;
|
|
238705
|
+
}
|
|
238706
|
+
tick() {
|
|
238707
|
+
let rss;
|
|
238708
|
+
try {
|
|
238709
|
+
rss = this.rssSampler();
|
|
238710
|
+
} catch (err) {
|
|
238711
|
+
logger.error("PackageMemoryGovernor: RSS sample failed", {
|
|
238712
|
+
error: err
|
|
238713
|
+
});
|
|
238714
|
+
return;
|
|
238715
|
+
}
|
|
238716
|
+
this.lastSampledRss = rss;
|
|
238717
|
+
this.lastSampledAt = Date.now();
|
|
238718
|
+
if (!this.config.backpressureEnabled) {
|
|
238719
|
+
return;
|
|
238720
|
+
}
|
|
238721
|
+
if (rss >= this.highWaterBytes && !this.backpressured) {
|
|
238722
|
+
this.backpressured = true;
|
|
238723
|
+
this.backpressureActivationsCounter.add(1);
|
|
238724
|
+
logger.warn(`PackageMemoryGovernor: activating back-pressure (rss=${rss}B >= high=${this.highWaterBytes}B). New package loads will be rejected with HTTP 503 until rss <= ${this.lowWaterBytes}B.`);
|
|
238725
|
+
} else if (rss <= this.lowWaterBytes && this.backpressured) {
|
|
238726
|
+
this.backpressured = false;
|
|
238727
|
+
logger.info(`PackageMemoryGovernor: clearing back-pressure (rss=${rss}B <= low=${this.lowWaterBytes}B).`);
|
|
238728
|
+
}
|
|
238729
|
+
}
|
|
238730
|
+
isBackpressured() {
|
|
238731
|
+
return this.backpressured;
|
|
238732
|
+
}
|
|
238733
|
+
getStatus() {
|
|
238734
|
+
return {
|
|
238735
|
+
rssBytes: this.lastSampledRss,
|
|
238736
|
+
maxMemoryBytes: this.config.maxMemoryBytes,
|
|
238737
|
+
highWaterBytes: this.highWaterBytes,
|
|
238738
|
+
lowWaterBytes: this.lowWaterBytes,
|
|
238739
|
+
backpressured: this.backpressured,
|
|
238740
|
+
lastSampledAt: this.lastSampledAt
|
|
238741
|
+
};
|
|
238742
|
+
}
|
|
238743
|
+
}
|
|
238744
|
+
|
|
238387
238745
|
// src/server.ts
|
|
238388
238746
|
function normalizeQueryArray(value) {
|
|
238389
238747
|
if (value === undefined || value === null)
|
|
@@ -238465,6 +238823,10 @@ var manifestService = new ManifestService(environmentStore);
|
|
|
238465
238823
|
var watchModeController = new WatchModeController(environmentStore);
|
|
238466
238824
|
var connectionController = new ConnectionController(environmentStore);
|
|
238467
238825
|
var modelController = new ModelController(environmentStore);
|
|
238826
|
+
var memoryGovernorConfig = getMemoryGovernorConfig();
|
|
238827
|
+
var memoryGovernor = memoryGovernorConfig ? new PackageMemoryGovernor(memoryGovernorConfig) : null;
|
|
238828
|
+
memoryGovernor?.start();
|
|
238829
|
+
environmentStore.setMemoryGovernor(memoryGovernor);
|
|
238468
238830
|
var packageController = new PackageController(environmentStore, manifestService);
|
|
238469
238831
|
var databaseController = new DatabaseController(environmentStore);
|
|
238470
238832
|
var queryController = new QueryController(environmentStore);
|