bulltrackers-module 1.0.143 → 1.0.145
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.
|
@@ -12,8 +12,7 @@ function groupByPass(manifest) { return manifest.reduce((acc, calc) => { (acc[ca
|
|
|
12
12
|
*/
|
|
13
13
|
function checkRootDependencies(calcManifest, rootDataStatus) {
|
|
14
14
|
const missing = [];
|
|
15
|
-
if (!calcManifest.rootDataDependencies || !calcManifest.rootDataDependencies.length) {
|
|
16
|
-
return { canRun: true, missing };}
|
|
15
|
+
if (!calcManifest.rootDataDependencies || !calcManifest.rootDataDependencies.length) { return { canRun: true, missing };}
|
|
17
16
|
for (const dep of calcManifest.rootDataDependencies) {
|
|
18
17
|
if (dep === 'portfolio' && !rootDataStatus.hasPortfolio) missing.push('portfolio');
|
|
19
18
|
else if (dep === 'insights' && !rootDataStatus.hasInsights) missing.push('insights');
|
|
@@ -34,8 +33,6 @@ async function checkRootDataAvailability(dateStr, config, dependencies, earliest
|
|
|
34
33
|
let hasPortfolio = false, hasInsights = false, hasSocial = false, hasHistory = false;
|
|
35
34
|
try {
|
|
36
35
|
const tasks = [];
|
|
37
|
-
// This logic is correct. It *avoids* calling get...Refs
|
|
38
|
-
// if the dateToProcess is before the earliest known data.
|
|
39
36
|
if (dateToProcess >= earliestDates.portfolio)
|
|
40
37
|
{tasks.push(getPortfolioPartRefs(config, dependencies, dateStr).then(res => {portfolioRefs = res;hasPortfolio = !!(res?.length);}));}
|
|
41
38
|
if (dateToProcess >= earliestDates.insights) {
|
|
@@ -44,18 +41,11 @@ async function checkRootDataAvailability(dateStr, config, dependencies, earliest
|
|
|
44
41
|
tasks.push(loadDailySocialPostInsights(config, dependencies, dateStr).then(res => {socialData = res;hasSocial = !!res;}));}
|
|
45
42
|
if (dateToProcess >= earliestDates.history) {
|
|
46
43
|
tasks.push(getHistoryPartRefs(config, dependencies, dateStr).then(res => {historyRefs = res;hasHistory = !!(res?.length);}));}
|
|
47
|
-
|
|
48
44
|
await Promise.all(tasks);
|
|
49
|
-
|
|
50
|
-
// --- NEW: Log what was *actually* found ---
|
|
51
45
|
logger.log('INFO', `[PassRunner] Data availability for ${dateStr}: P:${hasPortfolio}, I:${hasInsights}, S:${hasSocial}, H:${hasHistory}`);
|
|
52
46
|
|
|
53
|
-
if (!(hasPortfolio || hasInsights || hasSocial || hasHistory)) {
|
|
54
|
-
|
|
55
|
-
// We return null to skip the entire day
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return {portfolioRefs, insightsData,socialData,historyRefs,status: { hasPortfolio, hasInsights, hasSocial, hasHistory }};
|
|
47
|
+
if (!(hasPortfolio || hasInsights || hasSocial || hasHistory)) { logger.log('WARN', `[PassRunner] No root data at all for ${dateStr}.`); return null; }
|
|
48
|
+
return { portfolioRefs, todayInsights: insightsData, todaySocialPostInsights: socialData, historyRefs, status: { hasPortfolio, hasInsights, hasSocial, hasHistory } };
|
|
59
49
|
} catch (err) { logger.log('ERROR', `[PassRunner] Error checking data for ${dateStr}`, { errorMessage: err.message }); return null; }
|
|
60
50
|
}
|
|
61
51
|
|
|
@@ -91,76 +81,32 @@ async function fetchExistingResults(dateStr, calcsInPass, fullManifest, config,
|
|
|
91
81
|
function filterCalculations(standardCalcs, metaCalcs, rootDataStatus, existingResults, passToRun, dateStr, earliestDates, logger) {
|
|
92
82
|
const skipped = new Set();
|
|
93
83
|
const dateToProcess = new Date(dateStr + 'T00:00:00Z');
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* --- CORRECTED LOGIC ---
|
|
97
|
-
* Helper to get the true earliest date a calc can run.
|
|
98
|
-
*/
|
|
99
84
|
const getTrueEarliestRunDate = (calc) => {
|
|
100
|
-
let earliestRunDate = new Date('1970-01-01T00:00:00Z');
|
|
85
|
+
let earliestRunDate = new Date('1970-01-01T00:00:00Z');
|
|
101
86
|
const dependencies = calc.rootDataDependencies || [];
|
|
102
|
-
|
|
103
|
-
// 1. Find the LATEST "today" dependency
|
|
104
|
-
// This is the date where all *today* data is first available
|
|
105
87
|
for (const dep of dependencies) {
|
|
106
88
|
if (dep === 'portfolio' && earliestDates.portfolio > earliestRunDate) earliestRunDate = earliestDates.portfolio;
|
|
107
89
|
if (dep === 'history' && earliestDates.history > earliestRunDate) earliestRunDate = earliestDates.history;
|
|
108
90
|
if (dep === 'social' && earliestDates.social > earliestRunDate) earliestRunDate = earliestDates.social;
|
|
109
91
|
if (dep === 'insights' && earliestDates.insights > earliestRunDate) earliestRunDate = earliestDates.insights;
|
|
110
92
|
}
|
|
111
|
-
|
|
112
|
-
// 2. If the calc is historical, shift the *final* date by +1
|
|
113
|
-
// This universally applies the "+1" rule if *any* yesterday data is needed,
|
|
114
|
-
// (as long as we found a dependency in step 1).
|
|
115
|
-
if (calc.isHistorical && earliestRunDate.getTime() > 0) {
|
|
116
|
-
earliestRunDate.setUTCDate(earliestRunDate.getUTCDate() + 1);
|
|
117
|
-
}
|
|
118
|
-
|
|
93
|
+
if (calc.isHistorical && earliestRunDate.getTime() > 0) { earliestRunDate.setUTCDate(earliestRunDate.getUTCDate() + 1); }
|
|
119
94
|
return earliestRunDate;
|
|
120
95
|
};
|
|
121
|
-
|
|
122
96
|
const filterCalc = (calc) => {
|
|
123
|
-
|
|
124
|
-
if (existingResults[calc.name]) {
|
|
125
|
-
logger.log('TRACE', `[Pass ${passToRun}] Skipping ${calc.name} for ${dateStr}. Result already exists.`);
|
|
126
|
-
skipped.add(calc.name);
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
97
|
+
if (existingResults[calc.name]) {logger.log('TRACE', `[Pass ${passToRun}] Skipping ${calc.name} for ${dateStr}. Result already exists.`); skipped.add(calc.name); return false;}
|
|
129
98
|
|
|
130
|
-
// 2. Check *true* earliest run date
|
|
131
99
|
const earliestRunDate = getTrueEarliestRunDate(calc);
|
|
132
|
-
if (dateToProcess < earliestRunDate) {
|
|
133
|
-
|
|
134
|
-
skipped.add(calc.name);
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 3. Check if *today's* root data was *actually* found
|
|
139
|
-
// This handles gaps *after* the earliest date
|
|
100
|
+
if (dateToProcess < earliestRunDate) {logger.log('TRACE', `[Pass ${passToRun}] Skipping ${calc.name} for ${dateStr}. Date is before true earliest run date (${earliestRunDate.toISOString().slice(0, 10)}).`); skipped.add(calc.name); return false; }
|
|
101
|
+
|
|
140
102
|
const { canRun, missing: missingRoot } = checkRootDependencies(calc, rootDataStatus);
|
|
141
|
-
if (!canRun) {
|
|
142
|
-
logger.log('INFO', `[Pass ${passToRun}] Skipping ${calc.name} for ${dateStr}. Data missing for this date: [${missingRoot.join(', ')}]`);
|
|
143
|
-
skipped.add(calc.name);
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// 4. (For Meta Calcs) Check computed dependencies
|
|
148
|
-
if (calc.type === 'meta') {
|
|
149
|
-
const missingDeps = (calc.dependencies || []).map(normalizeName).filter(d => !existingResults[d]);
|
|
150
|
-
if (missingDeps.length > 0) {
|
|
151
|
-
logger.log('WARN', `[Pass ${passToRun} Meta] Skipping ${calc.name} for ${dateStr}. Missing computed deps: [${missingDeps.join(', ')}]`);
|
|
152
|
-
skipped.add(calc.name);
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
103
|
+
if (!canRun) {logger.log('INFO', `[Pass ${passToRun}] Skipping ${calc.name} for ${dateStr}. Data missing for this date: [${missingRoot.join(', ')}]`);skipped.add(calc.name); return false;}
|
|
156
104
|
|
|
157
|
-
|
|
105
|
+
if (calc.type === 'meta') { const missingDeps = (calc.dependencies || []).map(normalizeName).filter(d => !existingResults[d]); if (missingDeps.length > 0) { logger.log('WARN', `[Pass ${passToRun} Meta] Skipping ${calc.name} for ${dateStr}. Missing computed deps: [${missingDeps.join(', ')}]`); skipped.add(calc.name); return false;} }
|
|
158
106
|
return true;
|
|
159
107
|
};
|
|
160
|
-
|
|
161
108
|
const standardCalcsToRun = standardCalcs.filter(filterCalc);
|
|
162
109
|
const metaCalcsToRun = metaCalcs.filter(filterCalc);
|
|
163
|
-
|
|
164
110
|
return { standardCalcsToRun, metaCalcsToRun };
|
|
165
111
|
}
|
|
166
112
|
|
|
@@ -169,50 +115,35 @@ function filterCalculations(standardCalcs, metaCalcs, rootDataStatus, existingRe
|
|
|
169
115
|
function initializeCalculators(calcs, logger) { const state = {}; for (const c of calcs) { const name=normalizeName(c.name), Cl=c.class; if(typeof Cl==='function') try { const inst=new Cl(); inst.manifest=c; state[name]=inst; } catch(e){logger.warn(`Init failed ${name}`,{errorMessage:e.message}); state[name]=null;} else {logger.warn(`Class missing ${name}`); state[name]=null;} } return state; }
|
|
170
116
|
|
|
171
117
|
/** * Stage 7: Load historical data required for calculations
|
|
172
|
-
* --- THIS FUNCTION IS NOW FIXED ---
|
|
173
118
|
*/
|
|
174
119
|
async function loadHistoricalData(date, calcs, config, deps, rootData) {
|
|
175
|
-
const { logger }
|
|
176
|
-
const updated
|
|
177
|
-
|
|
120
|
+
const { logger } = deps;
|
|
121
|
+
const updated = {...rootData}, dStr=date.toISOString().slice(0,10); const tasks = [];
|
|
178
122
|
const needsYesterdayPortfolio = calcs.some(c => c.isHistorical && c.rootDataDependencies.includes('portfolio'));
|
|
179
|
-
const needsTodayHistory
|
|
180
|
-
const needsYesterdayHistory
|
|
181
|
-
const needsYesterdayInsights
|
|
182
|
-
const needsYesterdaySocial
|
|
183
|
-
|
|
184
|
-
// --- MODIFIED: Be smarter about loading data ---
|
|
123
|
+
const needsTodayHistory = calcs.some(c => c.rootDataDependencies.includes('history'));
|
|
124
|
+
const needsYesterdayHistory = calcs.some(c => c.isHistorical && c.rootDataDependencies.includes('history'));
|
|
125
|
+
const needsYesterdayInsights = calcs.some(c => c.isHistorical && c.rootDataDependencies.includes('insights'));
|
|
126
|
+
const needsYesterdaySocial = calcs.some(c => c.isHistorical && c.rootDataDependencies.includes('social'));
|
|
185
127
|
if(needsYesterdayPortfolio) {
|
|
186
128
|
tasks.push((async()=>{ const prev=new Date(date); prev.setUTCDate(prev.getUTCDate()-1); const prevStr=prev.toISOString().slice(0,10);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
})());
|
|
190
|
-
}
|
|
129
|
+
logger.log('INFO', `[PassRunner] Loading YESTERDAY portfolio data for ${prevStr}`);
|
|
130
|
+
updated.yesterdayPortfolios=await loadFullDayMap(config,deps,await getPortfolioPartRefs(config,deps,prevStr)); })());}
|
|
191
131
|
if(needsTodayHistory) {
|
|
192
132
|
tasks.push((async()=>{
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
})());
|
|
196
|
-
}
|
|
133
|
+
logger.log('INFO', `[PassRunner] Loading TODAY history data for ${dStr}`);
|
|
134
|
+
updated.todayHistoryData=await loadFullDayMap(config,deps,rootData.historyRefs); })());}
|
|
197
135
|
if(needsYesterdayHistory) {
|
|
198
136
|
tasks.push((async()=>{ const prev=new Date(date); prev.setUTCDate(prev.getUTCDate()-1); const prevStr=prev.toISOString().slice(0,10);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
})());
|
|
202
|
-
}
|
|
137
|
+
logger.log('INFO', `[PassRunner] Loading YESTERDAY history data for ${prevStr}`);
|
|
138
|
+
updated.yesterdayHistoryData=await loadFullDayMap(config,deps,await getHistoryPartRefs(config,deps,prevStr)); })());}
|
|
203
139
|
if(needsYesterdayInsights) {
|
|
204
140
|
tasks.push((async()=>{ const prev=new Date(date); prev.setUTCDate(prev.getUTCDate()-1); const prevStr=prev.toISOString().slice(0,10);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
})());
|
|
208
|
-
}
|
|
141
|
+
logger.log('INFO', `[PassRunner] Loading YESTERDAY insights data for ${prevStr}`);
|
|
142
|
+
updated.yesterdayInsights=await loadDailyInsights(config,deps,prevStr); })());}
|
|
209
143
|
if(needsYesterdaySocial) {
|
|
210
144
|
tasks.push((async()=>{ const prev=new Date(date); prev.setUTCDate(prev.getUTCDate()-1); const prevStr=prev.toISOString().slice(0,10);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
})());
|
|
214
|
-
}
|
|
215
|
-
|
|
145
|
+
logger.log('INFO', `[PassRunner] Loading YESTERDAY social data for ${prevStr}`);
|
|
146
|
+
updated.yesterdaySocialPostInsights=await loadDailySocialPostInsights(config,deps,prevStr); })());}
|
|
216
147
|
await Promise.all(tasks); return updated;
|
|
217
148
|
}
|
|
218
149
|
|
|
@@ -223,17 +154,10 @@ async function loadHistoricalData(date, calcs, config, deps, rootData) {
|
|
|
223
154
|
*/
|
|
224
155
|
async function streamAndProcess(dateStr, state, passName, config, deps, rootData) {
|
|
225
156
|
const { logger, calculationUtils } = deps;
|
|
226
|
-
// --- MODIFIED: yesterdayInsights/Social are now loaded by loadHistoricalData ---
|
|
227
157
|
const { todayInsights, yesterdayInsights, todaySocialPostInsights, yesterdaySocialPostInsights, todayHistoryData, yesterdayHistoryData, yesterdayPortfolios } = rootData;
|
|
228
|
-
|
|
229
|
-
// --- NEW: Check if streaming is even needed ---
|
|
230
158
|
const calcsThatStreamPortfolio = Object.values(state).filter(calc => calc && calc.manifest && (calc.manifest.rootDataDependencies.includes('portfolio') || calc.manifest.category === 'speculators'));
|
|
231
|
-
|
|
232
159
|
const context={instrumentMappings:(await calculationUtils.loadInstrumentMappings()).instrumentToTicker, sectorMapping:(await calculationUtils.loadInstrumentMappings()).instrumentToSector, todayDateStr:dateStr, dependencies:deps, config};
|
|
233
|
-
|
|
234
|
-
// --- MODIFIED: Run non-streaming calcs first (social/insights) ---
|
|
235
|
-
// This allows them to run even if portfolio data is missing
|
|
236
|
-
let firstUser=true; // Used to run them only once
|
|
160
|
+
let firstUser=true;
|
|
237
161
|
for(const name in state){
|
|
238
162
|
const calc=state[name]; if(!calc||typeof calc.process!=='function') continue;
|
|
239
163
|
const cat=calc.manifest.category;
|
|
@@ -241,7 +165,6 @@ async function streamAndProcess(dateStr, state, passName, config, deps, rootData
|
|
|
241
165
|
if (firstUser) {
|
|
242
166
|
logger.log('INFO', `[${passName}] Running non-streaming calc: ${name}`);
|
|
243
167
|
let args=[null,null,null,{...context, userType: 'n/a'},todayInsights,yesterdayInsights,todaySocialPostInsights,yesterdaySocialPostInsights,todayHistoryData,yesterdayHistoryData];
|
|
244
|
-
// Pass historical data if needed
|
|
245
168
|
if(calc.manifest.isHistorical) {
|
|
246
169
|
args=[null,null,null,{...context, userType: 'n/a'},todayInsights,yesterdayInsights,todaySocialPostInsights,yesterdaySocialPostInsights,todayHistoryData,yesterdayHistoryData];
|
|
247
170
|
}
|
|
@@ -249,15 +172,10 @@ async function streamAndProcess(dateStr, state, passName, config, deps, rootData
|
|
|
249
172
|
}
|
|
250
173
|
}
|
|
251
174
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
175
|
if (calcsThatStreamPortfolio.length === 0) {
|
|
255
176
|
logger.log('INFO', `[${passName}] No portfolio-streaming calcs to run for ${dateStr}. Skipping stream.`);
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
|
|
177
|
+
return; }
|
|
259
178
|
logger.log('INFO', `[${passName}] Streaming portfolio data for ${calcsThatStreamPortfolio.length} calcs...`);
|
|
260
|
-
|
|
261
179
|
for await (const chunk of streamPortfolioData(config, deps, dateStr)) {
|
|
262
180
|
for(const uid in chunk){ const p=chunk[uid]; if(!p) continue;
|
|
263
181
|
const userType=p.PublicPositions?'speculator':'normal';
|
|
@@ -265,18 +183,12 @@ async function streamAndProcess(dateStr, state, passName, config, deps, rootData
|
|
|
265
183
|
for(const name in state){
|
|
266
184
|
const calc=state[name]; if(!calc||typeof calc.process!=='function') continue;
|
|
267
185
|
const cat=calc.manifest.category, isSocialOrInsights=cat==='socialPosts'||cat==='insights', isHistorical=calc.manifest.isHistorical, isSpec=cat==='speculators';
|
|
268
|
-
|
|
269
|
-
// --- MODIFIED: Skip social/insights here, they ran above ---
|
|
270
186
|
if(isSocialOrInsights) continue;
|
|
271
|
-
|
|
272
187
|
let args=[p,null,uid,context,todayInsights,yesterdayInsights,todaySocialPostInsights,yesterdaySocialPostInsights,todayHistoryData,yesterdayHistoryData];
|
|
273
|
-
|
|
274
188
|
if(isHistorical){
|
|
275
|
-
const pY=yesterdayPortfolios ? yesterdayPortfolios[uid] : null;
|
|
276
|
-
// V3 behavioural calcs (like history aggregator) *can* run without pY
|
|
189
|
+
const pY=yesterdayPortfolios ? yesterdayPortfolios[uid] : null;
|
|
277
190
|
if(!pY && (cat !== 'behavioural' && name !== 'historical-performance-aggregator')) continue;
|
|
278
|
-
args=[p,pY,uid,context,todayInsights,yesterdayInsights,todaySocialPostInsights,yesterdaySocialPostInsights,todayHistoryData,yesterdayHistoryData];
|
|
279
|
-
}
|
|
191
|
+
args=[p,pY,uid,context,todayInsights,yesterdayInsights,todaySocialPostInsights,yesterdaySocialPostInsights,todayHistoryData,yesterdayHistoryData]; }
|
|
280
192
|
if((userType==='normal'&&isSpec)||(userType==='speculator'&&!isSpec&&name!=='users-processed')) continue;
|
|
281
193
|
try{ await Promise.resolve(calc.process(...args)); } catch(e){logger.log('WARN',`Process error ${name} for ${uid}`,{err:e.message});} }
|
|
282
194
|
firstUser=false;
|
|
@@ -287,20 +199,13 @@ async function streamAndProcess(dateStr, state, passName, config, deps, rootData
|
|
|
287
199
|
/** Stage 9: Run standard computations */
|
|
288
200
|
async function runStandardComputationPass(date, calcs, passName, config, deps, rootData) {
|
|
289
201
|
const dStr = date.toISOString().slice(0, 10), logger = deps.logger;
|
|
290
|
-
// --- THIS IS THE CRITICAL CHANGE ---
|
|
291
|
-
// If 'calcs' is empty *because of the new filter*, this log won't even appear.
|
|
292
202
|
if (calcs.length === 0) {
|
|
293
203
|
logger.log('INFO', `[${passName}] No standard calcs to run for ${dStr} after filtering.`);
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
// This log now only appears if there is *actually* work to do.
|
|
204
|
+
return; }
|
|
297
205
|
logger.log('INFO', `[${passName}] Running ${dStr} with ${calcs.length} calcs.`);
|
|
298
|
-
|
|
299
206
|
const fullRoot = await loadHistoricalData(date, calcs, config, deps, rootData);
|
|
300
207
|
const state = initializeCalculators(calcs, logger);
|
|
301
|
-
|
|
302
208
|
await streamAndProcess(dStr, state, passName, config, deps, fullRoot);
|
|
303
|
-
|
|
304
209
|
let success = 0;
|
|
305
210
|
const standardWrites = [];
|
|
306
211
|
const shardedWrites = {};
|
|
@@ -337,8 +242,8 @@ async function runStandardComputationPass(date, calcs, passName, config, deps, r
|
|
|
337
242
|
if (standardWrites.length > 0) {
|
|
338
243
|
await commitBatchInChunks(config, deps, standardWrites, `${passName} Standard ${dStr}`);
|
|
339
244
|
}
|
|
340
|
-
for (const docPath in shardedWrites) {
|
|
341
|
-
const docData = shardedWrites[docPath];
|
|
245
|
+
for (const docPath in shardedWrites) {
|
|
246
|
+
const docData = shardedWrites[docPath];
|
|
342
247
|
const shardedDocWrites = [];
|
|
343
248
|
let docRef;
|
|
344
249
|
if (docPath.includes('/')) {
|
|
@@ -364,17 +269,12 @@ async function runStandardComputationPass(date, calcs, passName, config, deps, r
|
|
|
364
269
|
/** Stage 10: Run meta computations */
|
|
365
270
|
async function runMetaComputationPass(date, calcs, passName, config, deps, fetchedDeps, rootData) {
|
|
366
271
|
const dStr = date.toISOString().slice(0, 10), logger = deps.logger;
|
|
367
|
-
// --- THIS IS THE CRITICAL CHANGE ---
|
|
368
272
|
if (calcs.length === 0) {
|
|
369
273
|
logger.log('INFO', `[${passName}] No meta calcs to run for ${dStr} after filtering.`);
|
|
370
274
|
return;
|
|
371
275
|
}
|
|
372
276
|
logger.log('INFO', `[${passName}] Running ${dStr} with ${calcs.length} calcs.`);
|
|
373
|
-
|
|
374
|
-
// --- NEW: Load historical data for meta calcs if needed ---
|
|
375
|
-
// (This might be redundant if standard pass ran, but meta-calcs can run standalone)
|
|
376
277
|
const fullRoot = await loadHistoricalData(date, calcs, config, deps, rootData);
|
|
377
|
-
|
|
378
278
|
let success = 0;
|
|
379
279
|
const standardWrites = [];
|
|
380
280
|
const shardedWrites = {};
|
|
@@ -383,7 +283,6 @@ async function runMetaComputationPass(date, calcs, passName, config, deps, fetch
|
|
|
383
283
|
if (typeof Cl !== 'function') {logger.log('ERROR', `Invalid class ${name}`);continue;}
|
|
384
284
|
const inst = new Cl();
|
|
385
285
|
try {
|
|
386
|
-
// --- MODIFIED: Pass fullRoot to meta calcs ---
|
|
387
286
|
const result = await Promise.resolve(inst.process(dStr, { ...deps, rootData: fullRoot }, config, fetchedDeps));
|
|
388
287
|
if (result && Object.keys(result).length > 0) {const standardResult = {}; for (const key in result) {
|
|
389
288
|
if (key.startsWith('sharded_')) {const shardedData = result[key];for (const collectionName in shardedData)
|