bulltrackers-module 1.0.148 → 1.0.150
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.
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Exports the 'createApiApp' main pipe function.
|
|
4
4
|
* REFACTORED: /manifest endpoint now reads static schemas from Firestore.
|
|
5
5
|
* REFACTORED: /manifest/generate endpoint now reads static schema from class.
|
|
6
|
+
*
|
|
7
|
+
* --- MODIFIED: Added in-memory cache wrapper for the main API handler ---
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
const express = require('express');
|
|
@@ -16,6 +18,72 @@ const {
|
|
|
16
18
|
getDynamicSchema // <-- This helper's behavior has changed
|
|
17
19
|
} = require('./helpers/api_helpers.js');
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* --- NEW: In-Memory Cache Handler ---
|
|
23
|
+
* A wrapper function that adds a time-to-live (TTL) in-memory cache
|
|
24
|
+
* to any Express request handler.
|
|
25
|
+
* @param {function} handler - The original (req, res) handler to wrap.
|
|
26
|
+
* @param {object} dependencies - { logger }
|
|
27
|
+
* @returns {function} The new (req, res) handler with caching logic.
|
|
28
|
+
*/
|
|
29
|
+
const createCacheHandler = (handler, { logger }) => {
|
|
30
|
+
// 1. Define the cache *outside* the handler so it persists
|
|
31
|
+
const CACHE = {};
|
|
32
|
+
const CACHE_TTL_MS = 10 * 60 * 1000; // 10 minute cache
|
|
33
|
+
|
|
34
|
+
// 2. Return the new handler
|
|
35
|
+
return async (req, res) => {
|
|
36
|
+
const cacheKey = req.url; // Use the full URL (e.g., "/?computation=foo") as the key
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
|
|
39
|
+
// 3. --- Cache HIT ---
|
|
40
|
+
if (CACHE[cacheKey] && (now - CACHE[cacheKey].timestamp) < CACHE_TTL_MS) {
|
|
41
|
+
logger.log('INFO', `[API] Cache HIT for ${cacheKey}`);
|
|
42
|
+
// Send cached status and data
|
|
43
|
+
return res.status(CACHE[cacheKey].status).send(CACHE[cacheKey].data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 4. --- Cache MISS ---
|
|
47
|
+
logger.log('INFO', `[API] Cache MISS for ${cacheKey}`);
|
|
48
|
+
|
|
49
|
+
// We need to capture the response from the original handler.
|
|
50
|
+
// To do this, we "monkey-patch" res.send and res.status.
|
|
51
|
+
const originalSend = res.send;
|
|
52
|
+
const originalStatus = res.status;
|
|
53
|
+
|
|
54
|
+
let capturedData = null;
|
|
55
|
+
let capturedStatus = 200; // Default
|
|
56
|
+
|
|
57
|
+
// Create a new status function
|
|
58
|
+
res.status = (statusCode) => {
|
|
59
|
+
capturedStatus = statusCode;
|
|
60
|
+
// Call the original status function
|
|
61
|
+
return originalStatus.call(res, statusCode);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Create a new send function
|
|
65
|
+
res.send = (data) => {
|
|
66
|
+
capturedData = data;
|
|
67
|
+
// Call the original send function
|
|
68
|
+
return originalSend.call(res, data);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// 5. Call the original handler (which will now use our patched functions)
|
|
72
|
+
await handler(req, res);
|
|
73
|
+
|
|
74
|
+
// 6. If the response was successful, cache it
|
|
75
|
+
if (capturedStatus === 200 && capturedData) {
|
|
76
|
+
logger.log('INFO', `[API] Caching new entry for ${cacheKey}`);
|
|
77
|
+
CACHE[cacheKey] = {
|
|
78
|
+
data: capturedData,
|
|
79
|
+
status: capturedStatus,
|
|
80
|
+
timestamp: now
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
|
|
19
87
|
/**
|
|
20
88
|
* Main pipe: pipe.api.createApiApp
|
|
21
89
|
* Creates and configures the Express app for the Generic API.
|
|
@@ -36,7 +104,10 @@ function createApiApp(config, dependencies, unifiedCalculations) {
|
|
|
36
104
|
app.use(express.json());
|
|
37
105
|
|
|
38
106
|
// --- Main API Endpoint ---
|
|
39
|
-
|
|
107
|
+
// MODIFIED: We now wrap the original handler with the cache handler.
|
|
108
|
+
const originalApiHandler = createApiHandler(config, dependencies, calcMap);
|
|
109
|
+
const cachedApiHandler = createCacheHandler(originalApiHandler, dependencies);
|
|
110
|
+
app.get('/', cachedApiHandler); // <-- Use the new caching handler
|
|
40
111
|
|
|
41
112
|
// --- Health Check Endpoint ---
|
|
42
113
|
app.get('/health', (req, res) => {
|
|
@@ -168,7 +239,7 @@ function createApiApp(config, dependencies, unifiedCalculations) {
|
|
|
168
239
|
const schemaDoc = await db.collection(schemaCollection).doc(computationName).get();
|
|
169
240
|
|
|
170
241
|
if (!schemaDoc.exists) {
|
|
171
|
-
return res.status(
|
|
242
|
+
return res.status(4404).send({
|
|
172
243
|
status: 'error',
|
|
173
244
|
message: `Schema not found for computation: ${computationName}`,
|
|
174
245
|
hint: 'Try running the computation system or use POST /manifest/generate/:computationName'
|
|
@@ -56,15 +56,18 @@ async function handleUpdate(task, taskId, { logger, headerManager, proxyManager,
|
|
|
56
56
|
|
|
57
57
|
let wasHistorySuccess = false, isPrivate = false;
|
|
58
58
|
|
|
59
|
+
// --- FIX: 'fetchHistory' MUST be declared here, outside the 'try' block ---
|
|
60
|
+
let fetchHistory = false;
|
|
61
|
+
|
|
59
62
|
try {
|
|
60
63
|
// Fetch history ONCE per user
|
|
61
64
|
const promisesToRun = [];
|
|
62
|
-
|
|
65
|
+
// --- 'fetchHistory' is no longer declared here ---
|
|
63
66
|
|
|
64
67
|
if (!historyFetchedForUser.has(userId)) {
|
|
65
68
|
historyHeader = await headerManager.selectHeader();
|
|
66
69
|
if (historyHeader) {
|
|
67
|
-
fetchHistory = true;
|
|
70
|
+
fetchHistory = true; // This now sets the outer variable
|
|
68
71
|
historyFetchedForUser.add(userId);
|
|
69
72
|
const historyUrl = `${config.ETORO_API_USERSTATS_URL}${username}/trades/oneYearAgo?CopyAsAsset=true`;
|
|
70
73
|
promisesToRun.push(proxyManager.fetch(historyUrl, { headers: historyHeader.header }));
|