@resolveio/server-lib 22.2.18 → 22.2.20
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/managers/error-auto-fix.manager.d.ts +6 -0
- package/managers/error-auto-fix.manager.js +215 -85
- package/managers/error-auto-fix.manager.js.map +1 -1
- package/managers/method.manager.js +2 -0
- package/managers/method.manager.js.map +1 -1
- package/managers/mongo.manager.d.ts +3 -0
- package/managers/mongo.manager.js +184 -65
- package/managers/mongo.manager.js.map +1 -1
- package/managers/slow-query-verifier.manager.d.ts +30 -0
- package/managers/slow-query-verifier.manager.js +691 -192
- package/managers/slow-query-verifier.manager.js.map +1 -1
- package/managers/subscription.manager.d.ts +1 -0
- package/managers/subscription.manager.js +60 -21
- package/managers/subscription.manager.js.map +1 -1
- package/managers/worker-dispatcher.manager.js +60 -6
- package/managers/worker-dispatcher.manager.js.map +1 -1
- package/methods/ai-terminal.d.ts +4 -0
- package/methods/ai-terminal.js +64 -26
- package/methods/ai-terminal.js.map +1 -1
- package/methods/app-settings.js +2 -2
- package/methods/app-settings.js.map +1 -1
- package/methods/diagnostics.d.ts +2 -0
- package/methods/diagnostics.js +514 -0
- package/methods/diagnostics.js.map +1 -0
- package/methods.ts +15 -0
- package/package.json +1 -1
- package/resolveio-server-app.d.ts +17 -1
- package/resolveio-server-app.js +293 -25
- package/resolveio-server-app.js.map +1 -1
- package/server-app.js +22 -36
- package/server-app.js.map +1 -1
- package/util/error-reporter.js +26 -126
- package/util/error-reporter.js.map +1 -1
- package/util/slow-query-reporter.d.ts +0 -3
- package/util/slow-query-reporter.js +13 -120
- package/util/slow-query-reporter.js.map +1 -1
|
@@ -113,6 +113,7 @@ var resolveio_server_app_1 = require("../resolveio-server-app");
|
|
|
113
113
|
var common_1 = require("../util/common");
|
|
114
114
|
var mongodb_1 = require("mongodb");
|
|
115
115
|
var user_collection_1 = require("../collections/user.collection");
|
|
116
|
+
var app_setting_collection_1 = require("../collections/app-setting.collection");
|
|
116
117
|
var customer_notification_content_manager_1 = require("./customer-notification-content.manager");
|
|
117
118
|
var OPTIONAL_COLLECTION = {
|
|
118
119
|
findOne: function () { return Promise.resolve(null); },
|
|
@@ -192,12 +193,12 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
192
193
|
function SlowQueryVerifier(serverConfig, dependencies) {
|
|
193
194
|
var _this = this;
|
|
194
195
|
this.autoOptimizeInFlight = new Set();
|
|
196
|
+
this.appSettingsAutoOptimizeCacheExpiresAt = 0;
|
|
197
|
+
this.appSettingsAutoOptimizeCacheValue = null;
|
|
195
198
|
var resolvedDependencies = resolveSlowQueryVerifierDependencies(dependencies);
|
|
196
199
|
applySlowQueryVerifierDependencies(resolvedDependencies);
|
|
197
200
|
this.config = SlowQueryVerifier.resolveConfig(serverConfig);
|
|
198
|
-
|
|
199
|
-
this.config.autoOptimizeEnabled = false;
|
|
200
|
-
}
|
|
201
|
+
this.autoOptimizeDependenciesAvailable = !!(resolvedDependencies.AICoderApps && resolvedDependencies.AIDashboardJobs);
|
|
201
202
|
if (this.config.enabled) {
|
|
202
203
|
this._timer = setInterval(function () {
|
|
203
204
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -214,6 +215,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
214
215
|
SlowQueryVerifier.resolveConfig = function (serverConfig) {
|
|
215
216
|
var slowQueryConfig = (serverConfig && (serverConfig.slowQuery || serverConfig.SLOW_QUERY)) || {};
|
|
216
217
|
var verifierConfig = (slowQueryConfig && (slowQueryConfig.verifier || slowQueryConfig.slowQueryVerifier)) || {};
|
|
218
|
+
var autofixConfig = (serverConfig && (serverConfig.autofix || serverConfig.AUTOFIX)) || {};
|
|
217
219
|
var getBoolean = function (envKey, configKey, fallback) {
|
|
218
220
|
if (fallback === void 0) { fallback = true; }
|
|
219
221
|
if (typeof process.env[envKey] !== 'undefined') {
|
|
@@ -239,6 +241,22 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
239
241
|
}
|
|
240
242
|
return fallback;
|
|
241
243
|
};
|
|
244
|
+
var getString = function (envKey, configKey, fallback) {
|
|
245
|
+
if (fallback === void 0) { fallback = ''; }
|
|
246
|
+
if (typeof process.env[envKey] !== 'undefined') {
|
|
247
|
+
return String(process.env[envKey] || '').trim();
|
|
248
|
+
}
|
|
249
|
+
if (typeof verifierConfig[configKey] !== 'undefined') {
|
|
250
|
+
return String(verifierConfig[configKey] || '').trim();
|
|
251
|
+
}
|
|
252
|
+
if (typeof slowQueryConfig[configKey] !== 'undefined') {
|
|
253
|
+
return String(slowQueryConfig[configKey] || '').trim();
|
|
254
|
+
}
|
|
255
|
+
if (typeof autofixConfig[configKey] !== 'undefined') {
|
|
256
|
+
return String(autofixConfig[configKey] || '').trim();
|
|
257
|
+
}
|
|
258
|
+
return fallback;
|
|
259
|
+
};
|
|
242
260
|
var parseEmails = function (value) {
|
|
243
261
|
if (Array.isArray(value)) {
|
|
244
262
|
return value.map(function (item) { return "".concat(item || '').trim().toLowerCase(); }).filter(Boolean);
|
|
@@ -275,11 +293,14 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
275
293
|
|| slowQueryConfig.escalationEmails
|
|
276
294
|
|| slowQueryConfig.notifyEmails);
|
|
277
295
|
return {
|
|
278
|
-
enabled:
|
|
296
|
+
enabled: true,
|
|
279
297
|
fallbackToMainDB: getBoolean('SLOW_QUERY_VERIFIER_FALLBACK_MAIN_DB', 'fallbackToMainDB', true),
|
|
280
298
|
debugLogging: getBoolean('SLOW_QUERY_VERIFIER_DEBUG_LOGS', 'debugLogging', false),
|
|
281
|
-
configSource:
|
|
282
|
-
|
|
299
|
+
configSource: Object.keys(verifierConfig).length ? 'serverConfig' : 'defaults',
|
|
300
|
+
autofixRepoRoot: getString('AUTOFIX_REPO_ROOT', 'repoRoot', '/var/app/current'),
|
|
301
|
+
autofixGithubOwner: getString('AUTOFIX_GITHUB_OWNER', 'githubOwner', 'resolveio'),
|
|
302
|
+
autofixGithubRepo: getString('AUTOFIX_GITHUB_REPO', 'githubRepo', ''),
|
|
303
|
+
autoOptimizeEnabled: getBoolean('SLOW_QUERY_AUTO_OPTIMIZE_ENABLED', 'autoOptimizeEnabled', false),
|
|
283
304
|
autoOptimizeWaitTimeoutMs: getNumber('SLOW_QUERY_AUTO_OPTIMIZE_WAIT_TIMEOUT_MS', 'autoOptimizeWaitTimeoutMs', 45 * 60 * 1000),
|
|
284
305
|
autoOptimizeDurationRatioTarget: clampRatio(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_DURATION_RATIO', 'autoOptimizeDurationRatioTarget', AUTO_OPTIMIZE_DEFAULT_IMPROVEMENT_RATIO), AUTO_OPTIMIZE_DEFAULT_IMPROVEMENT_RATIO),
|
|
285
306
|
autoOptimizeDocsRatioTarget: clampRatio(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_DOCS_RATIO', 'autoOptimizeDocsRatioTarget', AUTO_OPTIMIZE_DEFAULT_IMPROVEMENT_RATIO), AUTO_OPTIMIZE_DEFAULT_IMPROVEMENT_RATIO),
|
|
@@ -290,17 +311,93 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
290
311
|
autoOptimizeFingerprintWindowHours: normalizePositiveInt(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_FINGERPRINT_WINDOW_HOURS', 'autoOptimizeFingerprintWindowHours', AUTO_OPTIMIZE_DEFAULT_FINGERPRINT_WINDOW_HOURS), AUTO_OPTIMIZE_DEFAULT_FINGERPRINT_WINDOW_HOURS),
|
|
291
312
|
autoOptimizeRequiredTokens: normalizeNonNegativeInt(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_REQUIRED_TOKENS', 'autoOptimizeRequiredTokens', 0), 0),
|
|
292
313
|
autoOptimizeOutputCompareEnabled: getBoolean('SLOW_QUERY_AUTO_OPTIMIZE_OUTPUT_COMPARE_ENABLED', 'autoOptimizeOutputCompareEnabled', true),
|
|
314
|
+
autoOptimizeRequireExactOutput: getBoolean('SLOW_QUERY_AUTO_OPTIMIZE_REQUIRE_EXACT_OUTPUT', 'autoOptimizeRequireExactOutput', true),
|
|
315
|
+
autoOptimizeOutputMismatchRetryCount: normalizeNonNegativeInt(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_OUTPUT_MISMATCH_RETRY_COUNT', 'autoOptimizeOutputMismatchRetryCount', 2), 2),
|
|
293
316
|
autoOptimizeOutputCompareMaxDocs: normalizePositiveInt(getNumber('SLOW_QUERY_AUTO_OPTIMIZE_OUTPUT_COMPARE_MAX_DOCS', 'autoOptimizeOutputCompareMaxDocs', AUTO_OPTIMIZE_DEFAULT_OUTPUT_COMPARE_MAX_DOCS), AUTO_OPTIMIZE_DEFAULT_OUTPUT_COMPARE_MAX_DOCS),
|
|
294
317
|
escalationEmails: escalationEmails
|
|
295
318
|
};
|
|
296
319
|
};
|
|
320
|
+
SlowQueryVerifier.prototype.parseBooleanEnv = function (envKey) {
|
|
321
|
+
if (typeof process.env[envKey] === 'undefined') {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
return process.env[envKey] === 'true';
|
|
325
|
+
};
|
|
326
|
+
SlowQueryVerifier.prototype.resolveAutoOptimizeEnabled = function () {
|
|
327
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
328
|
+
var now, envValue, enabled, activeSetting, _a, error_1;
|
|
329
|
+
var _b;
|
|
330
|
+
return __generator(this, function (_c) {
|
|
331
|
+
switch (_c.label) {
|
|
332
|
+
case 0:
|
|
333
|
+
if (!this.autoOptimizeDependenciesAvailable) {
|
|
334
|
+
return [2 /*return*/, false];
|
|
335
|
+
}
|
|
336
|
+
now = Date.now();
|
|
337
|
+
if (this.appSettingsAutoOptimizeCacheValue !== null && now < this.appSettingsAutoOptimizeCacheExpiresAt) {
|
|
338
|
+
return [2 /*return*/, this.appSettingsAutoOptimizeCacheValue];
|
|
339
|
+
}
|
|
340
|
+
envValue = this.parseBooleanEnv('SLOW_QUERY_AUTO_OPTIMIZE_ENABLED');
|
|
341
|
+
enabled = envValue !== null ? envValue : !!this.config.autoOptimizeEnabled;
|
|
342
|
+
_c.label = 1;
|
|
343
|
+
case 1:
|
|
344
|
+
_c.trys.push([1, 6, , 7]);
|
|
345
|
+
if (!(app_setting_collection_1.AppSettings && typeof app_setting_collection_1.AppSettings.findOne === 'function')) return [3 /*break*/, 5];
|
|
346
|
+
return [4 /*yield*/, app_setting_collection_1.AppSettings.findOne({
|
|
347
|
+
is_active: {
|
|
348
|
+
$ne: false
|
|
349
|
+
}
|
|
350
|
+
}, {
|
|
351
|
+
sort: {
|
|
352
|
+
updatedAt: -1,
|
|
353
|
+
createdAt: -1
|
|
354
|
+
}
|
|
355
|
+
})];
|
|
356
|
+
case 2:
|
|
357
|
+
_a = (_c.sent());
|
|
358
|
+
if (_a) return [3 /*break*/, 4];
|
|
359
|
+
return [4 /*yield*/, app_setting_collection_1.AppSettings.findOne({}, {
|
|
360
|
+
sort: {
|
|
361
|
+
updatedAt: -1,
|
|
362
|
+
createdAt: -1
|
|
363
|
+
}
|
|
364
|
+
})];
|
|
365
|
+
case 3:
|
|
366
|
+
_a = (_c.sent());
|
|
367
|
+
_c.label = 4;
|
|
368
|
+
case 4:
|
|
369
|
+
activeSetting = _a;
|
|
370
|
+
if (activeSetting && typeof activeSetting.enable_slow_query_optimizer === 'boolean') {
|
|
371
|
+
enabled = !!activeSetting.enable_slow_query_optimizer;
|
|
372
|
+
}
|
|
373
|
+
_c.label = 5;
|
|
374
|
+
case 5: return [3 /*break*/, 7];
|
|
375
|
+
case 6:
|
|
376
|
+
error_1 = _c.sent();
|
|
377
|
+
if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.debugLogging) {
|
|
378
|
+
console.warn('SlowQueryVerifier failed to read app settings slow-query optimizer toggle', error_1);
|
|
379
|
+
}
|
|
380
|
+
return [3 /*break*/, 7];
|
|
381
|
+
case 7:
|
|
382
|
+
this.appSettingsAutoOptimizeCacheValue = enabled;
|
|
383
|
+
this.appSettingsAutoOptimizeCacheExpiresAt = now + SlowQueryVerifier.APP_SETTINGS_CACHE_TTL_MS;
|
|
384
|
+
return [2 /*return*/, enabled];
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
};
|
|
297
389
|
SlowQueryVerifier.prototype.poll = function () {
|
|
298
390
|
return __awaiter(this, void 0, void 0, function () {
|
|
299
|
-
var now, candidates, candidates_1, candidates_1_1, candidate, e_1_1;
|
|
391
|
+
var autoOptimizeEnabled, now, candidates, candidates_1, candidates_1_1, candidate, e_1_1;
|
|
300
392
|
var e_1, _a;
|
|
301
393
|
return __generator(this, function (_b) {
|
|
302
394
|
switch (_b.label) {
|
|
303
|
-
case 0:
|
|
395
|
+
case 0: return [4 /*yield*/, this.resolveAutoOptimizeEnabled()];
|
|
396
|
+
case 1:
|
|
397
|
+
autoOptimizeEnabled = _b.sent();
|
|
398
|
+
if (!autoOptimizeEnabled) {
|
|
399
|
+
return [2 /*return*/];
|
|
400
|
+
}
|
|
304
401
|
now = new Date();
|
|
305
402
|
return [4 /*yield*/, SlowQueryLogs.find({
|
|
306
403
|
ignored: {
|
|
@@ -328,35 +425,35 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
328
425
|
},
|
|
329
426
|
limit: 5
|
|
330
427
|
})];
|
|
331
|
-
case 1:
|
|
332
|
-
candidates = _b.sent();
|
|
333
|
-
_b.label = 2;
|
|
334
428
|
case 2:
|
|
335
|
-
_b.
|
|
336
|
-
candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next();
|
|
429
|
+
candidates = _b.sent();
|
|
337
430
|
_b.label = 3;
|
|
338
431
|
case 3:
|
|
339
|
-
|
|
432
|
+
_b.trys.push([3, 8, 9, 10]);
|
|
433
|
+
candidates_1 = __values(candidates), candidates_1_1 = candidates_1.next();
|
|
434
|
+
_b.label = 4;
|
|
435
|
+
case 4:
|
|
436
|
+
if (!!candidates_1_1.done) return [3 /*break*/, 7];
|
|
340
437
|
candidate = candidates_1_1.value;
|
|
341
438
|
return [4 /*yield*/, this.processCandidate(candidate)];
|
|
342
|
-
case 4:
|
|
343
|
-
_b.sent();
|
|
344
|
-
_b.label = 5;
|
|
345
439
|
case 5:
|
|
440
|
+
_b.sent();
|
|
441
|
+
_b.label = 6;
|
|
442
|
+
case 6:
|
|
346
443
|
candidates_1_1 = candidates_1.next();
|
|
347
|
-
return [3 /*break*/,
|
|
348
|
-
case
|
|
349
|
-
case
|
|
444
|
+
return [3 /*break*/, 4];
|
|
445
|
+
case 7: return [3 /*break*/, 10];
|
|
446
|
+
case 8:
|
|
350
447
|
e_1_1 = _b.sent();
|
|
351
448
|
e_1 = { error: e_1_1 };
|
|
352
|
-
return [3 /*break*/,
|
|
353
|
-
case
|
|
449
|
+
return [3 /*break*/, 10];
|
|
450
|
+
case 9:
|
|
354
451
|
try {
|
|
355
452
|
if (candidates_1_1 && !candidates_1_1.done && (_a = candidates_1.return)) _a.call(candidates_1);
|
|
356
453
|
}
|
|
357
454
|
finally { if (e_1) throw e_1.error; }
|
|
358
455
|
return [7 /*endfinally*/];
|
|
359
|
-
case
|
|
456
|
+
case 10: return [2 /*return*/];
|
|
360
457
|
}
|
|
361
458
|
});
|
|
362
459
|
});
|
|
@@ -435,6 +532,325 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
435
532
|
});
|
|
436
533
|
});
|
|
437
534
|
};
|
|
535
|
+
SlowQueryVerifier.prototype.runLog = function (logId, options) {
|
|
536
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
537
|
+
var existing, updated;
|
|
538
|
+
return __generator(this, function (_a) {
|
|
539
|
+
switch (_a.label) {
|
|
540
|
+
case 0:
|
|
541
|
+
if (!logId) {
|
|
542
|
+
throw new Error('Slow query log ID is required.');
|
|
543
|
+
}
|
|
544
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
545
|
+
case 1:
|
|
546
|
+
existing = _a.sent();
|
|
547
|
+
if (!existing) {
|
|
548
|
+
return [2 /*return*/, {
|
|
549
|
+
status: 'not_found',
|
|
550
|
+
reason: 'Slow query log not found.'
|
|
551
|
+
}];
|
|
552
|
+
}
|
|
553
|
+
if (existing.ignored) {
|
|
554
|
+
throw new Error('Slow query log is ignored.');
|
|
555
|
+
}
|
|
556
|
+
if (this.autoOptimizeInFlight.has(logId) || existing.auto_fix_status === 'running' || existing.status === 'queued') {
|
|
557
|
+
return [2 /*return*/, {
|
|
558
|
+
status: 'in_progress',
|
|
559
|
+
reason: 'Slow query optimization is already running.',
|
|
560
|
+
log: existing
|
|
561
|
+
}];
|
|
562
|
+
}
|
|
563
|
+
this.autoOptimizeInFlight.add(logId);
|
|
564
|
+
_a.label = 2;
|
|
565
|
+
case 2:
|
|
566
|
+
_a.trys.push([2, , 4, 5]);
|
|
567
|
+
return [4 /*yield*/, this.runLogWithRetries(logId, {
|
|
568
|
+
force: !!(options === null || options === void 0 ? void 0 : options.force),
|
|
569
|
+
retryOutputMismatch: true
|
|
570
|
+
})];
|
|
571
|
+
case 3:
|
|
572
|
+
_a.sent();
|
|
573
|
+
return [3 /*break*/, 5];
|
|
574
|
+
case 4:
|
|
575
|
+
this.autoOptimizeInFlight.delete(logId);
|
|
576
|
+
return [7 /*endfinally*/];
|
|
577
|
+
case 5: return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
578
|
+
case 6:
|
|
579
|
+
updated = _a.sent();
|
|
580
|
+
if (!updated) {
|
|
581
|
+
return [2 /*return*/, {
|
|
582
|
+
status: 'not_found',
|
|
583
|
+
reason: 'Slow query log no longer exists.'
|
|
584
|
+
}];
|
|
585
|
+
}
|
|
586
|
+
if (updated.auto_fix_status === 'running' || updated.status === 'queued') {
|
|
587
|
+
return [2 /*return*/, {
|
|
588
|
+
status: 'in_progress',
|
|
589
|
+
reason: 'Slow query optimization queued.',
|
|
590
|
+
log: updated
|
|
591
|
+
}];
|
|
592
|
+
}
|
|
593
|
+
if (updated.auto_fix_status === 'completed' || updated.status === 'optimized') {
|
|
594
|
+
return [2 /*return*/, {
|
|
595
|
+
status: 'success',
|
|
596
|
+
reason: 'Slow query optimization completed.',
|
|
597
|
+
log: updated
|
|
598
|
+
}];
|
|
599
|
+
}
|
|
600
|
+
if (updated.auto_fix_status === 'failed') {
|
|
601
|
+
return [2 /*return*/, {
|
|
602
|
+
status: 'failed',
|
|
603
|
+
reason: updated.verification_notes || updated.auto_fix_disabled_reason || 'Slow query optimization failed.',
|
|
604
|
+
log: updated
|
|
605
|
+
}];
|
|
606
|
+
}
|
|
607
|
+
return [2 /*return*/, {
|
|
608
|
+
status: 'updated',
|
|
609
|
+
reason: updated.verification_notes || '',
|
|
610
|
+
log: updated
|
|
611
|
+
}];
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
};
|
|
616
|
+
SlowQueryVerifier.prototype.queueLogRun = function (logId, options) {
|
|
617
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
618
|
+
var existing, queuedAt, queuedLog;
|
|
619
|
+
var _this = this;
|
|
620
|
+
return __generator(this, function (_a) {
|
|
621
|
+
switch (_a.label) {
|
|
622
|
+
case 0:
|
|
623
|
+
if (!logId) {
|
|
624
|
+
throw new Error('Slow query log ID is required.');
|
|
625
|
+
}
|
|
626
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
627
|
+
case 1:
|
|
628
|
+
existing = _a.sent();
|
|
629
|
+
if (!existing) {
|
|
630
|
+
return [2 /*return*/, {
|
|
631
|
+
status: 'not_found',
|
|
632
|
+
reason: 'Slow query log not found.'
|
|
633
|
+
}];
|
|
634
|
+
}
|
|
635
|
+
if (existing.ignored) {
|
|
636
|
+
throw new Error('Slow query log is ignored.');
|
|
637
|
+
}
|
|
638
|
+
if (this.autoOptimizeInFlight.has(logId) || existing.auto_fix_status === 'running' || existing.status === 'queued') {
|
|
639
|
+
return [2 /*return*/, {
|
|
640
|
+
status: 'in_progress',
|
|
641
|
+
reason: 'Slow query optimization is already running.',
|
|
642
|
+
log: existing
|
|
643
|
+
}];
|
|
644
|
+
}
|
|
645
|
+
queuedAt = new Date();
|
|
646
|
+
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
647
|
+
$set: {
|
|
648
|
+
status: 'queued',
|
|
649
|
+
auto_fix_status: 'queued',
|
|
650
|
+
verification_notes: 'Slow query optimization queued from super-admin.',
|
|
651
|
+
last_triaged_by: 'super-admin',
|
|
652
|
+
last_triaged_at: queuedAt
|
|
653
|
+
}
|
|
654
|
+
})];
|
|
655
|
+
case 2:
|
|
656
|
+
_a.sent();
|
|
657
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
658
|
+
case 3:
|
|
659
|
+
queuedLog = (_a.sent()) || existing;
|
|
660
|
+
this.autoOptimizeInFlight.add(logId);
|
|
661
|
+
setImmediate(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
662
|
+
var error_2;
|
|
663
|
+
return __generator(this, function (_a) {
|
|
664
|
+
switch (_a.label) {
|
|
665
|
+
case 0:
|
|
666
|
+
_a.trys.push([0, 2, 3, 4]);
|
|
667
|
+
return [4 /*yield*/, this.runLogWithRetries(logId, {
|
|
668
|
+
force: !!(options === null || options === void 0 ? void 0 : options.force),
|
|
669
|
+
retryOutputMismatch: true
|
|
670
|
+
})];
|
|
671
|
+
case 1:
|
|
672
|
+
_a.sent();
|
|
673
|
+
return [3 /*break*/, 4];
|
|
674
|
+
case 2:
|
|
675
|
+
error_2 = _a.sent();
|
|
676
|
+
console.error('Slow query queued run failed', { logId: logId, error: (error_2 === null || error_2 === void 0 ? void 0 : error_2.message) || error_2 });
|
|
677
|
+
return [3 /*break*/, 4];
|
|
678
|
+
case 3:
|
|
679
|
+
this.autoOptimizeInFlight.delete(logId);
|
|
680
|
+
return [7 /*endfinally*/];
|
|
681
|
+
case 4: return [2 /*return*/];
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
}); });
|
|
685
|
+
return [2 /*return*/, {
|
|
686
|
+
status: 'in_progress',
|
|
687
|
+
reason: 'Slow query optimization queued.',
|
|
688
|
+
log: queuedLog
|
|
689
|
+
}];
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
};
|
|
694
|
+
SlowQueryVerifier.prototype.deployLog = function (logId) {
|
|
695
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
696
|
+
var log, jobId, job, publishOutcome, now, existingResult, refreshed, error_3, message, refreshed;
|
|
697
|
+
return __generator(this, function (_a) {
|
|
698
|
+
switch (_a.label) {
|
|
699
|
+
case 0:
|
|
700
|
+
if (!logId) {
|
|
701
|
+
throw new Error('Slow query log ID is required.');
|
|
702
|
+
}
|
|
703
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
704
|
+
case 1:
|
|
705
|
+
log = _a.sent();
|
|
706
|
+
if (!log) {
|
|
707
|
+
return [2 /*return*/, {
|
|
708
|
+
status: 'not_found',
|
|
709
|
+
reason: 'Slow query log not found.'
|
|
710
|
+
}];
|
|
711
|
+
}
|
|
712
|
+
jobId = String(log.openai_task_id || '').trim();
|
|
713
|
+
if (!jobId) {
|
|
714
|
+
throw new Error('Slow query log does not have a dashboard job id to deploy.');
|
|
715
|
+
}
|
|
716
|
+
_a.label = 2;
|
|
717
|
+
case 2:
|
|
718
|
+
_a.trys.push([2, 6, , 9]);
|
|
719
|
+
return [4 /*yield*/, this.publishDashboardJob(jobId)];
|
|
720
|
+
case 3:
|
|
721
|
+
job = _a.sent();
|
|
722
|
+
publishOutcome = this.evaluateDashboardPublishOutcome(job);
|
|
723
|
+
now = new Date();
|
|
724
|
+
existingResult = (log.auto_fix_result && typeof log.auto_fix_result === 'object')
|
|
725
|
+
? __assign({}, log.auto_fix_result) : {};
|
|
726
|
+
existingResult.manual_deploy = {
|
|
727
|
+
job_id: jobId,
|
|
728
|
+
requested_at: now,
|
|
729
|
+
success: publishOutcome.success,
|
|
730
|
+
message: publishOutcome.message,
|
|
731
|
+
branch_name: publishOutcome.branchName || existingResult.publish_branch || ''
|
|
732
|
+
};
|
|
733
|
+
if (publishOutcome.branchName) {
|
|
734
|
+
existingResult.publish_branch = publishOutcome.branchName;
|
|
735
|
+
}
|
|
736
|
+
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
737
|
+
$set: {
|
|
738
|
+
auto_fix_result: existingResult,
|
|
739
|
+
verification_notes: publishOutcome.success
|
|
740
|
+
? "Manual deploy completed: ".concat(publishOutcome.message)
|
|
741
|
+
: "Manual deploy failed: ".concat(publishOutcome.message),
|
|
742
|
+
last_triaged_by: 'super-admin',
|
|
743
|
+
last_triaged_at: now
|
|
744
|
+
}
|
|
745
|
+
})];
|
|
746
|
+
case 4:
|
|
747
|
+
_a.sent();
|
|
748
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
749
|
+
case 5:
|
|
750
|
+
refreshed = (_a.sent()) || log;
|
|
751
|
+
return [2 /*return*/, {
|
|
752
|
+
status: publishOutcome.success ? 'success' : 'failed',
|
|
753
|
+
reason: publishOutcome.message,
|
|
754
|
+
log: refreshed
|
|
755
|
+
}];
|
|
756
|
+
case 6:
|
|
757
|
+
error_3 = _a.sent();
|
|
758
|
+
message = (error_3 === null || error_3 === void 0 ? void 0 : error_3.message) || 'Manual deploy failed.';
|
|
759
|
+
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
760
|
+
$set: {
|
|
761
|
+
verification_notes: "Manual deploy failed: ".concat(message),
|
|
762
|
+
last_triaged_by: 'super-admin',
|
|
763
|
+
last_triaged_at: new Date()
|
|
764
|
+
}
|
|
765
|
+
})];
|
|
766
|
+
case 7:
|
|
767
|
+
_a.sent();
|
|
768
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
769
|
+
case 8:
|
|
770
|
+
refreshed = _a.sent();
|
|
771
|
+
return [2 /*return*/, {
|
|
772
|
+
status: 'failed',
|
|
773
|
+
reason: message,
|
|
774
|
+
log: refreshed || log
|
|
775
|
+
}];
|
|
776
|
+
case 9: return [2 /*return*/];
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
});
|
|
780
|
+
};
|
|
781
|
+
SlowQueryVerifier.prototype.runLogWithRetries = function (logId, options) {
|
|
782
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
783
|
+
var retryBudget, retriesUsed, latest, maxAttempts, attemptsUsed;
|
|
784
|
+
return __generator(this, function (_a) {
|
|
785
|
+
switch (_a.label) {
|
|
786
|
+
case 0:
|
|
787
|
+
retryBudget = options.retryOutputMismatch
|
|
788
|
+
? (Number.isFinite(Number(this.config.autoOptimizeOutputMismatchRetryCount))
|
|
789
|
+
? Number(this.config.autoOptimizeOutputMismatchRetryCount)
|
|
790
|
+
: 0)
|
|
791
|
+
: 0;
|
|
792
|
+
retriesUsed = 0;
|
|
793
|
+
_a.label = 1;
|
|
794
|
+
case 1:
|
|
795
|
+
if (!true) return [3 /*break*/, 5];
|
|
796
|
+
return [4 /*yield*/, this.runAutoOptimization(logId, options.force)];
|
|
797
|
+
case 2:
|
|
798
|
+
_a.sent();
|
|
799
|
+
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
800
|
+
case 3:
|
|
801
|
+
latest = _a.sent();
|
|
802
|
+
if (!latest) {
|
|
803
|
+
return [2 /*return*/, null];
|
|
804
|
+
}
|
|
805
|
+
if (!options.retryOutputMismatch
|
|
806
|
+
|| !this.shouldRetryForOutputMismatch(latest)
|
|
807
|
+
|| retriesUsed >= retryBudget) {
|
|
808
|
+
return [2 /*return*/, latest];
|
|
809
|
+
}
|
|
810
|
+
maxAttempts = Number.isFinite(Number(this.config.autoOptimizeMaxAttemptsPerQuery))
|
|
811
|
+
? Number(this.config.autoOptimizeMaxAttemptsPerQuery)
|
|
812
|
+
: 0;
|
|
813
|
+
attemptsUsed = Number.isFinite(Number(latest.auto_fix_attempt_count))
|
|
814
|
+
? Number(latest.auto_fix_attempt_count)
|
|
815
|
+
: 0;
|
|
816
|
+
if (maxAttempts > 0 && attemptsUsed >= maxAttempts) {
|
|
817
|
+
return [2 /*return*/, latest];
|
|
818
|
+
}
|
|
819
|
+
retriesUsed += 1;
|
|
820
|
+
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
821
|
+
$set: {
|
|
822
|
+
verification_notes: "Output equivalence mismatch detected. Retrying (".concat(retriesUsed, "/").concat(retryBudget, ")."),
|
|
823
|
+
last_triaged_by: 'auto-slow-query',
|
|
824
|
+
last_triaged_at: new Date()
|
|
825
|
+
}
|
|
826
|
+
})];
|
|
827
|
+
case 4:
|
|
828
|
+
_a.sent();
|
|
829
|
+
return [3 /*break*/, 1];
|
|
830
|
+
case 5: return [2 /*return*/];
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
});
|
|
834
|
+
};
|
|
835
|
+
SlowQueryVerifier.prototype.shouldRetryForOutputMismatch = function (log) {
|
|
836
|
+
if (!log || log.ignored || log.auto_fix_status !== 'failed') {
|
|
837
|
+
return false;
|
|
838
|
+
}
|
|
839
|
+
var result = (log.auto_fix_result && typeof log.auto_fix_result === 'object')
|
|
840
|
+
? log.auto_fix_result
|
|
841
|
+
: {};
|
|
842
|
+
var validation = (result.validation && typeof result.validation === 'object')
|
|
843
|
+
? result.validation
|
|
844
|
+
: {};
|
|
845
|
+
var outputEquivalence = result.output_equivalence;
|
|
846
|
+
var validationReason = String(validation.reason || '').toLowerCase();
|
|
847
|
+
var notes = String(log.verification_notes || '').toLowerCase();
|
|
848
|
+
if (outputEquivalence && outputEquivalence.passed === false) {
|
|
849
|
+
return true;
|
|
850
|
+
}
|
|
851
|
+
return validationReason.includes('output equivalence')
|
|
852
|
+
|| notes.includes('output equivalence');
|
|
853
|
+
};
|
|
438
854
|
SlowQueryVerifier.prototype.runExplain = function (log, overrides) {
|
|
439
855
|
return __awaiter(this, void 0, void 0, function () {
|
|
440
856
|
var collectionName, target, client, db, effectiveLog, pipeline_1, filter, findOptions, aggregateOptions_1, explainResponse, usedVerbosity, explainAggregate, cursor, err_3, code, codeName, message, fallbackErr_1, durationMs_1, cursor, _a, durationMs_2, durationMs, explainPlanRaw, explainStatsRaw, stageSummaries, explainPlan, explainStats;
|
|
@@ -807,7 +1223,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
807
1223
|
});
|
|
808
1224
|
};
|
|
809
1225
|
SlowQueryVerifier.prototype.scheduleAutoOptimization = function (logId) {
|
|
810
|
-
if (!
|
|
1226
|
+
if (!logId) {
|
|
811
1227
|
return;
|
|
812
1228
|
}
|
|
813
1229
|
if (this.autoOptimizeInFlight.has(logId)) {
|
|
@@ -819,7 +1235,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
819
1235
|
SlowQueryVerifier.prototype.runAutoOptimizationInBackground = function (logId) {
|
|
820
1236
|
var _this = this;
|
|
821
1237
|
setImmediate(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
822
|
-
var
|
|
1238
|
+
var error_4;
|
|
823
1239
|
return __generator(this, function (_a) {
|
|
824
1240
|
switch (_a.label) {
|
|
825
1241
|
case 0:
|
|
@@ -829,8 +1245,8 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
829
1245
|
_a.sent();
|
|
830
1246
|
return [3 /*break*/, 4];
|
|
831
1247
|
case 2:
|
|
832
|
-
|
|
833
|
-
console.error('Slow query auto optimization failed', { logId: logId, error: (
|
|
1248
|
+
error_4 = _a.sent();
|
|
1249
|
+
console.error('Slow query auto optimization failed', { logId: logId, error: (error_4 === null || error_4 === void 0 ? void 0 : error_4.message) || error_4 });
|
|
834
1250
|
return [3 /*break*/, 4];
|
|
835
1251
|
case 3:
|
|
836
1252
|
this.autoOptimizeInFlight.delete(logId);
|
|
@@ -858,7 +1274,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
858
1274
|
};
|
|
859
1275
|
SlowQueryVerifier.prototype.sendSlowQueryEscalationNotice = function (log, reason) {
|
|
860
1276
|
return __awaiter(this, void 0, void 0, function () {
|
|
861
|
-
var recipients, subject, body, methodManager, recipients_1, recipients_1_1, recipient,
|
|
1277
|
+
var recipients, subject, body, methodManager, recipients_1, recipients_1_1, recipient, error_5, e_2_1;
|
|
862
1278
|
var e_2, _a;
|
|
863
1279
|
return __generator(this, function (_b) {
|
|
864
1280
|
switch (_b.label) {
|
|
@@ -899,8 +1315,8 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
899
1315
|
_b.sent();
|
|
900
1316
|
return [3 /*break*/, 6];
|
|
901
1317
|
case 5:
|
|
902
|
-
|
|
903
|
-
console.error('Failed sending slow-query escalation email', { recipient: recipient, logId: log._id, error:
|
|
1318
|
+
error_5 = _b.sent();
|
|
1319
|
+
console.error('Failed sending slow-query escalation email', { recipient: recipient, logId: log._id, error: error_5 });
|
|
904
1320
|
return [3 /*break*/, 6];
|
|
905
1321
|
case 6:
|
|
906
1322
|
recipients_1_1 = recipients_1.next();
|
|
@@ -1163,7 +1579,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1163
1579
|
};
|
|
1164
1580
|
SlowQueryVerifier.prototype.notifyCustomerSlowQueryStatus = function (stage, log, extra) {
|
|
1165
1581
|
return __awaiter(this, void 0, void 0, function () {
|
|
1166
|
-
var target, isGeneratedApp, generatedApp, issueKey, dedupeKey, metadata, targetPayload, idUsers, payload,
|
|
1582
|
+
var target, isGeneratedApp, generatedApp, issueKey, dedupeKey, metadata, targetPayload, idUsers, payload, error_6;
|
|
1167
1583
|
return __generator(this, function (_a) {
|
|
1168
1584
|
switch (_a.label) {
|
|
1169
1585
|
case 0:
|
|
@@ -1259,12 +1675,12 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1259
1675
|
_a.sent();
|
|
1260
1676
|
return [3 /*break*/, 12];
|
|
1261
1677
|
case 11:
|
|
1262
|
-
|
|
1678
|
+
error_6 = _a.sent();
|
|
1263
1679
|
if (this.config.debugLogging) {
|
|
1264
1680
|
console.warn('Slow query customer notification failed', {
|
|
1265
1681
|
logId: log._id,
|
|
1266
1682
|
stage: stage,
|
|
1267
|
-
error: (
|
|
1683
|
+
error: (error_6 === null || error_6 === void 0 ? void 0 : error_6.message) || error_6
|
|
1268
1684
|
});
|
|
1269
1685
|
}
|
|
1270
1686
|
return [3 /*break*/, 12];
|
|
@@ -1597,7 +2013,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1597
2013
|
};
|
|
1598
2014
|
SlowQueryVerifier.prototype.createDashboardJob = function (payload) {
|
|
1599
2015
|
return __awaiter(this, void 0, void 0, function () {
|
|
1600
|
-
var methodManager,
|
|
2016
|
+
var methodManager, error_7, manager;
|
|
1601
2017
|
return __generator(this, function (_a) {
|
|
1602
2018
|
switch (_a.label) {
|
|
1603
2019
|
case 0:
|
|
@@ -1608,9 +2024,9 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1608
2024
|
return [4 /*yield*/, methodManager.callMethod('aiDashboardCreateJob', payload)];
|
|
1609
2025
|
case 2: return [2 /*return*/, _a.sent()];
|
|
1610
2026
|
case 3:
|
|
1611
|
-
|
|
1612
|
-
if (!this.shouldFallbackDashboardMethod(
|
|
1613
|
-
throw
|
|
2027
|
+
error_7 = _a.sent();
|
|
2028
|
+
if (!this.shouldFallbackDashboardMethod(error_7)) {
|
|
2029
|
+
throw error_7;
|
|
1614
2030
|
}
|
|
1615
2031
|
return [3 /*break*/, 4];
|
|
1616
2032
|
case 4:
|
|
@@ -1625,7 +2041,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1625
2041
|
};
|
|
1626
2042
|
SlowQueryVerifier.prototype.waitForDashboardJobStop = function (jobId, timeoutMs) {
|
|
1627
2043
|
return __awaiter(this, void 0, void 0, function () {
|
|
1628
|
-
var methodManager,
|
|
2044
|
+
var methodManager, error_8, manager;
|
|
1629
2045
|
return __generator(this, function (_a) {
|
|
1630
2046
|
switch (_a.label) {
|
|
1631
2047
|
case 0:
|
|
@@ -1638,9 +2054,9 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1638
2054
|
_a.sent();
|
|
1639
2055
|
return [2 /*return*/];
|
|
1640
2056
|
case 3:
|
|
1641
|
-
|
|
1642
|
-
if (!this.shouldFallbackDashboardMethod(
|
|
1643
|
-
throw
|
|
2057
|
+
error_8 = _a.sent();
|
|
2058
|
+
if (!this.shouldFallbackDashboardMethod(error_8)) {
|
|
2059
|
+
throw error_8;
|
|
1644
2060
|
}
|
|
1645
2061
|
return [3 /*break*/, 4];
|
|
1646
2062
|
case 4:
|
|
@@ -1657,7 +2073,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1657
2073
|
};
|
|
1658
2074
|
SlowQueryVerifier.prototype.isDashboardJobRunning = function (jobId) {
|
|
1659
2075
|
return __awaiter(this, void 0, void 0, function () {
|
|
1660
|
-
var methodManager, running,
|
|
2076
|
+
var methodManager, running, error_9, manager;
|
|
1661
2077
|
return __generator(this, function (_a) {
|
|
1662
2078
|
switch (_a.label) {
|
|
1663
2079
|
case 0:
|
|
@@ -1670,9 +2086,9 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1670
2086
|
running = _a.sent();
|
|
1671
2087
|
return [2 /*return*/, !!running];
|
|
1672
2088
|
case 3:
|
|
1673
|
-
|
|
1674
|
-
if (!this.shouldFallbackDashboardMethod(
|
|
1675
|
-
throw
|
|
2089
|
+
error_9 = _a.sent();
|
|
2090
|
+
if (!this.shouldFallbackDashboardMethod(error_9)) {
|
|
2091
|
+
throw error_9;
|
|
1676
2092
|
}
|
|
1677
2093
|
return [3 /*break*/, 4];
|
|
1678
2094
|
case 4:
|
|
@@ -1685,6 +2101,34 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1685
2101
|
});
|
|
1686
2102
|
});
|
|
1687
2103
|
};
|
|
2104
|
+
SlowQueryVerifier.prototype.publishDashboardJob = function (jobId) {
|
|
2105
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2106
|
+
var methodManager, error_10, manager;
|
|
2107
|
+
return __generator(this, function (_a) {
|
|
2108
|
+
switch (_a.label) {
|
|
2109
|
+
case 0:
|
|
2110
|
+
methodManager = resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager();
|
|
2111
|
+
_a.label = 1;
|
|
2112
|
+
case 1:
|
|
2113
|
+
_a.trys.push([1, 3, , 4]);
|
|
2114
|
+
return [4 /*yield*/, methodManager.callMethod('aiDashboardPublishJob', jobId)];
|
|
2115
|
+
case 2: return [2 /*return*/, _a.sent()];
|
|
2116
|
+
case 3:
|
|
2117
|
+
error_10 = _a.sent();
|
|
2118
|
+
if (!this.shouldFallbackDashboardMethod(error_10)) {
|
|
2119
|
+
throw error_10;
|
|
2120
|
+
}
|
|
2121
|
+
return [3 /*break*/, 4];
|
|
2122
|
+
case 4:
|
|
2123
|
+
manager = resolveio_server_app_1.ResolveIOServer['AIDashboardManager'];
|
|
2124
|
+
if (!(manager && manager.isEnabled && manager.isEnabled() && typeof manager.publishJob === 'function')) return [3 /*break*/, 6];
|
|
2125
|
+
return [4 /*yield*/, manager.publishJob(jobId)];
|
|
2126
|
+
case 5: return [2 /*return*/, _a.sent()];
|
|
2127
|
+
case 6: throw new Error('AI Dashboard manager is not available.');
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
});
|
|
2131
|
+
};
|
|
1688
2132
|
SlowQueryVerifier.prototype.evaluateDashboardPublishOutcome = function (job) {
|
|
1689
2133
|
var logEntries = Array.isArray(job === null || job === void 0 ? void 0 : job.log) ? job.log : [];
|
|
1690
2134
|
var lastMatch = function (predicate) {
|
|
@@ -1701,7 +2145,12 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1701
2145
|
}
|
|
1702
2146
|
var publishEntry = lastMatch(function (entry) { return /Published build to /i.test(entry || ''); });
|
|
1703
2147
|
if (publishEntry) {
|
|
1704
|
-
|
|
2148
|
+
var branchMatch = publishEntry.match(/\(([^()]+)\)\.?$/);
|
|
2149
|
+
return {
|
|
2150
|
+
success: true,
|
|
2151
|
+
message: publishEntry,
|
|
2152
|
+
branchName: (branchMatch && branchMatch[1]) ? branchMatch[1].trim() : undefined
|
|
2153
|
+
};
|
|
1705
2154
|
}
|
|
1706
2155
|
var skippedEntry = lastMatch(function (entry) { return /Publish skipped/i.test(entry || ''); });
|
|
1707
2156
|
if (skippedEntry) {
|
|
@@ -1933,6 +2382,22 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
1933
2382
|
};
|
|
1934
2383
|
};
|
|
1935
2384
|
SlowQueryVerifier.prototype.evaluateOptimizationOutcome = function (baseline, after, outputEquivalence) {
|
|
2385
|
+
if (this.config.autoOptimizeRequireExactOutput) {
|
|
2386
|
+
if (!this.config.autoOptimizeOutputCompareEnabled) {
|
|
2387
|
+
return {
|
|
2388
|
+
passed: false,
|
|
2389
|
+
reason: 'Exact output equivalence is required but output comparison is disabled.',
|
|
2390
|
+
outputEquivalence: outputEquivalence
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
if (!outputEquivalence) {
|
|
2394
|
+
return {
|
|
2395
|
+
passed: false,
|
|
2396
|
+
reason: 'Output equivalence proof is required but was not generated.',
|
|
2397
|
+
outputEquivalence: outputEquivalence
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
1936
2401
|
if (outputEquivalence && !outputEquivalence.passed) {
|
|
1937
2402
|
return {
|
|
1938
2403
|
passed: false,
|
|
@@ -2020,7 +2485,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2020
2485
|
}
|
|
2021
2486
|
return "".concat(index + 1, ". ").concat(stage.stage, " @ ").concat(stage.path).concat(metrics.length ? " (".concat(metrics.join(', '), ")") : '');
|
|
2022
2487
|
};
|
|
2023
|
-
SlowQueryVerifier.prototype.buildSlowQueryAutoOptimizeDescription = function (log, app, baseline) {
|
|
2488
|
+
SlowQueryVerifier.prototype.buildSlowQueryAutoOptimizeDescription = function (log, app, baseline, repoSlug) {
|
|
2024
2489
|
var _this = this;
|
|
2025
2490
|
var topStages = Array.isArray(baseline.topStages) ? baseline.topStages : [];
|
|
2026
2491
|
var lookupExprInCount = SlowQueryVerifier.countLookupExprInPattern(Array.isArray(log.pipeline) ? log.pipeline : []);
|
|
@@ -2035,14 +2500,17 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2035
2500
|
'5. Locate the source query in app code and optimize it safely (query shape contract must remain compatible).',
|
|
2036
2501
|
'6. Add or adjust indexes/code paths so docs examined and processing time drop significantly.',
|
|
2037
2502
|
'7. Measure before/after `explain(\"executionStats\")` and identify the slowest stages by execution time/docs examined.',
|
|
2038
|
-
'8.
|
|
2503
|
+
'8. Returned data must be exactly equivalent before and after optimization. Any output difference is a failed run.',
|
|
2039
2504
|
'9. In `$lookup`, avoid `$expr` + `$in` when equivalent `localField` / `foreignField` joins are possible and index-friendly.',
|
|
2040
2505
|
'10. Run build/lint checks and iterate until green.',
|
|
2041
|
-
'11.
|
|
2506
|
+
'11. Use workspace context `/var/ai-workspace/<id_slow_query>` and inspect transpiled runtime references under `/var/app/current`.',
|
|
2507
|
+
'12. Publish to default branch and deploy artifacts automatically after build success.',
|
|
2042
2508
|
'',
|
|
2043
2509
|
"App: ".concat(app.name || app._id),
|
|
2044
|
-
"Repo: ".concat(app.repo || 'unknown'),
|
|
2510
|
+
"Repo: ".concat(repoSlug || app.repo || 'unknown'),
|
|
2045
2511
|
"Slow Query #: ".concat(log.slow_query_count_string || log._id || ''),
|
|
2512
|
+
"Workspace Context Id: ".concat(String((log === null || log === void 0 ? void 0 : log._id) || '').trim() || 'n/a'),
|
|
2513
|
+
"Workspace Path: /var/ai-workspace/".concat(String((log === null || log === void 0 ? void 0 : log._id) || '').trim() || '<id_slow_query>'),
|
|
2046
2514
|
"Collection: ".concat(log.collection),
|
|
2047
2515
|
"Query Hash: ".concat(log.query_hash),
|
|
2048
2516
|
"Slow Query Log Id: ".concat(String((log === null || log === void 0 ? void 0 : log._id) || '').trim() || 'n/a'),
|
|
@@ -2076,6 +2544,23 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2076
2544
|
], false);
|
|
2077
2545
|
return lines.join('\n');
|
|
2078
2546
|
};
|
|
2547
|
+
SlowQueryVerifier.prototype.resolveAutoOptimizeRepoSlug = function (app) {
|
|
2548
|
+
var _a, _b;
|
|
2549
|
+
var configuredRepo = String(((_a = this.config) === null || _a === void 0 ? void 0 : _a.autofixGithubRepo) || '').trim();
|
|
2550
|
+
var configuredOwner = String(((_b = this.config) === null || _b === void 0 ? void 0 : _b.autofixGithubOwner) || 'resolveio').trim() || 'resolveio';
|
|
2551
|
+
if (configuredRepo) {
|
|
2552
|
+
return "".concat(configuredOwner, "/").concat(configuredRepo);
|
|
2553
|
+
}
|
|
2554
|
+
return String((app === null || app === void 0 ? void 0 : app.repo) || '').trim();
|
|
2555
|
+
};
|
|
2556
|
+
SlowQueryVerifier.prototype.resolveAutoOptimizeRepoPath = function (app) {
|
|
2557
|
+
var _a;
|
|
2558
|
+
var configuredPath = String(((_a = this.config) === null || _a === void 0 ? void 0 : _a.autofixRepoRoot) || '').trim();
|
|
2559
|
+
if (configuredPath) {
|
|
2560
|
+
return configuredPath;
|
|
2561
|
+
}
|
|
2562
|
+
return String((app === null || app === void 0 ? void 0 : app.git_local_path) || '').trim();
|
|
2563
|
+
};
|
|
2079
2564
|
SlowQueryVerifier.queryHasExplicitSort = function (pipeline, findOptions) {
|
|
2080
2565
|
var hasFindSort = !!((findOptions === null || findOptions === void 0 ? void 0 : findOptions.sort) && typeof findOptions.sort === 'object' && Object.keys(findOptions.sort).length);
|
|
2081
2566
|
if (hasFindSort) {
|
|
@@ -2496,184 +2981,193 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2496
2981
|
});
|
|
2497
2982
|
});
|
|
2498
2983
|
};
|
|
2499
|
-
SlowQueryVerifier.prototype.runAutoOptimization = function (
|
|
2500
|
-
return __awaiter(this,
|
|
2501
|
-
var log, attemptsUsed, maxAttempts, cooldownDeadline, fingerprintMaxAttempts, windowHours, windowStart, fingerprintAttempts, app, tokenEligibility, reason, baselineExplain,
|
|
2984
|
+
SlowQueryVerifier.prototype.runAutoOptimization = function (logId_1) {
|
|
2985
|
+
return __awaiter(this, arguments, void 0, function (logId, force) {
|
|
2986
|
+
var autoOptimizeEnabled, log, attemptsUsed, maxAttempts, cooldownDeadline, fingerprintMaxAttempts, windowHours, windowStart, fingerprintAttempts, app, resolvedRepoSlug, resolvedRepoPath, tokenEligibility, reason, baselineExplain, error_11, baselineFallbackDuration, baselineDurationMs, baselineMetrics, baselineOutputFingerprint, error_12, title, description, job, error_13, jobId, attemptStartedAt, queuedLog, error_14, isRunning, error_15, finalJob, publishOutcome, refreshedLog, afterExplain, error_16, afterMetrics, outputEquivalence, afterOutputFingerprint, error_17, validation, autoFixResult, optimizedLog;
|
|
2987
|
+
if (force === void 0) { force = false; }
|
|
2502
2988
|
return __generator(this, function (_a) {
|
|
2503
2989
|
switch (_a.label) {
|
|
2504
|
-
case 0:
|
|
2505
|
-
|
|
2990
|
+
case 0: return [4 /*yield*/, this.resolveAutoOptimizeEnabled()];
|
|
2991
|
+
case 1:
|
|
2992
|
+
autoOptimizeEnabled = _a.sent();
|
|
2993
|
+
if (!logId || (!autoOptimizeEnabled && !force)) {
|
|
2506
2994
|
return [2 /*return*/];
|
|
2507
2995
|
}
|
|
2508
2996
|
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
2509
|
-
case
|
|
2997
|
+
case 2:
|
|
2510
2998
|
log = _a.sent();
|
|
2511
2999
|
if (!log || !log._id || log.ignored) {
|
|
2512
3000
|
return [2 /*return*/];
|
|
2513
3001
|
}
|
|
2514
|
-
if (log.status === 'optimized') {
|
|
3002
|
+
if (log.status === 'optimized' && !force) {
|
|
2515
3003
|
return [2 /*return*/];
|
|
2516
3004
|
}
|
|
2517
|
-
if (log.auto_fix_status === 'running'
|
|
3005
|
+
if (log.auto_fix_status === 'running') {
|
|
2518
3006
|
return [2 /*return*/];
|
|
2519
3007
|
}
|
|
3008
|
+
if (log.auto_fix_status === 'queued' && String(log.openai_task_id || '').trim()) {
|
|
3009
|
+
return [2 /*return*/];
|
|
3010
|
+
}
|
|
3011
|
+
if (!!force) return [3 /*break*/, 9];
|
|
2520
3012
|
attemptsUsed = Number.isFinite(Number(log.auto_fix_attempt_count))
|
|
2521
3013
|
? Number(log.auto_fix_attempt_count)
|
|
2522
3014
|
: 0;
|
|
2523
3015
|
maxAttempts = Number.isFinite(Number(this.config.autoOptimizeMaxAttemptsPerQuery))
|
|
2524
3016
|
? Number(this.config.autoOptimizeMaxAttemptsPerQuery)
|
|
2525
3017
|
: 0;
|
|
2526
|
-
if (!(maxAttempts > 0 && attemptsUsed >= maxAttempts)) return [3 /*break*/,
|
|
3018
|
+
if (!(maxAttempts > 0 && attemptsUsed >= maxAttempts)) return [3 /*break*/, 4];
|
|
2527
3019
|
return [4 /*yield*/, this.markAutoOptimizeBudgetExceeded(log, 'Auto optimize skipped')];
|
|
2528
|
-
case
|
|
3020
|
+
case 3:
|
|
2529
3021
|
_a.sent();
|
|
2530
3022
|
return [2 /*return*/];
|
|
2531
|
-
case
|
|
3023
|
+
case 4:
|
|
2532
3024
|
cooldownDeadline = this.resolveCooldownDeadline(log);
|
|
2533
|
-
if (!(cooldownDeadline && cooldownDeadline.getTime() > Date.now())) return [3 /*break*/,
|
|
3025
|
+
if (!(cooldownDeadline && cooldownDeadline.getTime() > Date.now())) return [3 /*break*/, 6];
|
|
2534
3026
|
return [4 /*yield*/, this.markAutoOptimizeCooldownActive(log, cooldownDeadline)];
|
|
2535
|
-
case
|
|
3027
|
+
case 5:
|
|
2536
3028
|
_a.sent();
|
|
2537
3029
|
return [2 /*return*/];
|
|
2538
|
-
case
|
|
3030
|
+
case 6:
|
|
2539
3031
|
fingerprintMaxAttempts = Number.isFinite(Number(this.config.autoOptimizeMaxAttemptsPerFingerprint))
|
|
2540
3032
|
? Number(this.config.autoOptimizeMaxAttemptsPerFingerprint)
|
|
2541
3033
|
: 0;
|
|
2542
|
-
if (!(fingerprintMaxAttempts > 0)) return [3 /*break*/,
|
|
3034
|
+
if (!(fingerprintMaxAttempts > 0)) return [3 /*break*/, 9];
|
|
2543
3035
|
windowHours = Number.isFinite(Number(this.config.autoOptimizeFingerprintWindowHours))
|
|
2544
3036
|
? Number(this.config.autoOptimizeFingerprintWindowHours)
|
|
2545
3037
|
: AUTO_OPTIMIZE_DEFAULT_FINGERPRINT_WINDOW_HOURS;
|
|
2546
3038
|
windowStart = new Date(Date.now() - (windowHours * 60 * 60 * 1000));
|
|
2547
3039
|
return [4 /*yield*/, this.resolveFingerprintAttemptsInWindow(log, windowStart)];
|
|
2548
|
-
case
|
|
3040
|
+
case 7:
|
|
2549
3041
|
fingerprintAttempts = _a.sent();
|
|
2550
|
-
if (!(fingerprintAttempts >= fingerprintMaxAttempts)) return [3 /*break*/,
|
|
3042
|
+
if (!(fingerprintAttempts >= fingerprintMaxAttempts)) return [3 /*break*/, 9];
|
|
2551
3043
|
return [4 /*yield*/, this.markAutoOptimizeBudgetExceeded(log, "Auto optimize skipped: fingerprint budget reached (".concat(fingerprintAttempts, "/").concat(fingerprintMaxAttempts, ") in the last ").concat(windowHours, "h."))];
|
|
2552
|
-
case
|
|
3044
|
+
case 8:
|
|
2553
3045
|
_a.sent();
|
|
2554
3046
|
return [2 /*return*/];
|
|
2555
|
-
case
|
|
2556
|
-
case
|
|
3047
|
+
case 9: return [4 /*yield*/, this.resolveAutoOptimizeApp(log)];
|
|
3048
|
+
case 10:
|
|
2557
3049
|
app = _a.sent();
|
|
2558
|
-
|
|
3050
|
+
resolvedRepoSlug = this.resolveAutoOptimizeRepoSlug(app);
|
|
3051
|
+
resolvedRepoPath = this.resolveAutoOptimizeRepoPath(app);
|
|
3052
|
+
if (!(!(app === null || app === void 0 ? void 0 : app._id) || !resolvedRepoSlug)) return [3 /*break*/, 12];
|
|
2559
3053
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2560
3054
|
$set: {
|
|
2561
3055
|
status: 'investigating',
|
|
2562
3056
|
auto_fix_status: 'failed',
|
|
2563
|
-
verification_notes: 'Auto optimize skipped: unable to map slow query to AI Coder app/repo.',
|
|
3057
|
+
verification_notes: 'Auto optimize skipped: unable to map slow query to AI Coder app/repo configuration.',
|
|
2564
3058
|
last_triaged_by: 'auto-slow-query',
|
|
2565
3059
|
last_triaged_at: new Date()
|
|
2566
3060
|
}
|
|
2567
3061
|
})];
|
|
2568
|
-
case
|
|
3062
|
+
case 11:
|
|
2569
3063
|
_a.sent();
|
|
2570
3064
|
return [2 /*return*/];
|
|
2571
|
-
case
|
|
2572
|
-
case
|
|
3065
|
+
case 12: return [4 /*yield*/, checkAICoderTokenEligibility(app._id, this.config.autoOptimizeRequiredTokens > 0 ? this.config.autoOptimizeRequiredTokens : undefined)];
|
|
3066
|
+
case 13:
|
|
2573
3067
|
tokenEligibility = _a.sent();
|
|
2574
|
-
if (!!tokenEligibility.allowed) return [3 /*break*/,
|
|
3068
|
+
if (!!tokenEligibility.allowed) return [3 /*break*/, 15];
|
|
2575
3069
|
reason = "".concat(tokenEligibility.message, " Available: ").concat(tokenEligibility.summary.available_tokens.toLocaleString(), " tokens; required: ").concat(tokenEligibility.required_tokens.toLocaleString(), ".");
|
|
2576
3070
|
return [4 /*yield*/, this.markAutoOptimizeTokenIneligible(log, reason)];
|
|
2577
|
-
case
|
|
3071
|
+
case 14:
|
|
2578
3072
|
_a.sent();
|
|
2579
3073
|
return [2 /*return*/];
|
|
2580
|
-
case 14:
|
|
2581
|
-
_a.trys.push([14, 16, , 19]);
|
|
2582
|
-
return [4 /*yield*/, this.runExplain(log)];
|
|
2583
3074
|
case 15:
|
|
2584
|
-
|
|
2585
|
-
return [
|
|
3075
|
+
_a.trys.push([15, 17, , 20]);
|
|
3076
|
+
return [4 /*yield*/, this.runExplain(log)];
|
|
2586
3077
|
case 16:
|
|
2587
|
-
|
|
3078
|
+
baselineExplain = _a.sent();
|
|
3079
|
+
return [3 /*break*/, 20];
|
|
3080
|
+
case 17:
|
|
3081
|
+
error_11 = _a.sent();
|
|
2588
3082
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2589
3083
|
$set: {
|
|
2590
3084
|
status: 'investigating',
|
|
2591
3085
|
auto_fix_status: 'failed',
|
|
2592
3086
|
auto_fix_result: {
|
|
2593
|
-
baseline_error: (
|
|
3087
|
+
baseline_error: (error_11 === null || error_11 === void 0 ? void 0 : error_11.message) || 'unknown'
|
|
2594
3088
|
},
|
|
2595
|
-
verification_notes: "Auto optimize baseline measurement failed: ".concat((
|
|
3089
|
+
verification_notes: "Auto optimize baseline measurement failed: ".concat((error_11 === null || error_11 === void 0 ? void 0 : error_11.message) || 'unknown error'),
|
|
2596
3090
|
last_triaged_by: 'auto-slow-query',
|
|
2597
3091
|
last_triaged_at: new Date()
|
|
2598
3092
|
}
|
|
2599
3093
|
})];
|
|
2600
|
-
case
|
|
3094
|
+
case 18:
|
|
2601
3095
|
_a.sent();
|
|
2602
3096
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize baseline measurement failed')];
|
|
2603
|
-
case
|
|
3097
|
+
case 19:
|
|
2604
3098
|
_a.sent();
|
|
2605
3099
|
return [2 /*return*/];
|
|
2606
|
-
case
|
|
3100
|
+
case 20:
|
|
2607
3101
|
baselineFallbackDuration = this.resolveBaselineDurationMs(log);
|
|
2608
3102
|
baselineDurationMs = SlowQueryVerifier.isValidDuration(baselineExplain.durationMs)
|
|
2609
3103
|
? baselineExplain.durationMs
|
|
2610
3104
|
: baselineFallbackDuration;
|
|
2611
3105
|
baselineMetrics = this.resolveExecutionMetrics(baselineExplain.explainStats || {}, baselineDurationMs, baselineExplain.stageSummaries || []);
|
|
2612
|
-
if (!this.config.autoOptimizeOutputCompareEnabled) return [3 /*break*/,
|
|
2613
|
-
_a.label =
|
|
2614
|
-
case 20:
|
|
2615
|
-
_a.trys.push([20, 22, , 25]);
|
|
2616
|
-
return [4 /*yield*/, this.captureOutputFingerprint(log)];
|
|
3106
|
+
if (!this.config.autoOptimizeOutputCompareEnabled) return [3 /*break*/, 26];
|
|
3107
|
+
_a.label = 21;
|
|
2617
3108
|
case 21:
|
|
2618
|
-
|
|
2619
|
-
return [
|
|
3109
|
+
_a.trys.push([21, 23, , 26]);
|
|
3110
|
+
return [4 /*yield*/, this.captureOutputFingerprint(log)];
|
|
2620
3111
|
case 22:
|
|
2621
|
-
|
|
3112
|
+
baselineOutputFingerprint = _a.sent();
|
|
3113
|
+
return [3 /*break*/, 26];
|
|
3114
|
+
case 23:
|
|
3115
|
+
error_12 = _a.sent();
|
|
2622
3116
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2623
3117
|
$set: {
|
|
2624
3118
|
status: 'investigating',
|
|
2625
3119
|
auto_fix_status: 'failed',
|
|
2626
3120
|
auto_fix_result: {
|
|
2627
|
-
baseline_error: (
|
|
3121
|
+
baseline_error: (error_12 === null || error_12 === void 0 ? void 0 : error_12.message) || 'unknown'
|
|
2628
3122
|
},
|
|
2629
|
-
verification_notes: "Auto optimize baseline output comparison failed: ".concat((
|
|
3123
|
+
verification_notes: "Auto optimize baseline output comparison failed: ".concat((error_12 === null || error_12 === void 0 ? void 0 : error_12.message) || 'unknown error'),
|
|
2630
3124
|
last_triaged_by: 'auto-slow-query',
|
|
2631
3125
|
last_triaged_at: new Date()
|
|
2632
3126
|
}
|
|
2633
3127
|
})];
|
|
2634
|
-
case
|
|
3128
|
+
case 24:
|
|
2635
3129
|
_a.sent();
|
|
2636
3130
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize baseline output comparison failed')];
|
|
2637
|
-
case
|
|
3131
|
+
case 25:
|
|
2638
3132
|
_a.sent();
|
|
2639
3133
|
return [2 /*return*/];
|
|
2640
|
-
case 25:
|
|
2641
|
-
title = "Optimize slow query ".concat(log.slow_query_count_string || log.collection);
|
|
2642
|
-
description = this.buildSlowQueryAutoOptimizeDescription(log, app, baselineMetrics);
|
|
2643
|
-
_a.label = 26;
|
|
2644
3134
|
case 26:
|
|
2645
|
-
|
|
3135
|
+
title = "Optimize slow query ".concat(log.slow_query_count_string || log.collection);
|
|
3136
|
+
description = this.buildSlowQueryAutoOptimizeDescription(log, app, baselineMetrics, resolvedRepoSlug);
|
|
3137
|
+
_a.label = 27;
|
|
3138
|
+
case 27:
|
|
3139
|
+
_a.trys.push([27, 29, , 32]);
|
|
2646
3140
|
return [4 /*yield*/, this.createDashboardJob({
|
|
2647
3141
|
project: app._id,
|
|
2648
3142
|
title: title,
|
|
2649
3143
|
description: description,
|
|
2650
|
-
repo:
|
|
2651
|
-
path:
|
|
3144
|
+
repo: resolvedRepoSlug,
|
|
3145
|
+
path: resolvedRepoPath || undefined,
|
|
2652
3146
|
projectRoot: app.project_root || undefined
|
|
2653
3147
|
})];
|
|
2654
|
-
case 27:
|
|
2655
|
-
job = _a.sent();
|
|
2656
|
-
return [3 /*break*/, 31];
|
|
2657
3148
|
case 28:
|
|
2658
|
-
|
|
3149
|
+
job = _a.sent();
|
|
3150
|
+
return [3 /*break*/, 32];
|
|
3151
|
+
case 29:
|
|
3152
|
+
error_13 = _a.sent();
|
|
2659
3153
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2660
3154
|
$set: {
|
|
2661
3155
|
status: 'investigating',
|
|
2662
3156
|
auto_fix_status: 'failed',
|
|
2663
|
-
verification_notes: "Auto optimize enqueue failed: ".concat((
|
|
3157
|
+
verification_notes: "Auto optimize enqueue failed: ".concat((error_13 === null || error_13 === void 0 ? void 0 : error_13.message) || 'unknown error'),
|
|
2664
3158
|
last_triaged_by: 'auto-slow-query',
|
|
2665
3159
|
last_triaged_at: new Date()
|
|
2666
3160
|
}
|
|
2667
3161
|
})];
|
|
2668
|
-
case
|
|
3162
|
+
case 30:
|
|
2669
3163
|
_a.sent();
|
|
2670
3164
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize wait failed')];
|
|
2671
|
-
case
|
|
3165
|
+
case 31:
|
|
2672
3166
|
_a.sent();
|
|
2673
3167
|
return [2 /*return*/];
|
|
2674
|
-
case
|
|
3168
|
+
case 32:
|
|
2675
3169
|
jobId = String((job === null || job === void 0 ? void 0 : job._id) || '').trim();
|
|
2676
|
-
if (!!jobId) return [3 /*break*/,
|
|
3170
|
+
if (!!jobId) return [3 /*break*/, 34];
|
|
2677
3171
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2678
3172
|
$set: {
|
|
2679
3173
|
status: 'investigating',
|
|
@@ -2683,10 +3177,10 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2683
3177
|
last_triaged_at: new Date()
|
|
2684
3178
|
}
|
|
2685
3179
|
})];
|
|
2686
|
-
case
|
|
3180
|
+
case 33:
|
|
2687
3181
|
_a.sent();
|
|
2688
3182
|
return [2 /*return*/];
|
|
2689
|
-
case
|
|
3183
|
+
case 34:
|
|
2690
3184
|
attemptStartedAt = new Date();
|
|
2691
3185
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2692
3186
|
$inc: {
|
|
@@ -2709,71 +3203,71 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2709
3203
|
last_triaged_at: new Date()
|
|
2710
3204
|
}
|
|
2711
3205
|
})];
|
|
2712
|
-
case
|
|
3206
|
+
case 35:
|
|
2713
3207
|
_a.sent();
|
|
2714
3208
|
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
2715
|
-
case
|
|
3209
|
+
case 36:
|
|
2716
3210
|
queuedLog = (_a.sent()) || log;
|
|
2717
3211
|
return [4 /*yield*/, this.notifyCustomerSlowQueryStatus('detected_auto_optimize_enabled', queuedLog)];
|
|
2718
|
-
case 36:
|
|
2719
|
-
_a.sent();
|
|
2720
|
-
_a.label = 37;
|
|
2721
3212
|
case 37:
|
|
2722
|
-
_a.trys.push([37, 39, , 42]);
|
|
2723
|
-
return [4 /*yield*/, this.waitForDashboardJobStop(jobId, this.config.autoOptimizeWaitTimeoutMs)];
|
|
2724
|
-
case 38:
|
|
2725
3213
|
_a.sent();
|
|
2726
|
-
|
|
3214
|
+
_a.label = 38;
|
|
3215
|
+
case 38:
|
|
3216
|
+
_a.trys.push([38, 40, , 43]);
|
|
3217
|
+
return [4 /*yield*/, this.waitForDashboardJobStop(jobId, this.config.autoOptimizeWaitTimeoutMs)];
|
|
2727
3218
|
case 39:
|
|
2728
|
-
|
|
3219
|
+
_a.sent();
|
|
3220
|
+
return [3 /*break*/, 43];
|
|
3221
|
+
case 40:
|
|
3222
|
+
error_14 = _a.sent();
|
|
2729
3223
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2730
3224
|
$set: {
|
|
2731
3225
|
status: 'investigating',
|
|
2732
3226
|
auto_fix_status: 'failed',
|
|
2733
3227
|
auto_fix_result: {
|
|
2734
3228
|
job_id: jobId,
|
|
2735
|
-
error: (
|
|
3229
|
+
error: (error_14 === null || error_14 === void 0 ? void 0 : error_14.message) || 'timeout'
|
|
2736
3230
|
},
|
|
2737
|
-
verification_notes: "Auto optimize wait failed: ".concat((
|
|
3231
|
+
verification_notes: "Auto optimize wait failed: ".concat((error_14 === null || error_14 === void 0 ? void 0 : error_14.message) || 'timeout'),
|
|
2738
3232
|
last_triaged_by: 'auto-slow-query',
|
|
2739
3233
|
last_triaged_at: new Date()
|
|
2740
3234
|
}
|
|
2741
3235
|
})];
|
|
2742
|
-
case
|
|
3236
|
+
case 41:
|
|
2743
3237
|
_a.sent();
|
|
2744
3238
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize job state check failed')];
|
|
2745
|
-
case
|
|
3239
|
+
case 42:
|
|
2746
3240
|
_a.sent();
|
|
2747
3241
|
return [2 /*return*/];
|
|
2748
|
-
case 42:
|
|
2749
|
-
isRunning = false;
|
|
2750
|
-
_a.label = 43;
|
|
2751
3242
|
case 43:
|
|
2752
|
-
|
|
2753
|
-
|
|
3243
|
+
isRunning = false;
|
|
3244
|
+
_a.label = 44;
|
|
2754
3245
|
case 44:
|
|
2755
|
-
|
|
2756
|
-
return [
|
|
3246
|
+
_a.trys.push([44, 46, , 48]);
|
|
3247
|
+
return [4 /*yield*/, this.isDashboardJobRunning(jobId)];
|
|
2757
3248
|
case 45:
|
|
2758
|
-
|
|
3249
|
+
isRunning = _a.sent();
|
|
3250
|
+
return [3 /*break*/, 48];
|
|
3251
|
+
case 46:
|
|
3252
|
+
error_15 = _a.sent();
|
|
2759
3253
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2760
3254
|
$set: {
|
|
2761
3255
|
status: 'investigating',
|
|
2762
3256
|
auto_fix_status: 'failed',
|
|
2763
3257
|
auto_fix_result: {
|
|
2764
3258
|
job_id: jobId,
|
|
2765
|
-
error: (
|
|
3259
|
+
error: (error_15 === null || error_15 === void 0 ? void 0 : error_15.message) || 'unknown'
|
|
2766
3260
|
},
|
|
2767
|
-
verification_notes: "Unable to confirm dashboard job state: ".concat((
|
|
3261
|
+
verification_notes: "Unable to confirm dashboard job state: ".concat((error_15 === null || error_15 === void 0 ? void 0 : error_15.message) || 'unknown error'),
|
|
2768
3262
|
last_triaged_by: 'auto-slow-query',
|
|
2769
3263
|
last_triaged_at: new Date()
|
|
2770
3264
|
}
|
|
2771
3265
|
})];
|
|
2772
|
-
case
|
|
3266
|
+
case 47:
|
|
2773
3267
|
_a.sent();
|
|
2774
3268
|
return [2 /*return*/];
|
|
2775
|
-
case
|
|
2776
|
-
if (!isRunning) return [3 /*break*/,
|
|
3269
|
+
case 48:
|
|
3270
|
+
if (!isRunning) return [3 /*break*/, 51];
|
|
2777
3271
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2778
3272
|
$set: {
|
|
2779
3273
|
status: 'investigating',
|
|
@@ -2787,16 +3281,16 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2787
3281
|
last_triaged_at: new Date()
|
|
2788
3282
|
}
|
|
2789
3283
|
})];
|
|
2790
|
-
case
|
|
3284
|
+
case 49:
|
|
2791
3285
|
_a.sent();
|
|
2792
3286
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize timed out')];
|
|
2793
|
-
case
|
|
3287
|
+
case 50:
|
|
2794
3288
|
_a.sent();
|
|
2795
3289
|
return [2 /*return*/];
|
|
2796
|
-
case
|
|
2797
|
-
case
|
|
3290
|
+
case 51: return [4 /*yield*/, AIDashboardJobs.findOne({ _id: jobId })];
|
|
3291
|
+
case 52:
|
|
2798
3292
|
finalJob = _a.sent();
|
|
2799
|
-
if (!(!finalJob || finalJob.phase !== 'COMPLETE' || finalJob.paused)) return [3 /*break*/,
|
|
3293
|
+
if (!(!finalJob || finalJob.phase !== 'COMPLETE' || finalJob.paused)) return [3 /*break*/, 55];
|
|
2800
3294
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2801
3295
|
$set: {
|
|
2802
3296
|
status: 'investigating',
|
|
@@ -2811,46 +3305,47 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2811
3305
|
last_triaged_at: new Date()
|
|
2812
3306
|
}
|
|
2813
3307
|
})];
|
|
2814
|
-
case
|
|
3308
|
+
case 53:
|
|
2815
3309
|
_a.sent();
|
|
2816
3310
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize job did not complete')];
|
|
2817
|
-
case
|
|
3311
|
+
case 54:
|
|
2818
3312
|
_a.sent();
|
|
2819
3313
|
return [2 /*return*/];
|
|
2820
|
-
case
|
|
3314
|
+
case 55:
|
|
2821
3315
|
publishOutcome = this.evaluateDashboardPublishOutcome(finalJob);
|
|
2822
|
-
if (!!publishOutcome.success) return [3 /*break*/,
|
|
3316
|
+
if (!!publishOutcome.success) return [3 /*break*/, 58];
|
|
2823
3317
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2824
3318
|
$set: {
|
|
2825
3319
|
status: 'investigating',
|
|
2826
3320
|
auto_fix_status: 'failed',
|
|
2827
3321
|
auto_fix_result: {
|
|
2828
3322
|
job_id: jobId,
|
|
2829
|
-
publish_message: publishOutcome.message
|
|
3323
|
+
publish_message: publishOutcome.message,
|
|
3324
|
+
publish_branch: publishOutcome.branchName || ''
|
|
2830
3325
|
},
|
|
2831
3326
|
verification_notes: "Auto optimize publish/deploy failed: ".concat(publishOutcome.message),
|
|
2832
3327
|
last_triaged_by: 'auto-slow-query',
|
|
2833
3328
|
last_triaged_at: new Date()
|
|
2834
3329
|
}
|
|
2835
3330
|
})];
|
|
2836
|
-
case
|
|
3331
|
+
case 56:
|
|
2837
3332
|
_a.sent();
|
|
2838
3333
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize publish/deploy failed')];
|
|
2839
|
-
case
|
|
3334
|
+
case 57:
|
|
2840
3335
|
_a.sent();
|
|
2841
3336
|
return [2 /*return*/];
|
|
2842
|
-
case
|
|
2843
|
-
case 58:
|
|
2844
|
-
refreshedLog = (_a.sent()) || log;
|
|
2845
|
-
_a.label = 59;
|
|
3337
|
+
case 58: return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
2846
3338
|
case 59:
|
|
2847
|
-
_a.
|
|
2848
|
-
|
|
3339
|
+
refreshedLog = (_a.sent()) || log;
|
|
3340
|
+
_a.label = 60;
|
|
2849
3341
|
case 60:
|
|
2850
|
-
|
|
2851
|
-
return [
|
|
3342
|
+
_a.trys.push([60, 62, , 65]);
|
|
3343
|
+
return [4 /*yield*/, this.runExplain(refreshedLog)];
|
|
2852
3344
|
case 61:
|
|
2853
|
-
|
|
3345
|
+
afterExplain = _a.sent();
|
|
3346
|
+
return [3 /*break*/, 65];
|
|
3347
|
+
case 62:
|
|
3348
|
+
error_16 = _a.sent();
|
|
2854
3349
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2855
3350
|
$set: {
|
|
2856
3351
|
status: 'investigating',
|
|
@@ -2858,38 +3353,39 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2858
3353
|
auto_fix_result: {
|
|
2859
3354
|
job_id: jobId,
|
|
2860
3355
|
publish_message: publishOutcome.message,
|
|
2861
|
-
|
|
3356
|
+
publish_branch: publishOutcome.branchName || '',
|
|
3357
|
+
validation_error: (error_16 === null || error_16 === void 0 ? void 0 : error_16.message) || 'unknown'
|
|
2862
3358
|
},
|
|
2863
|
-
verification_notes: "Post-deploy validation failed: ".concat((
|
|
3359
|
+
verification_notes: "Post-deploy validation failed: ".concat((error_16 === null || error_16 === void 0 ? void 0 : error_16.message) || 'unknown error'),
|
|
2864
3360
|
last_triaged_by: 'auto-slow-query',
|
|
2865
3361
|
last_triaged_at: new Date()
|
|
2866
3362
|
}
|
|
2867
3363
|
})];
|
|
2868
|
-
case
|
|
3364
|
+
case 63:
|
|
2869
3365
|
_a.sent();
|
|
2870
3366
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize post-deploy validation failed')];
|
|
2871
|
-
case
|
|
3367
|
+
case 64:
|
|
2872
3368
|
_a.sent();
|
|
2873
3369
|
return [2 /*return*/];
|
|
2874
|
-
case
|
|
3370
|
+
case 65:
|
|
2875
3371
|
afterMetrics = this.resolveExecutionMetrics(afterExplain.explainStats || {}, afterExplain.durationMs, afterExplain.stageSummaries || []);
|
|
2876
|
-
if (!this.config.autoOptimizeOutputCompareEnabled) return [3 /*break*/,
|
|
2877
|
-
if (!!baselineOutputFingerprint) return [3 /*break*/,
|
|
3372
|
+
if (!this.config.autoOptimizeOutputCompareEnabled) return [3 /*break*/, 71];
|
|
3373
|
+
if (!!baselineOutputFingerprint) return [3 /*break*/, 66];
|
|
2878
3374
|
outputEquivalence = {
|
|
2879
3375
|
passed: false,
|
|
2880
3376
|
reason: 'Baseline output fingerprint missing.',
|
|
2881
3377
|
mode: 'unknown'
|
|
2882
3378
|
};
|
|
2883
|
-
return [3 /*break*/,
|
|
2884
|
-
case 65:
|
|
2885
|
-
_a.trys.push([65, 67, , 70]);
|
|
2886
|
-
return [4 /*yield*/, this.captureOutputFingerprint(refreshedLog)];
|
|
3379
|
+
return [3 /*break*/, 71];
|
|
2887
3380
|
case 66:
|
|
3381
|
+
_a.trys.push([66, 68, , 71]);
|
|
3382
|
+
return [4 /*yield*/, this.captureOutputFingerprint(refreshedLog)];
|
|
3383
|
+
case 67:
|
|
2888
3384
|
afterOutputFingerprint = _a.sent();
|
|
2889
3385
|
outputEquivalence = this.compareOutputEquivalence(baselineOutputFingerprint, afterOutputFingerprint);
|
|
2890
|
-
return [3 /*break*/,
|
|
2891
|
-
case
|
|
2892
|
-
|
|
3386
|
+
return [3 /*break*/, 71];
|
|
3387
|
+
case 68:
|
|
3388
|
+
error_17 = _a.sent();
|
|
2893
3389
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2894
3390
|
$set: {
|
|
2895
3391
|
status: 'investigating',
|
|
@@ -2897,11 +3393,12 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2897
3393
|
auto_fix_result: {
|
|
2898
3394
|
job_id: jobId,
|
|
2899
3395
|
publish_message: publishOutcome.message,
|
|
3396
|
+
publish_branch: publishOutcome.branchName || '',
|
|
2900
3397
|
baseline: baselineMetrics,
|
|
2901
3398
|
after: afterMetrics,
|
|
2902
|
-
output_equivalence_error: (
|
|
3399
|
+
output_equivalence_error: (error_17 === null || error_17 === void 0 ? void 0 : error_17.message) || 'unknown'
|
|
2903
3400
|
},
|
|
2904
|
-
verification_notes: "Post-deploy output comparison failed: ".concat((
|
|
3401
|
+
verification_notes: "Post-deploy output comparison failed: ".concat((error_17 === null || error_17 === void 0 ? void 0 : error_17.message) || 'unknown error'),
|
|
2905
3402
|
explain_plan: afterExplain.explainPlan,
|
|
2906
3403
|
explain_execution_stats: afterExplain.explainStats,
|
|
2907
3404
|
explain_generated_at: new Date(),
|
|
@@ -2915,23 +3412,24 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2915
3412
|
}
|
|
2916
3413
|
}
|
|
2917
3414
|
})];
|
|
2918
|
-
case
|
|
3415
|
+
case 69:
|
|
2919
3416
|
_a.sent();
|
|
2920
3417
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize output comparison failed')];
|
|
2921
|
-
case
|
|
3418
|
+
case 70:
|
|
2922
3419
|
_a.sent();
|
|
2923
3420
|
return [2 /*return*/];
|
|
2924
|
-
case
|
|
3421
|
+
case 71:
|
|
2925
3422
|
validation = this.evaluateOptimizationOutcome(baselineMetrics, afterMetrics, outputEquivalence);
|
|
2926
3423
|
autoFixResult = {
|
|
2927
3424
|
job_id: jobId,
|
|
2928
3425
|
publish_message: publishOutcome.message,
|
|
3426
|
+
publish_branch: publishOutcome.branchName || '',
|
|
2929
3427
|
baseline: baselineMetrics,
|
|
2930
3428
|
after: afterMetrics,
|
|
2931
3429
|
output_equivalence: outputEquivalence,
|
|
2932
3430
|
validation: validation
|
|
2933
3431
|
};
|
|
2934
|
-
if (!!validation.passed) return [3 /*break*/,
|
|
3432
|
+
if (!!validation.passed) return [3 /*break*/, 74];
|
|
2935
3433
|
return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2936
3434
|
$set: {
|
|
2937
3435
|
status: 'investigating',
|
|
@@ -2951,13 +3449,13 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2951
3449
|
}
|
|
2952
3450
|
}
|
|
2953
3451
|
})];
|
|
2954
|
-
case
|
|
3452
|
+
case 72:
|
|
2955
3453
|
_a.sent();
|
|
2956
3454
|
return [4 /*yield*/, this.maybeStopAutoOptimizeAfterFailure(logId, 'Auto optimize validation failed')];
|
|
2957
|
-
case
|
|
3455
|
+
case 73:
|
|
2958
3456
|
_a.sent();
|
|
2959
3457
|
return [2 /*return*/];
|
|
2960
|
-
case
|
|
3458
|
+
case 74: return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: logId }, {
|
|
2961
3459
|
$set: {
|
|
2962
3460
|
status: 'optimized',
|
|
2963
3461
|
auto_fix_status: 'completed',
|
|
@@ -2976,13 +3474,13 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
2976
3474
|
}
|
|
2977
3475
|
}
|
|
2978
3476
|
})];
|
|
2979
|
-
case
|
|
3477
|
+
case 75:
|
|
2980
3478
|
_a.sent();
|
|
2981
3479
|
return [4 /*yield*/, SlowQueryLogs.findOne({ _id: logId })];
|
|
2982
|
-
case
|
|
3480
|
+
case 76:
|
|
2983
3481
|
optimizedLog = (_a.sent()) || log;
|
|
2984
3482
|
return [4 /*yield*/, this.notifyCustomerSlowQueryStatus('completed_success', optimizedLog, { notes: validation.reason })];
|
|
2985
|
-
case
|
|
3483
|
+
case 77:
|
|
2986
3484
|
_a.sent();
|
|
2987
3485
|
return [2 /*return*/];
|
|
2988
3486
|
}
|
|
@@ -3351,6 +3849,7 @@ var SlowQueryVerifier = /** @class */ (function () {
|
|
|
3351
3849
|
});
|
|
3352
3850
|
return result;
|
|
3353
3851
|
};
|
|
3852
|
+
SlowQueryVerifier.APP_SETTINGS_CACHE_TTL_MS = 10000;
|
|
3354
3853
|
return SlowQueryVerifier;
|
|
3355
3854
|
}());
|
|
3356
3855
|
exports.SlowQueryVerifier = SlowQueryVerifier;
|