bulltrackers-module 1.0.121 → 1.0.122
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,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Sub-pipe for dispatching tasks.
|
|
3
3
|
* REFACTORED: Now stateless and receives dependencies.
|
|
4
|
+
*
|
|
5
|
+
* --- MODIFICATION ---
|
|
6
|
+
* This file has been modified to publish tasks in batches
|
|
7
|
+
* within a single Pub/Sub message, rather than one message per task.
|
|
8
|
+
* This enables the Task Engine to process users in a stateful batch.
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
@@ -23,12 +28,21 @@ async function dispatchTasksInBatches(tasks, dependencies, config) {
|
|
|
23
28
|
logger.log('INFO', `[Module Dispatcher] Received ${tasks.length} tasks. Creating batches...`);
|
|
24
29
|
|
|
25
30
|
for (let i = 0; i < tasks.length; i += batchSize) {
|
|
26
|
-
const batch = tasks.slice(i, i + batchSize);
|
|
31
|
+
const batch = tasks.slice(i, i + batchSize); // e.g., batch is [task1, task2, ... task100]
|
|
27
32
|
|
|
28
33
|
try {
|
|
29
|
-
|
|
34
|
+
// --- START MODIFICATION ---
|
|
35
|
+
// Wrap the entire batch of tasks into a single object payload.
|
|
36
|
+
// This is the payload the Task Engine will now receive.
|
|
37
|
+
const messagePayload = { tasks: batch };
|
|
38
|
+
|
|
39
|
+
// Publish the entire batch as a single message
|
|
40
|
+
await topic.publishMessage({ json: messagePayload });
|
|
41
|
+
|
|
42
|
+
// --- END MODIFICATION ---
|
|
43
|
+
|
|
30
44
|
totalTasksQueued += batch.length;
|
|
31
|
-
logger.log('INFO', `[Module Dispatcher] Dispatched batch ${Math.ceil((i + 1) / batchSize)} with ${batch.length} tasks.`);
|
|
45
|
+
logger.log('INFO', `[Module Dispatcher] Dispatched batch ${Math.ceil((i + 1) / batchSize)} with ${batch.length} tasks as a single message.`);
|
|
32
46
|
|
|
33
47
|
if (i + batchSize < tasks.length) {
|
|
34
48
|
await sleep(batchDelayMs);
|
|
@@ -44,4 +58,4 @@ async function dispatchTasksInBatches(tasks, dependencies, config) {
|
|
|
44
58
|
|
|
45
59
|
module.exports = {
|
|
46
60
|
dispatchTasksInBatches
|
|
47
|
-
};
|
|
61
|
+
};
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* @fileoverview Main pipe for the Task Engine.
|
|
3
3
|
* REFACTORED: This file is now 'handler_creator.js' in name only.
|
|
4
4
|
* It exports the main 'handleRequest' pipe function.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* --- MODIFICATION ---
|
|
7
|
+
* The `handleRequest` function is now designed to receive a *batch*
|
|
8
|
+
* of tasks (e.g., { tasks: [...] }) from the Dispatcher. It loops
|
|
9
|
+
* through all tasks in a single function instance, allowing the
|
|
10
|
+
* FirestoreBatchManager to accumulate state. It then explicitly
|
|
11
|
+
* calls `batchManager.flushBatches()` in the `finally` block
|
|
12
|
+
* to commit all changes.
|
|
7
13
|
*/
|
|
8
14
|
|
|
9
15
|
const { handleDiscover } = require('./helpers/discover_helpers');
|
|
@@ -19,7 +25,7 @@ const { handleUpdate } = require('./helpers/update_helpers');
|
|
|
19
25
|
* @param {object} dependencies - Contains all clients: db, pubsub, logger, headerManager, proxyManager, batchManager.
|
|
20
26
|
*/
|
|
21
27
|
async function handleRequest(message, context, config, dependencies) {
|
|
22
|
-
// ---
|
|
28
|
+
// --- MODIFICATION: Destructure batchManager and headerManager ---
|
|
23
29
|
const { logger, batchManager, headerManager } = dependencies;
|
|
24
30
|
|
|
25
31
|
if (!message || !message.data) {
|
|
@@ -27,51 +33,73 @@ async function handleRequest(message, context, config, dependencies) {
|
|
|
27
33
|
return;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
let
|
|
36
|
+
let payload;
|
|
31
37
|
try {
|
|
32
|
-
|
|
38
|
+
payload = JSON.parse(Buffer.from(message.data, 'base64').toString('utf-8'));
|
|
33
39
|
} catch (e) {
|
|
34
40
|
logger.log('ERROR', '[TaskEngine Module] Failed to parse Pub/Sub message data.', { error: e.message, data: message.data });
|
|
35
41
|
return;
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
// --- START MODIFICATION: Handle Batch Payload ---
|
|
45
|
+
|
|
46
|
+
// Check if this is a batched task payload
|
|
47
|
+
if (!payload.tasks || !Array.isArray(payload.tasks)) {
|
|
48
|
+
logger.log('ERROR', `[TaskEngine] Received invalid payload. Expected { tasks: [...] }`, { payload });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (payload.tasks.length === 0) {
|
|
53
|
+
logger.log('WARN', '[TaskEngine] Received message with an empty tasks array.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const taskId = `batch-${payload.tasks[0]?.type || 'unknown'}-${Date.now()}`;
|
|
58
|
+
logger.log('INFO', `[TaskEngine/${taskId}] Received batch of ${payload.tasks.length} tasks.`);
|
|
40
59
|
|
|
41
60
|
try {
|
|
42
|
-
|
|
61
|
+
// Loop through all tasks in this single function instance
|
|
62
|
+
for (const task of payload.tasks) {
|
|
63
|
+
|
|
64
|
+
// Generate a sub-task ID for logging
|
|
65
|
+
const subTaskId = `${task.type || 'unknown'}-${task.userType || 'unknown'}-${task.userId || task.cids?.[0] || 'sub'}`;
|
|
43
66
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
update: handleUpdate
|
|
50
|
-
}[task.type];
|
|
67
|
+
const handlerFunction = {
|
|
68
|
+
discover: handleDiscover,
|
|
69
|
+
verify: handleVerify,
|
|
70
|
+
update: handleUpdate
|
|
71
|
+
}[task.type];
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
if (handlerFunction) {
|
|
74
|
+
// We await each one sequentially to manage API load,
|
|
75
|
+
// but they all use the *same* batchManager instance.
|
|
76
|
+
await handlerFunction(task, subTaskId, dependencies, config);
|
|
77
|
+
} else {
|
|
78
|
+
logger.log('ERROR', `[TaskEngine/${taskId}] Unknown task type in batch: ${task.type}`);
|
|
79
|
+
}
|
|
58
80
|
}
|
|
81
|
+
|
|
82
|
+
logger.log('SUCCESS', `[TaskEngine/${taskId}] Processed ${payload.tasks.length} tasks. Done.`);
|
|
83
|
+
|
|
59
84
|
} catch (error) {
|
|
60
|
-
logger.log('ERROR', `[TaskEngine/${taskId}] Failed.`, { errorMessage: error.message, errorStack: error.stack });
|
|
85
|
+
logger.log('ERROR', `[TaskEngine/${taskId}] Failed during batch processing.`, { errorMessage: error.message, errorStack: error.stack });
|
|
61
86
|
|
|
62
87
|
} finally {
|
|
63
88
|
try {
|
|
64
|
-
// ---
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
logger.log('INFO', `[TaskEngine/${taskId}]
|
|
70
|
-
|
|
89
|
+
// --- MODIFICATION ---
|
|
90
|
+
// This is the most critical change.
|
|
91
|
+
// After the loop (or if an error occurs), explicitly flush
|
|
92
|
+
// all accumulated writes (portfolios, timestamps, etc.)
|
|
93
|
+
// from the batchManager.
|
|
94
|
+
logger.log('INFO', `[TaskEngine/${taskId}] Flushing all accumulated batches...`);
|
|
95
|
+
await batchManager.flushBatches();
|
|
96
|
+
logger.log('INFO', `[TaskEngine/${taskId}] Final batch and header flush complete.`);
|
|
97
|
+
// --- END MODIFICATION ---
|
|
71
98
|
} catch (flushError) {
|
|
72
99
|
logger.log('ERROR', `[TaskEngine/${taskId}] Error during final flush attempt.`, { error: flushError.message });
|
|
73
100
|
}
|
|
74
101
|
}
|
|
102
|
+
// --- END MODIFICATION ---
|
|
75
103
|
}
|
|
76
104
|
|
|
77
105
|
module.exports = {
|