bulltrackers-module 1.0.176 → 1.0.177
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.
- package/functions/computation-system/controllers/computation_controller.js +1 -15
- package/functions/computation-system/helpers/computation_manifest_builder.js +4 -10
- package/functions/computation-system/helpers/computation_pass_runner.js +2 -8
- package/functions/task-engine/helpers/update_helpers.js +10 -2
- package/package.json +1 -1
|
@@ -147,28 +147,17 @@ class ComputationExecutor {
|
|
|
147
147
|
*/
|
|
148
148
|
async executePerUser(calcInstance, metadata, dateStr, portfolioData, yesterdayPortfolioData, historyData, computedDeps, prevDeps) {
|
|
149
149
|
const { logger } = this.deps;
|
|
150
|
-
|
|
151
|
-
// Fix for the 'all' userType discrepancy:
|
|
152
|
-
const targetUserType = metadata.userType; // 'all', 'normal', or 'speculator'
|
|
153
|
-
|
|
150
|
+
const targetUserType = metadata.userType;
|
|
154
151
|
const mappings = await this.loader.loadMappings();
|
|
155
152
|
const insights = metadata.rootDataDependencies?.includes('insights') ? { today: await this.loader.loadInsights(dateStr) } : null;
|
|
156
|
-
|
|
157
153
|
for (const [userId, todayPortfolio] of Object.entries(portfolioData)) {
|
|
158
|
-
// 1. Get Yesterday's Portfolio (if available)
|
|
159
154
|
const yesterdayPortfolio = yesterdayPortfolioData ? yesterdayPortfolioData[userId] : null;
|
|
160
|
-
|
|
161
|
-
// 2. Get Today's Trading History (if available)
|
|
162
155
|
const todayHistory = historyData ? historyData[userId] : null;
|
|
163
|
-
|
|
164
156
|
const actualUserType = todayPortfolio.PublicPositions ? SCHEMAS.USER_TYPES.SPECULATOR : SCHEMAS.USER_TYPES.NORMAL;
|
|
165
|
-
|
|
166
|
-
// Filtering Logic
|
|
167
157
|
if (targetUserType !== 'all') {
|
|
168
158
|
const mappedTarget = (targetUserType === 'speculator') ? SCHEMAS.USER_TYPES.SPECULATOR : SCHEMAS.USER_TYPES.NORMAL;
|
|
169
159
|
if (mappedTarget !== actualUserType) continue;
|
|
170
160
|
}
|
|
171
|
-
|
|
172
161
|
const context = ContextBuilder.buildPerUserContext({
|
|
173
162
|
todayPortfolio, yesterdayPortfolio,
|
|
174
163
|
todayHistory,
|
|
@@ -177,7 +166,6 @@ class ComputationExecutor {
|
|
|
177
166
|
previousComputedDependencies: prevDeps,
|
|
178
167
|
config: this.config, deps: this.deps
|
|
179
168
|
});
|
|
180
|
-
|
|
181
169
|
try { await calcInstance.process(context); }
|
|
182
170
|
catch (e) { logger.log('WARN', `Calc ${metadata.name} failed for user ${userId}: ${e.message}`); }
|
|
183
171
|
}
|
|
@@ -187,14 +175,12 @@ class ComputationExecutor {
|
|
|
187
175
|
const mappings = await this.loader.loadMappings();
|
|
188
176
|
const insights = metadata.rootDataDependencies?.includes('insights') ? { today: await this.loader.loadInsights(dateStr) } : null;
|
|
189
177
|
const social = metadata.rootDataDependencies?.includes('social') ? { today: await this.loader.loadSocial(dateStr) } : null;
|
|
190
|
-
|
|
191
178
|
const context = ContextBuilder.buildMetaContext({
|
|
192
179
|
dateStr, metadata, mappings, insights, socialData: social,
|
|
193
180
|
computedDependencies: computedDeps,
|
|
194
181
|
previousComputedDependencies: prevDeps,
|
|
195
182
|
config: this.config, deps: this.deps
|
|
196
183
|
});
|
|
197
|
-
|
|
198
184
|
return await calcInstance.process(context);
|
|
199
185
|
}
|
|
200
186
|
}
|
|
@@ -11,15 +11,6 @@
|
|
|
11
11
|
* It has removed all logic for deprecated folder structures (e.g., /historical/).
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
//Hacky solution to force tmp writes TODO : This Tmp write is really dodgy, not ideal but works, consider less hacky solutions to writing to filesystem
|
|
16
|
-
process.env.TMPDIR = '/tmp';
|
|
17
|
-
process.env.TMP = '/tmp';
|
|
18
|
-
process.env.TEMP = '/tmp';
|
|
19
|
-
const os = require('os');
|
|
20
|
-
|
|
21
|
-
const path = require('path');
|
|
22
|
-
|
|
23
14
|
/* --------------------------------------------------
|
|
24
15
|
* Pretty Console Helpers
|
|
25
16
|
* -------------------------------------------------- */
|
|
@@ -54,7 +45,7 @@ function suggestClosest(name, candidates, n = 3) {
|
|
|
54
45
|
return dp[m][n];
|
|
55
46
|
};
|
|
56
47
|
const scores = candidates.map(c => [c, levenshtein(name, c)]);
|
|
57
|
-
scores.sort((a, b)
|
|
48
|
+
scores.sort((a, b) => a[1] - b[1]);
|
|
58
49
|
return scores.slice(0, n).map(s => s[0]);
|
|
59
50
|
}
|
|
60
51
|
|
|
@@ -206,17 +197,20 @@ function buildManifest(productLinesToRun = [], calculations) {
|
|
|
206
197
|
const sortedManifest = [];
|
|
207
198
|
const queue = [];
|
|
208
199
|
let maxPass = 0;
|
|
200
|
+
|
|
209
201
|
for (const [name, degree] of filteredInDegree) { if (degree === 0) { queue.push(name); filteredManifestMap.get(name).pass = 1; maxPass = 1; } }
|
|
210
202
|
queue.sort();
|
|
211
203
|
while (queue.length) {
|
|
212
204
|
const currentName = queue.shift();
|
|
213
205
|
const currentEntry = filteredManifestMap.get(currentName);
|
|
214
206
|
sortedManifest.push(currentEntry);
|
|
207
|
+
|
|
215
208
|
for (const neighborName of (filteredReverseAdjacency.get(currentName) || [])) { const newDegree = filteredInDegree.get(neighborName) - 1; filteredInDegree.set(neighborName, newDegree);
|
|
216
209
|
const neighborEntry = filteredManifestMap.get(neighborName);
|
|
217
210
|
if (neighborEntry.pass <= currentEntry.pass) { neighborEntry.pass = currentEntry.pass + 1; if (neighborEntry.pass > maxPass) maxPass = neighborEntry.pass; }
|
|
218
211
|
if (newDegree === 0) { queue.push(neighborName); } }
|
|
219
212
|
queue.sort(); }
|
|
213
|
+
|
|
220
214
|
if (sortedManifest.length !== filteredManifestMap.size) {
|
|
221
215
|
log.divider('Circular Dependency Detected');
|
|
222
216
|
const cycles = findCycles(filteredManifestMap, adjacency);
|
|
@@ -62,8 +62,6 @@ async function runComputationPass(config, dependencies, computationManifest) {
|
|
|
62
62
|
// Process a single date and RETURN updates (do not write)
|
|
63
63
|
const processDate = async (dateStr) => {
|
|
64
64
|
const dateToProcess = new Date(dateStr + 'T00:00:00Z');
|
|
65
|
-
|
|
66
|
-
// Filter using in-memory status
|
|
67
65
|
const standardToRun = standardCalcs.filter(c => shouldRun(c, dateStr));
|
|
68
66
|
const metaToRun = metaCalcs.filter(c => shouldRun(c, dateStr));
|
|
69
67
|
|
|
@@ -84,21 +82,17 @@ async function runComputationPass(config, dependencies, computationManifest) {
|
|
|
84
82
|
try {
|
|
85
83
|
const calcsRunning = [...finalStandardToRun, ...finalMetaToRun];
|
|
86
84
|
const existingResults = await fetchExistingResults(dateStr, calcsRunning, computationManifest, config, dependencies, false);
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
const prevDateStr = prevDate.toISOString().slice(0, 10);
|
|
85
|
+
const prevDate = new Date(dateToProcess); prevDate.setUTCDate(prevDate.getUTCDate() - 1);
|
|
86
|
+
const prevDateStr = prevDate.toISOString().slice(0, 10);
|
|
90
87
|
const previousResults = await fetchExistingResults(prevDateStr, calcsRunning, computationManifest, config, dependencies, true);
|
|
91
|
-
|
|
92
88
|
if (finalStandardToRun.length) {
|
|
93
89
|
const updates = await runStandardComputationPass(dateToProcess, finalStandardToRun, `Pass ${passToRun} (Std)`, config, dependencies, rootData, existingResults, previousResults, true); // skipStatusWrite=true
|
|
94
90
|
Object.assign(dateUpdates, updates);
|
|
95
91
|
}
|
|
96
|
-
|
|
97
92
|
if (finalMetaToRun.length) {
|
|
98
93
|
const updates = await runMetaComputationPass(dateToProcess, finalMetaToRun, `Pass ${passToRun} (Meta)`, config, dependencies, existingResults, previousResults, rootData, true); // skipStatusWrite=true
|
|
99
94
|
Object.assign(dateUpdates, updates);
|
|
100
95
|
}
|
|
101
|
-
|
|
102
96
|
} catch (err) {
|
|
103
97
|
logger.log('ERROR', `[PassRunner] FAILED Pass ${passToRun} for ${dateStr}`, { errorMessage: err.message });
|
|
104
98
|
// Mark failures
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* (REFACTORED: Removed all concurrency from `handleUpdate` and `lookupUsernames`)
|
|
4
4
|
* (REFACTORED: Added node-fetch fallback for all API calls)
|
|
5
5
|
* (REFACTORED: Added verbose, user-centric logging for all operations)
|
|
6
|
+
* (FIXED: Corrected variable name 'instId' to 'instrumentId' in final timestamp loops)
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
const { FieldValue } = require('@google-cloud/firestore');
|
|
@@ -174,9 +175,12 @@ async function handleUpdate(task, taskId, { logger, headerManager, proxyManager,
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
// --- 5. Handle Private Users & Timestamps ---
|
|
178
|
+
// FIXED: Corrected variable naming here from 'instId' to 'instrumentId'
|
|
177
179
|
if (isPrivate) {
|
|
178
180
|
logger.log('WARN', `[handleUpdate/${userId}] Removing private user from updates.`);
|
|
179
|
-
for (const instrumentId of instrumentsToProcess) {
|
|
181
|
+
for (const instrumentId of instrumentsToProcess) {
|
|
182
|
+
await batchManager.deleteFromTimestampBatch(userId, userType, instrumentId);
|
|
183
|
+
}
|
|
180
184
|
const blockCountsRef = db.doc(config.FIRESTORE_DOC_SPECULATOR_BLOCK_COUNTS);
|
|
181
185
|
for (const instrumentId of instrumentsToProcess) {
|
|
182
186
|
const incrementField = `counts.${instrumentId}_${Math.floor(userId/1e6)*1e6}`;
|
|
@@ -186,7 +190,11 @@ async function handleUpdate(task, taskId, { logger, headerManager, proxyManager,
|
|
|
186
190
|
}
|
|
187
191
|
|
|
188
192
|
// If not private, update all timestamps
|
|
189
|
-
|
|
193
|
+
// FIXED: Corrected variable naming here from 'instId' to 'instrumentId'
|
|
194
|
+
for (const instrumentId of instrumentsToProcess) {
|
|
195
|
+
await batchManager.updateUserTimestamp(userId, userType, instrumentId);
|
|
196
|
+
}
|
|
197
|
+
|
|
190
198
|
if (userType === 'speculator') { await batchManager.addSpeculatorTimestampFix(userId, String(Math.floor(userId/1e6)*1e6)); }
|
|
191
199
|
|
|
192
200
|
logger.log('INFO', `[handleUpdate/${userId}] Update task finished successfully.`);
|