bulltrackers-module 1.0.330 → 1.0.332
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.
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Executor for "Standard" (per-user) calculations.
|
|
3
3
|
* UPDATED: Tracks IO Operations (Reads/Writes) for Cost Analysis.
|
|
4
|
+
* UPDATED: Supports System Context Injection (requiresEarliestDataDate).
|
|
4
5
|
*/
|
|
5
|
-
const { normalizeName }
|
|
6
|
+
const { normalizeName, getEarliestDataDates } = require('../utils/utils');
|
|
6
7
|
const { streamPortfolioData, streamHistoryData, getPortfolioPartRefs } = require('../utils/data_loader');
|
|
7
8
|
const { CachedDataLoader } = require('../data/CachedDataLoader');
|
|
8
9
|
const { ContextFactory } = require('../context/ContextFactory');
|
|
@@ -78,6 +79,13 @@ class StandardExecutor {
|
|
|
78
79
|
const prevDate = new Date(dateStr + 'T00:00:00Z'); prevDate.setUTCDate(prevDate.getUTCDate() - 1);
|
|
79
80
|
const prevDateStr = prevDate.toISOString().slice(0, 10);
|
|
80
81
|
|
|
82
|
+
// [NEW] Check if any calculation requires System Context Injection (e.g. Earliest Date)
|
|
83
|
+
let earliestDates = null;
|
|
84
|
+
if (streamingCalcs.some(c => c.manifest.requiresEarliestDataDate)) {
|
|
85
|
+
// Fetch once per batch, not per user
|
|
86
|
+
earliestDates = await getEarliestDataDates(config, deps);
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
const tP_iter = streamPortfolioData(config, deps, dateStr, portfolioRefs);
|
|
82
90
|
const needsYesterdayPortfolio = streamingCalcs.some(c => c.manifest.isHistorical);
|
|
83
91
|
const yP_iter = (needsYesterdayPortfolio && rootData.yesterdayPortfolioRefs) ? streamPortfolioData(config, deps, prevDateStr, rootData.yesterdayPortfolioRefs) : null;
|
|
@@ -102,7 +110,8 @@ class StandardExecutor {
|
|
|
102
110
|
StandardExecutor.executePerUser(
|
|
103
111
|
calc, calc.manifest, dateStr, tP_chunk, yP_chunk, tH_chunk,
|
|
104
112
|
fetchedDeps, previousFetchedDeps, config, deps, cachedLoader,
|
|
105
|
-
executionStats[normalizeName(calc.manifest.name)]
|
|
113
|
+
executionStats[normalizeName(calc.manifest.name)],
|
|
114
|
+
earliestDates // [NEW] Pass system context data
|
|
106
115
|
)
|
|
107
116
|
));
|
|
108
117
|
|
|
@@ -208,7 +217,7 @@ class StandardExecutor {
|
|
|
208
217
|
if (newResult.failureReport) failureAcc.push(...newResult.failureReport);
|
|
209
218
|
}
|
|
210
219
|
|
|
211
|
-
static async executePerUser(calcInstance, metadata, dateStr, portfolioData, yesterdayPortfolioData, historyData, computedDeps, prevDeps, config, deps, loader, stats) {
|
|
220
|
+
static async executePerUser(calcInstance, metadata, dateStr, portfolioData, yesterdayPortfolioData, historyData, computedDeps, prevDeps, config, deps, loader, stats, earliestDates) {
|
|
212
221
|
const { logger } = deps;
|
|
213
222
|
const targetUserType = metadata.userType;
|
|
214
223
|
const mappings = await loader.loadMappings();
|
|
@@ -237,6 +246,12 @@ class StandardExecutor {
|
|
|
237
246
|
computedDependencies: computedDeps, previousComputedDependencies: prevDeps,
|
|
238
247
|
config, deps
|
|
239
248
|
});
|
|
249
|
+
|
|
250
|
+
// [NEW] Inject System Context if requested by Metadata
|
|
251
|
+
if (metadata.requiresEarliestDataDate && earliestDates) {
|
|
252
|
+
if (!context.system) context.system = {};
|
|
253
|
+
context.system.earliestHistoryDate = earliestDates.history;
|
|
254
|
+
}
|
|
240
255
|
|
|
241
256
|
try {
|
|
242
257
|
await calcInstance.process(context);
|
|
@@ -357,7 +357,7 @@ async function handleStandardDispatch(config, dependencies, computationManifest,
|
|
|
357
357
|
|
|
358
358
|
const taskDetails = selectedTasks.map(t => `${t.name} (${t.reason})`);
|
|
359
359
|
logger.log('INFO', `[Dispatcher] ✅ Dispatching ${selectedTasks.length} tasks for ${selectedDate}.`, {
|
|
360
|
-
date: selectedDate, pass: passToRun, dispatchedCount: selectedTasks.length, etaSeconds, dispatchId: currentDispatchId
|
|
360
|
+
date: selectedDate, pass: passToRun, dispatchedCount: selectedTasks.length, etaSeconds, dispatchId: currentDispatchId, details: taskDetails
|
|
361
361
|
});
|
|
362
362
|
|
|
363
363
|
const mapToTaskPayload = (t) => ({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Handles saving computation results with observability and Smart Cleanup.
|
|
3
3
|
* UPDATED: Tracks specific Firestore Ops (Writes/Deletes) for cost analysis.
|
|
4
|
+
* UPDATED: Added Dynamic Circuit Breaker Bypass for Price-Only calculations.
|
|
4
5
|
*/
|
|
5
6
|
const { commitBatchInChunks, generateDataHash } = require('../utils/utils');
|
|
6
7
|
const { updateComputationStatus } = require('./StatusRepository');
|
|
@@ -54,12 +55,23 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
|
|
|
54
55
|
try {
|
|
55
56
|
const result = await calc.getResult();
|
|
56
57
|
const configOverrides = validationOverrides[calc.manifest.name] || {};
|
|
58
|
+
|
|
59
|
+
// --- [DYNAMIC OVERRIDE LOGIC START] ---
|
|
57
60
|
const dataDeps = calc.manifest.rootDataDependencies || [];
|
|
58
61
|
const isPriceOnly = (dataDeps.length === 1 && dataDeps[0] === 'price');
|
|
59
62
|
let effectiveOverrides = { ...configOverrides };
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
// If a calculation relies solely on price, we strictly bypass the circuit breaker.
|
|
65
|
+
// This handles Holidays (Weekday 0s), Weekends (Scheduler Gaps), and Crypto/Stock mix.
|
|
66
|
+
if (isPriceOnly) {
|
|
67
|
+
effectiveOverrides.maxZeroPct = 100;
|
|
68
|
+
effectiveOverrides.maxFlatlinePct = 100;
|
|
69
|
+
effectiveOverrides.maxNullPct = 100;
|
|
70
|
+
effectiveOverrides.maxNanPct = 100;
|
|
71
|
+
// Remove specific weekend config to ensure these permissive global limits apply 7 days/week
|
|
72
|
+
delete effectiveOverrides.weekend;
|
|
62
73
|
}
|
|
74
|
+
// --- [DYNAMIC OVERRIDE LOGIC END] ---
|
|
63
75
|
|
|
64
76
|
const contract = contractMap[name];
|
|
65
77
|
if (contract) {
|