bulltrackers-module 1.0.311 → 1.0.312
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,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FILENAME: computation-system/helpers/computation_dispatcher.js
|
|
3
3
|
* PURPOSE: Sequential Cursor-Based Dispatcher with Hyper-Verbose Telemetry.
|
|
4
|
-
* FIX: Added dispatchId
|
|
4
|
+
* FIX: Added dispatchId, triggerReason, and detailed logging requirements.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { getExpectedDateStrings, getEarliestDataDates, normalizeName, DEFINITIVE_EARLIEST_DATES } = require('../utils/utils.js');
|
|
@@ -9,7 +9,7 @@ const { groupByPass, analyzeDateExecution } = require('../WorkflowOrchestrator.j
|
|
|
9
9
|
const { PubSubUtils } = require('../../core/utils/pubsub_utils');
|
|
10
10
|
const { fetchComputationStatus } = require('../persistence/StatusRepository');
|
|
11
11
|
const { checkRootDataAvailability } = require('../data/AvailabilityChecker');
|
|
12
|
-
const crypto = require('crypto');
|
|
12
|
+
const crypto = require('crypto');
|
|
13
13
|
|
|
14
14
|
const OOM_THRESHOLD_MB = 1500;
|
|
15
15
|
const SECONDS_PER_CALC_MARGIN = 25;
|
|
@@ -43,14 +43,12 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
43
43
|
const targetCursorN = parseInt(reqBody.cursorIndex || 1);
|
|
44
44
|
const dateLimitStr = reqBody.date || config.date || "2025-01-01";
|
|
45
45
|
|
|
46
|
-
logger.log('INFO', `[Dispatcher] 🚀 STARTING DISPATCH: Pass ${passToRun}, Cursor ${targetCursorN}, Limit ${dateLimitStr}`);
|
|
47
|
-
|
|
48
46
|
const manifestMap = new Map(computationManifest.map(c => [normalizeName(c.name), c]));
|
|
49
47
|
const passes = groupByPass(computationManifest);
|
|
50
48
|
const calcsInThisPass = passes[passToRun] || [];
|
|
51
49
|
|
|
52
50
|
if (!calcsInThisPass.length) {
|
|
53
|
-
logger.log('WARN', `[Dispatcher] 🛑 No calculations found for Pass ${passToRun}
|
|
51
|
+
logger.log('WARN', `[Dispatcher] 🛑 No calculations found for Pass ${passToRun}.`);
|
|
54
52
|
return { status: 'MOVE_TO_NEXT_PASS', dispatched: 0 };
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -62,6 +60,7 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
62
60
|
return { status: 'MOVE_TO_NEXT_PASS', dispatched: 0 };
|
|
63
61
|
}
|
|
64
62
|
|
|
63
|
+
// 1. Identify all "Dirty" dates (dates that actually have work to do)
|
|
65
64
|
const dirtyDates = [];
|
|
66
65
|
for (const d of allDates) {
|
|
67
66
|
const dailyStatus = await fetchComputationStatus(d, config, dependencies);
|
|
@@ -82,10 +81,10 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
82
81
|
let isReroute = false;
|
|
83
82
|
let isSweep = false;
|
|
84
83
|
|
|
84
|
+
// Logic for Reroutes (OOM handling)
|
|
85
85
|
if (targetCursorN > 1 && (targetCursorN - 2) < dirtyDates.length) {
|
|
86
86
|
const prevEntry = dirtyDates[targetCursorN - 2];
|
|
87
87
|
const reroutes = await getHighMemReroutes(db, prevEntry.date, passToRun, prevEntry.tasks);
|
|
88
|
-
|
|
89
88
|
if (reroutes.length > 0) {
|
|
90
89
|
selectedDate = prevEntry.date;
|
|
91
90
|
selectedTasks = reroutes;
|
|
@@ -93,6 +92,7 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
|
|
95
|
+
// Logic for standard cursor progression
|
|
96
96
|
if (!selectedDate) {
|
|
97
97
|
if (targetCursorN <= dirtyDates.length) {
|
|
98
98
|
const entry = dirtyDates[targetCursorN - 1];
|
|
@@ -106,11 +106,27 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (!selectedDate) {
|
|
109
|
+
logger.log('INFO', `[Dispatcher] 🏁 Pass ${passToRun} is fully satiated. No work remaining.`);
|
|
109
110
|
return { status: 'MOVE_TO_NEXT_PASS', dispatched: 0, etaSeconds: 0 };
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
//
|
|
113
|
+
// 2. Prepare Payload and Telemetry
|
|
113
114
|
const currentDispatchId = crypto.randomUUID();
|
|
115
|
+
const etaSeconds = Math.max(20, selectedTasks.length * SECONDS_PER_CALC_MARGIN);
|
|
116
|
+
const remainingDatesCount = Math.max(0, dirtyDates.length - targetCursorN);
|
|
117
|
+
|
|
118
|
+
// requirement: condense computations into a log payload
|
|
119
|
+
const computationNames = selectedTasks.map(t => t.name);
|
|
120
|
+
|
|
121
|
+
logger.log('INFO', `[Dispatcher] ✅ Dispatching ${selectedTasks.length} tasks for ${selectedDate}. ETA: ${etaSeconds}s.`, {
|
|
122
|
+
date: selectedDate,
|
|
123
|
+
pass: passToRun,
|
|
124
|
+
dispatchedCount: selectedTasks.length,
|
|
125
|
+
remainingCursorDates: remainingDatesCount,
|
|
126
|
+
etaSeconds: etaSeconds,
|
|
127
|
+
dispatchId: currentDispatchId,
|
|
128
|
+
tasks: computationNames // Condensed into JSON payload
|
|
129
|
+
});
|
|
114
130
|
|
|
115
131
|
const mapToTaskPayload = (t) => ({
|
|
116
132
|
...t,
|
|
@@ -118,8 +134,8 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
118
134
|
computation: t.name,
|
|
119
135
|
date: selectedDate,
|
|
120
136
|
pass: passToRun,
|
|
121
|
-
dispatchId: currentDispatchId,
|
|
122
|
-
triggerReason: t.reason
|
|
137
|
+
dispatchId: currentDispatchId,
|
|
138
|
+
triggerReason: t.reason
|
|
123
139
|
});
|
|
124
140
|
|
|
125
141
|
const standardTasks = selectedTasks.filter(t => t.resources !== 'high-mem').map(mapToTaskPayload);
|
|
@@ -142,14 +158,13 @@ async function dispatchComputationPass(config, dependencies, computationManifest
|
|
|
142
158
|
}
|
|
143
159
|
await Promise.all(pubPromises);
|
|
144
160
|
|
|
145
|
-
const etaSeconds = Math.max(20, selectedTasks.length * SECONDS_PER_CALC_MARGIN);
|
|
146
|
-
|
|
147
161
|
return {
|
|
148
162
|
status : isSweep ? 'RECOVERY' : 'CONTINUE_PASS',
|
|
149
163
|
dateProcessed : selectedDate,
|
|
150
164
|
dispatched : selectedTasks.length,
|
|
151
165
|
n_cursor_ignored: isReroute,
|
|
152
|
-
etaSeconds : etaSeconds
|
|
166
|
+
etaSeconds : etaSeconds,
|
|
167
|
+
remainingDates : remainingDatesCount // For Workflow consumption
|
|
153
168
|
};
|
|
154
169
|
}
|
|
155
170
|
|