bulltrackers-module 1.0.652 → 1.0.654
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.
|
@@ -230,23 +230,92 @@ async function handleForceRun(config, dependencies, computationManifest, reqBody
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// 2. Determine Target Dates
|
|
233
|
-
let
|
|
233
|
+
let candidateDates = [];
|
|
234
234
|
if (dateInput) {
|
|
235
235
|
// Single Date Mode
|
|
236
|
-
|
|
236
|
+
candidateDates = [dateInput];
|
|
237
237
|
} else {
|
|
238
238
|
// All Dates Mode (Backfill)
|
|
239
239
|
logger.log('INFO', `[ForceRun] No date provided. Calculating date range for ${computationName}...`);
|
|
240
240
|
const earliestDates = await getEarliestDataDates(config, dependencies);
|
|
241
241
|
// Calculate from system start until today
|
|
242
|
-
|
|
242
|
+
candidateDates = getExpectedDateStrings(earliestDates.absoluteEarliest, new Date());
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
logger.log('
|
|
245
|
+
logger.log('INFO', `[ForceRun] Checking ${candidateDates.length} candidate dates for runnability...`);
|
|
246
246
|
|
|
247
|
-
// 3.
|
|
247
|
+
// 3. Filter to only runnable dates using analyzeDateExecution
|
|
248
|
+
const manifestMap = new Map(computationManifest.map(c => [normalizeName(c.name), c]));
|
|
249
|
+
const calcsInPass = groupByPass(computationManifest, manifestItem.pass || "1");
|
|
250
|
+
const targetComputationNormalized = normalizeName(computationName);
|
|
251
|
+
|
|
252
|
+
// Filter to only the target computation
|
|
253
|
+
const targetCalcs = calcsInPass.filter(c => normalizeName(c.name) === targetComputationNormalized);
|
|
254
|
+
|
|
255
|
+
if (targetCalcs.length === 0) {
|
|
256
|
+
throw new Error(`Computation '${computationName}' not found in pass ${manifestItem.pass || "1"}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const runnableDates = [];
|
|
260
|
+
const skippedDates = [];
|
|
261
|
+
|
|
262
|
+
for (const dateStr of candidateDates) {
|
|
263
|
+
// Check root data availability
|
|
264
|
+
const rootDataStatus = await checkRootDataAvailability(dateStr, config, dependencies, DEFINITIVE_EARLIEST_DATES);
|
|
265
|
+
|
|
266
|
+
// Get computation status for this date
|
|
267
|
+
const dailyStatus = await fetchComputationStatus(dateStr, config, dependencies);
|
|
268
|
+
|
|
269
|
+
// Check previous day status if needed
|
|
270
|
+
let prevDailyStatus = null;
|
|
271
|
+
if (targetCalcs.some(c => c.isHistorical)) {
|
|
272
|
+
const prevDate = new Date(dateStr + 'T00:00:00Z');
|
|
273
|
+
prevDate.setUTCDate(prevDate.getUTCDate() - 1);
|
|
274
|
+
prevDailyStatus = await fetchComputationStatus(prevDate.toISOString().slice(0, 10), config, dependencies);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Analyze if this computation can run on this date
|
|
278
|
+
const report = analyzeDateExecution(dateStr, targetCalcs, rootDataStatus, dailyStatus, manifestMap, prevDailyStatus);
|
|
279
|
+
|
|
280
|
+
// Check if the target computation is runnable, needs re-run, or has failed dependencies
|
|
281
|
+
const isRunnable = report.runnable.some(t => normalizeName(t.name) === targetComputationNormalized);
|
|
282
|
+
const needsReRun = report.reRuns.some(t => normalizeName(t.name) === targetComputationNormalized);
|
|
283
|
+
const hasFailedDep = report.failedDependency.some(t => normalizeName(t.name) === targetComputationNormalized);
|
|
284
|
+
const isImpossible = report.impossible.some(t => normalizeName(t.name) === targetComputationNormalized);
|
|
285
|
+
const isBlocked = report.blocked.some(t => normalizeName(t.name) === targetComputationNormalized);
|
|
286
|
+
|
|
287
|
+
if (isRunnable || needsReRun || hasFailedDep) {
|
|
288
|
+
runnableDates.push(dateStr);
|
|
289
|
+
} else if (isImpossible) {
|
|
290
|
+
skippedDates.push({ date: dateStr, reason: report.impossible.find(t => normalizeName(t.name) === targetComputationNormalized)?.reason || 'Impossible' });
|
|
291
|
+
} else if (isBlocked) {
|
|
292
|
+
skippedDates.push({ date: dateStr, reason: report.blocked.find(t => normalizeName(t.name) === targetComputationNormalized)?.reason || 'Blocked' });
|
|
293
|
+
} else {
|
|
294
|
+
skippedDates.push({ date: dateStr, reason: 'Not runnable (unknown reason)' });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
logger.log('INFO', `[ForceRun] ✅ Found ${runnableDates.length} runnable dates out of ${candidateDates.length} candidates`);
|
|
299
|
+
if (skippedDates.length > 0) {
|
|
300
|
+
logger.log('INFO', `[ForceRun] ⏭️ Skipped ${skippedDates.length} dates: ${skippedDates.slice(0, 5).map(s => `${s.date} (${s.reason})`).join(', ')}${skippedDates.length > 5 ? '...' : ''}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (runnableDates.length === 0) {
|
|
304
|
+
return {
|
|
305
|
+
status: 'NO_RUNNABLE_DATES',
|
|
306
|
+
computation: computationName,
|
|
307
|
+
mode: dateInput ? 'SINGLE_DATE' : 'ALL_DATES',
|
|
308
|
+
datesChecked: candidateDates.length,
|
|
309
|
+
datesRunnable: 0,
|
|
310
|
+
skippedReasons: skippedDates.slice(0, 10)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
logger.log('WARN', `[ForceRun] 🚨 MANUALLY Triggering ${computationName} for ${runnableDates.length} runnable dates. Pass: ${manifestItem.pass}`);
|
|
315
|
+
|
|
316
|
+
// 4. Construct Tasks (only for runnable dates)
|
|
248
317
|
const dispatchId = crypto.randomUUID();
|
|
249
|
-
const tasks =
|
|
318
|
+
const tasks = runnableDates.map(date => {
|
|
250
319
|
const traceId = crypto.randomBytes(16).toString('hex');
|
|
251
320
|
const spanId = crypto.randomBytes(8).toString('hex');
|
|
252
321
|
return {
|
|
@@ -288,7 +357,10 @@ async function handleForceRun(config, dependencies, computationManifest, reqBody
|
|
|
288
357
|
status: 'FORCED',
|
|
289
358
|
computation: computationName,
|
|
290
359
|
mode: dateInput ? 'SINGLE_DATE' : 'ALL_DATES',
|
|
360
|
+
datesChecked: candidateDates.length,
|
|
361
|
+
datesRunnable: runnableDates.length,
|
|
291
362
|
datesTriggered: dispatchedCount,
|
|
363
|
+
skippedCount: skippedDates.length,
|
|
292
364
|
targetTopic: topic
|
|
293
365
|
};
|
|
294
366
|
}
|