bulltrackers-module 1.0.137 → 1.0.138
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.
|
@@ -26,11 +26,52 @@ async function runComputationPass(config, dependencies, computationManifest) {
|
|
|
26
26
|
const yesterday = new Date(); yesterday.setUTCDate(yesterday.getUTCDate()-1);
|
|
27
27
|
const endDateUTC = new Date(Date.UTC(yesterday.getUTCFullYear(), yesterday.getUTCMonth(), yesterday.getUTCDate()));
|
|
28
28
|
const earliestDates = await getEarliestDataDates(config, dependencies);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
29
|
+
|
|
30
|
+
// --- REMOVE OLD/REPLACE WITH NEW LOGIC FOR PROBLEM 3 & 4 ---
|
|
31
|
+
// const firstDate = earliestDates.absoluteEarliest; // <-- REMOVE
|
|
32
|
+
// const startDateUTC = firstDate ? new Date(Date.UTC(firstDate.getUTCFullYear(), firstDate.getUTCMonth(), firstDate.getUTCDate())) : new Date(config.earliestComputationDate+'T00:00:00Z'); // <-- REMOVE
|
|
33
|
+
|
|
32
34
|
const passes = groupByPass(computationManifest);
|
|
33
35
|
const calcsInThisPass = passes[passToRun] || []; if (!calcsInThisPass.length) return logger.log('WARN', `[PassRunner] No calcs for Pass ${passToRun}. Exiting.`);
|
|
36
|
+
|
|
37
|
+
// --- START: NEW LOGIC FOR PROBLEM 3 & 4 ---
|
|
38
|
+
// Determine the earliest start date based *only* on data required for THIS pass.
|
|
39
|
+
const requiredRootData = new Set();
|
|
40
|
+
calcsInThisPass.forEach(c => {
|
|
41
|
+
(c.rootDataDependencies || []).forEach(dep => requiredRootData.add(dep));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
let earliestStartDateForPass = null;
|
|
45
|
+
if (requiredRootData.size > 0) {
|
|
46
|
+
// Find the LATEST of the earliest dates for all required data types.
|
|
47
|
+
// e.g., If portfolio starts 09-25 and social starts 10-30, a calc
|
|
48
|
+
// needing both must start on 10-30.
|
|
49
|
+
let latestOfEarliestDates = new Date(0); // Start at epoch
|
|
50
|
+
requiredRootData.forEach(dep => {
|
|
51
|
+
const earliestDateForDep = earliestDates[dep]; // e.g., earliestDates.portfolio
|
|
52
|
+
if (earliestDateForDep && earliestDateForDep > latestOfEarliestDates) {
|
|
53
|
+
latestOfEarliestDates = earliestDateForDep;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (latestOfEarliestDates.getTime() > 0) {
|
|
58
|
+
earliestStartDateForPass = latestOfEarliestDates;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Use the pass-specific date. Fall back to absolute earliest, then config.
|
|
63
|
+
const firstDate = earliestStartDateForPass || earliestDates.absoluteEarliest;
|
|
64
|
+
const startDateUTC = firstDate
|
|
65
|
+
? new Date(Date.UTC(firstDate.getUTCFullYear(), firstDate.getUTCMonth(), firstDate.getUTCDate()))
|
|
66
|
+
: new Date(config.earliestComputationDate+'T00:00:00Z');
|
|
67
|
+
|
|
68
|
+
logger.log('INFO', `[PassRunner] Pass ${passToRun} requires data: [${Array.from(requiredRootData).join(', ')}].`);
|
|
69
|
+
logger.log('INFO', `[PassRunner] Determined start date for this pass: ${startDateUTC.toISOString().slice(0, 10)}`);
|
|
70
|
+
// --- END: NEW LOGIC ---
|
|
71
|
+
|
|
72
|
+
const allExpectedDates = getExpectedDateStrings(startDateUTC, endDateUTC);
|
|
73
|
+
const firstDayOfBackfill = allExpectedDates.length > 0 ? allExpectedDates[0] : null; // --- MOVED FROM ABOVE ---
|
|
74
|
+
|
|
34
75
|
const standardCalcs = calcsInThisPass.filter(c => c.type==='standard');
|
|
35
76
|
const metaCalcs = calcsInThisPass.filter(c => c.type==='meta');
|
|
36
77
|
const processDate = async (dateStr) => {
|
|
@@ -39,7 +80,7 @@ async function runComputationPass(config, dependencies, computationManifest) {
|
|
|
39
80
|
const rootData = await checkRootDataAvailability(dateStr, config, dependencies, earliestDates);
|
|
40
81
|
if (!rootData) { logger.log('WARN', `[PassRunner] Skipping ${dateStr} for Pass ${passToRun}: No root data.`);return;}
|
|
41
82
|
const existingResults = await fetchExistingResults(dateStr, calcsInThisPass, computationManifest, config, dependencies);
|
|
42
|
-
const { standardCalcsToRun, metaCalcsToRun } = filterCalculations(standardCalcs, metaCalcs, rootData.status, existingResults, passToRun, dateStr, logger);
|
|
83
|
+
const { standardCalcsToRun, metaCalcsToRun } = filterCalculations(standardCalcs, metaCalcs, rootData.status, existingResults, passToRun, dateStr, logger,dateStr === firstDayOfBackfill );
|
|
43
84
|
if (standardCalcsToRun.length === 0 && metaCalcsToRun.length === 0) {logger.log('INFO', `[PassRunner] All calcs for ${dateStr} Pass ${passToRun} are already complete. Skipping.`);return;}
|
|
44
85
|
if (standardCalcsToRun.length) await runStandardComputationPass(dateToProcess, standardCalcsToRun, `Pass ${passToRun} (Standard)`, config, dependencies, rootData);
|
|
45
86
|
if (metaCalcsToRun.length) await runMetaComputationPass(dateToProcess, metaCalcsToRun, `Pass ${passToRun} (Meta)`, config, dependencies, existingResults, rootData);
|
|
@@ -72,20 +72,26 @@ async function fetchExistingResults(dateStr, calcsInPass, fullManifest, config,
|
|
|
72
72
|
|
|
73
73
|
/** --- MODIFIED: Stage 5: Filter calculations to skip completed work ---
|
|
74
74
|
*/
|
|
75
|
-
function filterCalculations(standardCalcs, metaCalcs, rootDataStatus, existingResults, passToRun, dateStr, logger) {
|
|
75
|
+
function filterCalculations(standardCalcs, metaCalcs, rootDataStatus, existingResults, passToRun, dateStr, logger, isFirstDayOfBackfill = false) {
|
|
76
76
|
const skipped = new Set();
|
|
77
|
-
// Filter Standard Calcs
|
|
78
77
|
const standardCalcsToRun = standardCalcs.filter(c => {
|
|
79
78
|
if (existingResults[c.name]) {logger.log('TRACE', `[Pass ${passToRun}] Skipping ${c.name} for ${dateStr}. Result already exists.`);return false;}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
if (isFirstDayOfBackfill && c.isHistorical) {
|
|
80
|
+
logger.log('INFO', `[Pass ${passToRun}] Skipping ${c.name} for ${dateStr}. Historical calc on the first day of backfill (no yesterday).`);
|
|
81
|
+
skipped.add(c.name);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
85
84
|
});
|
|
86
85
|
// Filter Meta Calcs
|
|
87
86
|
const metaCalcsToRun = metaCalcs.filter(c => {
|
|
88
87
|
if (existingResults[c.name]) {logger.log('TRACE', `[Pass ${passToRun} Meta] Skipping ${c.name} for ${dateStr}. Result already exists.`);skipped.add(c.name);return false;}
|
|
88
|
+
// --- START: RECOMMENDED ADDITION ---
|
|
89
|
+
if (isFirstDayOfBackfill && c.isHistorical) {
|
|
90
|
+
logger.log('INFO', `[Pass ${passToRun} Meta] Skipping ${c.name} for ${dateStr}. Historical calc on the first day of backfill (no yesterday).`);
|
|
91
|
+
skipped.add(c.name);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
// --- END: RECOMMENDED ADDITION ---
|
|
89
95
|
// 1. Check root data
|
|
90
96
|
const { canRun, missing: missingRoot } = checkRootDependencies(c, rootDataStatus);
|
|
91
97
|
if (!canRun) {logger.log('INFO', `[Pass ${passToRun} Meta] Skipping ${c.name} for ${dateStr}. Missing root data: [${missingRoot.join(', ')}]`);skipped.add(c.name);return false;}
|