bulltrackers-module 1.0.137 → 1.0.139

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.
@@ -25,12 +25,81 @@ async function runComputationPass(config, dependencies, computationManifest) {
25
25
  logger.log('INFO', `🚀 Starting PASS ${passToRun}...`);
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
- const earliestDates = await getEarliestDataDates(config, dependencies);
29
- const firstDate = earliestDates.absoluteEarliest;
30
- const startDateUTC = firstDate ? new Date(Date.UTC(firstDate.getUTCFullYear(), firstDate.getUTCMonth(), firstDate.getUTCDate())) : new Date(config.earliestComputationDate+'T00:00:00Z');
31
- const allExpectedDates = getExpectedDateStrings(startDateUTC, endDateUTC);
28
+
29
+ // const earliestDates = await getEarliestDataDates(config, dependencies); // <-- 1. COMMENT OUT OR REMOVE THIS BROKEN CALL
30
+
31
+ // --- START: 2. NEW HARDCODED DATES (V2 - CORRECTED) ---
32
+ logger.log('INFO', 'Using hardcoded earliest data dates to bypass faulty discovery.');
33
+
34
+ // Use the exact dates you provided:
35
+ const earliestPortfolio = new Date('2025-09-25T00:00:00Z'); // Earliest of Normal (09-25) and Spec (09-29)
36
+ const earliestHistory = new Date('2025-11-05T00:00:00Z'); // Both Normal and Spec history
37
+ const earliestSocial = new Date('2025-10-30T00:00:00Z'); // daily_social_insights
38
+ const earliestInsights = new Date('2025-08-26T00:00:00Z'); // daily_instrument_insights (Your new date)
39
+
40
+ const earliestDates = {
41
+ portfolio: earliestPortfolio,
42
+ history: earliestHistory,
43
+ social: earliestSocial,
44
+ insights: earliestInsights, // <-- Use the real date
45
+ // Calculate absoluteEarliest based on all real data
46
+ absoluteEarliest: [earliestPortfolio, earliestHistory, earliestSocial, earliestInsights].reduce((a, b) => a < b ? a : b)
47
+ };
48
+
49
+ logger.log('INFO', `Hardcoded map: portfolio=${earliestDates.portfolio.toISOString().slice(0,10)}, history=${earliestDates.history.toISOString().slice(0,10)}, social=${earliestDates.social.toISOString().slice(0,10)}, insights=${earliestDates.insights.toISOString().slice(0,10)}`);
50
+ // --- END: NEW HARDCODED DATES ---
51
+
52
+
32
53
  const passes = groupByPass(computationManifest);
33
54
  const calcsInThisPass = passes[passToRun] || []; if (!calcsInThisPass.length) return logger.log('WARN', `[PassRunner] No calcs for Pass ${passToRun}. Exiting.`);
55
+
56
+ // --- 3. THIS LOGIC BLOCK (from our last fix) IS NOW CORRECT ---
57
+ // It will consume the clean, hardcoded 'earliestDates' map and work as intended.
58
+ const requiredRootData = new Set();
59
+ calcsInThisPass.forEach(c => {
60
+ (c.rootDataDependencies || []).forEach(dep => requiredRootData.add(dep));
61
+ });
62
+
63
+ let earliestStartDateForPass = null;
64
+ if (requiredRootData.size > 0) {
65
+ let latestOfEarliestDates = new Date(0); // Start at epoch
66
+ const farFutureSentinelYear = 2999; // Keep as a safety check for any future issues
67
+ let hasAtLeastOneValidDate = false;
68
+
69
+ requiredRootData.forEach(dep => {
70
+ const earliestDateForDep = earliestDates[dep];
71
+
72
+ // This check is now just a safeguard
73
+ if (earliestDateForDep && earliestDateForDep.getUTCFullYear() < farFutureSentinelYear) {
74
+ if (earliestDateForDep > latestOfEarliestDates) {
75
+ latestOfEarliestDates = earliestDateForDep;
76
+ }
77
+ hasAtLeastOneValidDate = true;
78
+ } else if (earliestDateForDep) {
79
+ logger.log('INFO', `[PassRunner] Dependency '${dep}' is not available (date: ${earliestDateForDep.toISOString().slice(0, 10)}). Calcs requiring it will be skipped.`);
80
+ } else {
81
+ logger.log('WARN', `[PassRunner] Dependency '${dep}' has no earliest date defined in hardcoded map.`);
82
+ }
83
+ });
84
+
85
+ if (hasAtLeastOneValidDate) {
86
+ earliestStartDateForPass = latestOfEarliestDates;
87
+ }
88
+ }
89
+
90
+ // Use the pass-specific date. Fall back to absolute earliest, then config.
91
+ const firstDate = earliestStartDateForPass || earliestDates.absoluteEarliest;
92
+ const startDateUTC = firstDate
93
+ ? new Date(Date.UTC(firstDate.getUTCFullYear(), firstDate.getUTCMonth(), firstDate.getUTCDate()))
94
+ : new Date(config.earliestComputationDate+'T00:00:00Z');
95
+
96
+ logger.log('INFO', `[PassRunner] Pass ${passToRun} requires data: [${Array.from(requiredRootData).join(', ')}].`);
97
+ logger.log('INFO', `[PassRunner] Determined start date for this pass: ${startDateUTC.toISOString().slice(0, 10)}`);
98
+ // --- END OF LOGIC BLOCK ---
99
+
100
+ const allExpectedDates = getExpectedDateStrings(startDateUTC, endDateUTC);
101
+ const firstDayOfBackfill = allExpectedDates.length > 0 ? allExpectedDates[0] : null; // --- MOVED FROM ABOVE ---
102
+
34
103
  const standardCalcs = calcsInThisPass.filter(c => c.type==='standard');
35
104
  const metaCalcs = calcsInThisPass.filter(c => c.type==='meta');
36
105
  const processDate = async (dateStr) => {
@@ -39,7 +108,7 @@ async function runComputationPass(config, dependencies, computationManifest) {
39
108
  const rootData = await checkRootDataAvailability(dateStr, config, dependencies, earliestDates);
40
109
  if (!rootData) { logger.log('WARN', `[PassRunner] Skipping ${dateStr} for Pass ${passToRun}: No root data.`);return;}
41
110
  const existingResults = await fetchExistingResults(dateStr, calcsInThisPass, computationManifest, config, dependencies);
42
- const { standardCalcsToRun, metaCalcsToRun } = filterCalculations(standardCalcs, metaCalcs, rootData.status, existingResults, passToRun, dateStr, logger);
111
+ const { standardCalcsToRun, metaCalcsToRun } = filterCalculations(standardCalcs, metaCalcs, rootData.status, existingResults, passToRun, dateStr, logger,dateStr === firstDayOfBackfill );
43
112
  if (standardCalcsToRun.length === 0 && metaCalcsToRun.length === 0) {logger.log('INFO', `[PassRunner] All calcs for ${dateStr} Pass ${passToRun} are already complete. Skipping.`);return;}
44
113
  if (standardCalcsToRun.length) await runStandardComputationPass(dateToProcess, standardCalcsToRun, `Pass ${passToRun} (Standard)`, config, dependencies, rootData);
45
114
  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
- const { canRun, missing } = checkRootDependencies(c, rootDataStatus);
81
- if (canRun) return true;
82
- logger.log('INFO', `[Pass ${passToRun}] Skipping ${c.name} for ${dateStr}. Missing root data: [${missing.join(', ')}]`);
83
- skipped.add(c.name);
84
- return false;
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;}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.137",
3
+ "version": "1.0.139",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [