bulltrackers-module 1.0.213 → 1.0.215

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.
@@ -33,24 +33,22 @@ async function runComputationPass(config, dependencies, computationManifest) {
33
33
  insights: new Date('2025-08-26T00:00:00Z'),
34
34
  price: new Date('2025-08-01T00:00:00Z')
35
35
  };
36
+
36
37
  earliestDates.absoluteEarliest = Object.values(earliestDates).reduce((a, b) => a < b ? a : b);
37
38
 
38
39
  const passes = groupByPass(computationManifest);
39
40
  const calcsInThisPass = passes[passToRun] || [];
40
41
 
41
- if (!calcsInThisPass.length)
42
- return logger.log('WARN', `[PassRunner] No calcs for Pass ${passToRun}. Exiting.`);
43
-
44
- const passEarliestDate = earliestDates.absoluteEarliest;
45
- const endDateUTC = new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate() - 1));
46
- const allExpectedDates = getExpectedDateStrings(passEarliestDate, endDateUTC);
42
+ if (!calcsInThisPass.length) return logger.log('WARN', `[PassRunner] No calcs for Pass ${passToRun}. Exiting.`);
47
43
 
48
- const priceBatchCalcs = calcsInThisPass.filter(c => c.type === 'meta' && c.rootDataDependencies?.includes('price'));
44
+ const passEarliestDate = earliestDates.absoluteEarliest;
45
+ const endDateUTC = new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate() - 1));
46
+ const allExpectedDates = getExpectedDateStrings(passEarliestDate, endDateUTC);
47
+ const priceBatchCalcs = calcsInThisPass.filter(c => c.type === 'meta' && c.rootDataDependencies?.includes('price'));
49
48
  const standardAndOtherMetaCalcs = calcsInThisPass.filter(c => !priceBatchCalcs.includes(c));
50
49
 
51
50
  if (priceBatchCalcs.length > 0) {
52
- try {
53
- await runBatchPriceComputation(config, dependencies, allExpectedDates, priceBatchCalcs);
51
+ try { await runBatchPriceComputation(config, dependencies, allExpectedDates, priceBatchCalcs);
54
52
  } catch (e) { logger.log('ERROR', 'Legacy Batch Price failed', e); }
55
53
  }
56
54
 
@@ -63,51 +61,26 @@ async function runComputationPass(config, dependencies, computationManifest) {
63
61
  }
64
62
 
65
63
  async function runDateComputation(dateStr, passToRun, calcsInThisPass, config, dependencies, computationManifest) {
66
- const { logger } = dependencies;
64
+ const { logger } = dependencies;
67
65
  const dateToProcess = new Date(dateStr + 'T00:00:00Z');
68
-
69
- const dailyStatus = await fetchComputationStatus(dateStr, config, dependencies);
70
-
71
- // Filter AND Log reason for skipping
66
+ const dailyStatus = await fetchComputationStatus(dateStr, config, dependencies);
72
67
  const calcsToAttempt = [];
73
-
74
68
  for (const calc of calcsInThisPass) {
75
- const cName = normalizeName(calc.name);
69
+ const cName = normalizeName(calc.name);
76
70
  const storedStatus = dailyStatus[cName];
77
- const currentHash = calc.hash;
71
+ const currentHash = calc.hash;
78
72
 
79
73
  // 1. Dependency Check
80
- if (calc.dependencies && calc.dependencies.length > 0) {
81
- const missing = calc.dependencies.filter(depName => !dailyStatus[normalizeName(depName)]);
82
- if (missing.length > 0) {
83
- // Too noisy to log every skip, but useful for debugging if needed.
84
- // Only logging if it's NOT a bulk skip.
85
- // logger.log('TRACE', `[Skip] ${cName} missing deps: ${missing.join(', ')}`);
86
- continue;
87
- }
88
- }
74
+ if (calc.dependencies && calc.dependencies.length > 0) { const missing = calc.dependencies.filter(depName => !dailyStatus[normalizeName(depName)]); if (missing.length > 0) { logger.log('TRACE', `[Skip] ${cName} missing deps: ${missing.join(', ')}`); continue; } }
89
75
 
90
76
  // 2. Logic A: No previous run
91
- if (!storedStatus) {
92
- logger.log('INFO', `[Versioning] ${cName}: New run needed (No prior status).`);
93
- calcsToAttempt.push(calc);
94
- continue;
95
- }
77
+ if (!storedStatus) { logger.log('INFO', `[Versioning] ${cName}: New run needed (No prior status).`); calcsToAttempt.push(calc); continue; }
96
78
 
97
79
  // 3. Logic B: Hash Mismatch
98
- // FIX: Ensure storedStatus is a string before calling substring
99
- if (typeof storedStatus === 'string' && currentHash && storedStatus !== currentHash) {
100
- logger.log('INFO', `[Versioning] ${cName}: Code Changed. (Old: ${storedStatus.substring(0,6)}... New: ${currentHash.substring(0,6)}...)`);
101
- calcsToAttempt.push(calc);
102
- continue;
103
- }
80
+ if (typeof storedStatus === 'string' && currentHash && storedStatus !== currentHash) { logger.log('INFO', `[Versioning] ${cName}: Code Changed. (Old: ${storedStatus.substring(0,6)}... New: ${currentHash.substring(0,6)}...)`); calcsToAttempt.push(calc); continue; }
104
81
 
105
82
  // 4. Logic C: Upgrade Legacy Boolean -> Hash
106
- if (storedStatus === true && currentHash) {
107
- logger.log('INFO', `[Versioning] ${cName}: Upgrading legacy status to Hash.`);
108
- calcsToAttempt.push(calc);
109
- continue;
110
- }
83
+ if (storedStatus === true && currentHash) { logger.log('INFO', `[Versioning] ${cName}: Upgrading legacy status to Hash.`); calcsToAttempt.push(calc); continue; }
111
84
  }
112
85
 
113
86
  if (!calcsToAttempt.length) return null;
@@ -121,47 +94,34 @@ async function runDateComputation(dateStr, passToRun, calcsInThisPass, config, d
121
94
  };
122
95
 
123
96
  const rootData = await checkRootDataAvailability(dateStr, config, dependencies, earliestDates);
124
- if (!rootData) {
125
- logger.log('INFO', `[DateRunner] Root data missing for ${dateStr}. Skipping.`);
126
- return null;
127
- }
128
-
97
+ if (!rootData) { logger.log('INFO', `[DateRunner] Root data missing for ${dateStr}. Skipping.`); return null; }
129
98
  const runnableCalcs = calcsToAttempt.filter(c => checkRootDependencies(c, rootData.status).canRun);
130
-
131
99
  if (!runnableCalcs.length) return null;
132
-
133
100
  const standardToRun = runnableCalcs.filter(c => c.type === 'standard');
134
101
  const metaToRun = runnableCalcs.filter(c => c.type === 'meta');
135
-
136
102
  logger.log('INFO', `[DateRunner] Running ${dateStr}: ${standardToRun.length} std, ${metaToRun.length} meta`);
137
-
138
103
  const dateUpdates = {};
139
104
 
140
105
  try {
141
106
  const calcsRunning = [...standardToRun, ...metaToRun];
142
-
143
107
  const existingResults = await fetchExistingResults(dateStr, calcsRunning, computationManifest, config, dependencies, false);
144
108
  const prevDate = new Date(dateToProcess); prevDate.setUTCDate(prevDate.getUTCDate() - 1);
145
109
  const prevDateStr = prevDate.toISOString().slice(0, 10);
146
110
  const previousResults = await fetchExistingResults(prevDateStr, calcsRunning, computationManifest, config, dependencies, true);
147
111
 
148
- if (standardToRun.length) {
149
- const updates = await runStandardComputationPass(dateToProcess, standardToRun, `Pass ${passToRun} (Std)`, config, dependencies, rootData, existingResults, previousResults, false);
150
- Object.assign(dateUpdates, updates);
151
- }
152
- if (metaToRun.length) {
153
- const updates = await runMetaComputationPass(dateToProcess, metaToRun, `Pass ${passToRun} (Meta)`, config, dependencies, existingResults, previousResults, rootData, false);
154
- Object.assign(dateUpdates, updates);
155
- }
112
+ if (standardToRun.length) { const updates = await runStandardComputationPass(dateToProcess, standardToRun, `Pass ${passToRun} (Std)`, config, dependencies, rootData, existingResults, previousResults, false);
113
+ Object.assign(dateUpdates, updates); }
114
+
115
+ if (metaToRun.length) { const updates = await runMetaComputationPass(dateToProcess, metaToRun, `Pass ${passToRun} (Meta)`, config, dependencies, existingResults, previousResults, rootData, false);
116
+ Object.assign(dateUpdates, updates); }
117
+
156
118
  } catch (err) {
157
119
  logger.log('ERROR', `[DateRunner] FAILED Pass ${passToRun} for ${dateStr}`, { errorMessage: err.message });
158
120
  [...standardToRun, ...metaToRun].forEach(c => dateUpdates[normalizeName(c.name)] = false);
159
121
  throw err;
160
122
  }
161
123
 
162
- if (Object.keys(dateUpdates).length > 0) {
163
- await updateComputationStatus(dateStr, dateUpdates, config, dependencies);
164
- }
124
+ if (Object.keys(dateUpdates).length > 0) { await updateComputationStatus(dateStr, dateUpdates, config, dependencies); }
165
125
 
166
126
  return { date: dateStr, updates: dateUpdates };
167
127
  }
@@ -17,70 +17,28 @@ async function handleComputationTask(message, config, dependencies, computationM
17
17
  let data;
18
18
  try {
19
19
  // 1. Handle Cloud Functions Gen 2 (CloudEvent)
20
- // Structure: event.data.message.data (base64)
21
- if (message.data && message.data.message && message.data.message.data) {
22
- const buffer = Buffer.from(message.data.message.data, 'base64');
23
- data = JSON.parse(buffer.toString());
24
- }
20
+ if (message.data && message.data.message && message.data.message.data) { const buffer = Buffer.from(message.data.message.data, 'base64'); data = JSON.parse(buffer.toString()); }
25
21
  // 2. Handle Cloud Functions Gen 1 / Legacy PubSub
26
- // Structure: message.data (base64) or message.json
27
- else if (message.data && typeof message.data === 'string') {
28
- const buffer = Buffer.from(message.data, 'base64');
29
- data = JSON.parse(buffer.toString());
30
- }
22
+ else if (message.data && typeof message.data === 'string') { const buffer = Buffer.from(message.data, 'base64'); data = JSON.parse(buffer.toString()); }
31
23
  // 3. Handle Direct JSON (Test harness or simulator)
32
- else if (message.json) {
33
- data = message.json;
34
- }
24
+ else if (message.json) { data = message.json; }
35
25
  // 4. Fallback: Assume message is the payload
36
- else {
37
- data = message;
38
- }
39
- } catch (parseError) {
40
- logger.log('ERROR', `[Worker] Failed to parse Pub/Sub payload.`, { error: parseError.message });
41
- return;
42
- }
26
+ else { data = message; }
27
+ } catch (parseError) { logger.log('ERROR', `[Worker] Failed to parse Pub/Sub payload.`, { error: parseError.message }); return; }
43
28
 
44
29
  try {
45
30
  // Validate Action
46
- if (!data || data.action !== 'RUN_COMPUTATION_DATE') {
47
- // Only log if data exists but action is wrong, prevents log spam on empty messages
48
- if (data) logger.log('WARN', `[Worker] Unknown or missing action: ${data?.action}. Ignoring.`);
49
- return;
50
- }
51
-
31
+ if (!data || data.action !== 'RUN_COMPUTATION_DATE') { if (data) logger.log('WARN', `[Worker] Unknown or missing action: ${data?.action}. Ignoring.`); return; }
52
32
  const { date, pass } = data;
53
-
54
- if (!date || !pass) {
55
- logger.log('ERROR', `[Worker] Missing date or pass in payload: ${JSON.stringify(data)}`);
56
- return;
57
- }
58
-
33
+ if (!date || !pass) { logger.log('ERROR', `[Worker] Missing date or pass in payload: ${JSON.stringify(data)}`); return; }
59
34
  logger.log('INFO', `[Worker] Received task: Date=${date}, Pass=${pass}`);
60
-
61
- // Resolve calculations for this pass
62
35
  const passes = groupByPass(computationManifest);
63
36
  const calcsInThisPass = passes[pass] || [];
64
-
65
- if (!calcsInThisPass.length) {
66
- logger.log('WARN', `[Worker] No calculations found for Pass ${pass}.`);
67
- return;
68
- }
69
-
70
- // Execute the computation for this specific date
71
- // The runner internally checks dependencies (Pass 1, 2, 3 status) and skips if not ready.
37
+ if (!calcsInThisPass.length) { logger.log('WARN', `[Worker] No calculations found for Pass ${pass}.`); return; }
72
38
  const result = await runDateComputation(date, pass, calcsInThisPass, config, dependencies, computationManifest);
73
-
74
- if (result) {
75
- logger.log('INFO', `[Worker] Successfully processed ${date} (Pass ${pass}). Updates: ${Object.keys(result.updates || {}).length}`);
76
- } else {
77
- logger.log('INFO', `[Worker] Processed ${date} (Pass ${pass}) - Skipped (Dependencies missing or already done).`);
78
- }
79
-
80
- } catch (err) {
81
- logger.log('ERROR', `[Worker] Fatal error processing task: ${err.message}`, { stack: err.stack });
82
- throw err; // Re-throw to trigger Pub/Sub retry
83
- }
39
+ if (result) { logger.log('INFO', `[Worker] Successfully processed ${date} (Pass ${pass}). Updates: ${Object.keys(result.updates || {}).length}`);
40
+ } else { logger.log('INFO', `[Worker] Processed ${date} (Pass ${pass}) - Skipped (Dependencies missing or already done).`); }
41
+ } catch (err) { logger.log('ERROR', `[Worker] Fatal error processing task: ${err.message}`, { stack: err.stack }); throw err; }
84
42
  }
85
43
 
86
44
  module.exports = { handleComputationTask };