bulltrackers-module 1.0.731 → 1.0.732
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,8 +3,10 @@
|
|
|
3
3
|
* UPDATED: Injects verification and rankings data into context globally and locally.
|
|
4
4
|
* UPDATED: Added support for historical ranking data in both Standard and Meta contexts.
|
|
5
5
|
* UPDATED: Added support for 'series' data (historical root data or computation results) in Global Data.
|
|
6
|
+
* UPDATED: Added 'utils.fetchLatest' to support on-demand BigQuery fallback.
|
|
6
7
|
*/
|
|
7
8
|
const mathLayer = require('../layers/index');
|
|
9
|
+
const DataLoader = require('../utils/data_loader'); // [NEW] Import DataLoader
|
|
8
10
|
const { LEGACY_MAPPING } = require('../topology/HashManager');
|
|
9
11
|
|
|
10
12
|
class ContextFactory {
|
|
@@ -67,6 +69,14 @@ class ContextFactory {
|
|
|
67
69
|
computed: computedDependencies || {},
|
|
68
70
|
previousComputed: previousComputedDependencies || {},
|
|
69
71
|
meta: metadata, config, deps,
|
|
72
|
+
|
|
73
|
+
// [NEW] UTILS FOR ON-DEMAND FETCHING
|
|
74
|
+
utils: {
|
|
75
|
+
fetchLatest: async (rootType, lookbackDays) => {
|
|
76
|
+
return DataLoader.fetchLatestRootData(config, deps, rootType, userId, userType, lookbackDays);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
70
80
|
globalData: {
|
|
71
81
|
rankings: allRankings || [],
|
|
72
82
|
rankingsYesterday: allRankingsYesterday || [],
|
|
@@ -82,6 +92,7 @@ class ContextFactory {
|
|
|
82
92
|
}
|
|
83
93
|
|
|
84
94
|
static buildMetaContext(options) {
|
|
95
|
+
// ... (No changes needed for MetaContext yet)
|
|
85
96
|
const {
|
|
86
97
|
dateStr,
|
|
87
98
|
metadata,
|
|
@@ -123,7 +134,7 @@ class ContextFactory {
|
|
|
123
134
|
watchlistMembership: watchlistMembership || {},
|
|
124
135
|
alertHistory: alertHistory || {},
|
|
125
136
|
series: seriesData || {},
|
|
126
|
-
piMasterList: piMasterList || {}
|
|
137
|
+
piMasterList: piMasterList || {}
|
|
127
138
|
}
|
|
128
139
|
};
|
|
129
140
|
}
|
|
@@ -25,6 +25,84 @@ const {
|
|
|
25
25
|
} = require('../../core/utils/bigquery_utils');
|
|
26
26
|
|
|
27
27
|
const { normalizeName } = require('./utils');
|
|
28
|
+
const { BigQuery } = require('@google-cloud/bigquery'); // [NEW] Import BigQuery Client
|
|
29
|
+
|
|
30
|
+
// [NEW] Map root types to likely BQ tables (Configuration should ideally override this)
|
|
31
|
+
const ROOT_TABLE_MAP = {
|
|
32
|
+
portfolio: 'data-platform.feature_store.portfolios',
|
|
33
|
+
history: 'data-platform.feature_store.trade_history'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const bigquery = new BigQuery();
|
|
37
|
+
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// [NEW] ON-DEMAND LATEST DATA FETCHER
|
|
40
|
+
// =============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Fetches the latest available root data for a specific user from BigQuery.
|
|
43
|
+
* Used as a fallback when 'today's' data is missing due to outages.
|
|
44
|
+
* @param {object} config - System config
|
|
45
|
+
* @param {object} deps - Dependencies
|
|
46
|
+
* @param {string} rootType - 'portfolio' or 'history'
|
|
47
|
+
* @param {string} userId - The user ID (CID)
|
|
48
|
+
* @param {string} userType - The user type (e.g. POPULAR_INVESTOR)
|
|
49
|
+
* @param {number} lookbackDays - How far back to search (default 7)
|
|
50
|
+
*/
|
|
51
|
+
exports.fetchLatestRootData = async (config, deps, rootType, userId, userType, lookbackDays = 7) => {
|
|
52
|
+
const { logger } = deps;
|
|
53
|
+
const tableName = config.bigQuery?.tables?.[rootType] || ROOT_TABLE_MAP[rootType];
|
|
54
|
+
|
|
55
|
+
if (!tableName) {
|
|
56
|
+
logger.log('WARN', `[DataLoader] No BigQuery table mapped for rootType '${rootType}'`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// Construct Dynamic Query to get the Last Available Record
|
|
62
|
+
// Assumes schema: CustomerId, Date, UserType, and a payload column (e.g. PortfolioData/HistoryData)
|
|
63
|
+
// We select * to get the payload wrapper.
|
|
64
|
+
const query = `
|
|
65
|
+
SELECT *
|
|
66
|
+
FROM \`${tableName}\`
|
|
67
|
+
WHERE CustomerId = @userId
|
|
68
|
+
AND Date >= DATE_SUB(CURRENT_DATE(), INTERVAL @lookbackDays DAY)
|
|
69
|
+
ORDER BY Date DESC
|
|
70
|
+
LIMIT 1
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
const options = {
|
|
74
|
+
query: query,
|
|
75
|
+
params: { userId: String(userId), lookbackDays: lookbackDays }
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const [rows] = await bigquery.query(options);
|
|
79
|
+
|
|
80
|
+
if (rows && rows.length > 0) {
|
|
81
|
+
const record = rows[0];
|
|
82
|
+
const dateFound = record.Date ? record.Date.value || record.Date : 'unknown';
|
|
83
|
+
logger.log('INFO', `[DataLoader] 🔄 Fetched LATEST ${rootType} for ${userId} from ${dateFound}`);
|
|
84
|
+
|
|
85
|
+
// Normalize result to match stream format
|
|
86
|
+
// Assumes the payload is either the whole row or nested in a specific column like 'portfolio_data'
|
|
87
|
+
// We return the payload with _userType injected.
|
|
88
|
+
let payload = record;
|
|
89
|
+
if (rootType === 'portfolio' && record.portfolio_data) payload = record.portfolio_data;
|
|
90
|
+
if (rootType === 'history' && record.history_data) payload = record.history_data;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
...payload,
|
|
94
|
+
_userType: userType || record.UserType,
|
|
95
|
+
_isFallback: true,
|
|
96
|
+
_fetchedAt: new Date().toISOString()
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return null;
|
|
101
|
+
} catch (e) {
|
|
102
|
+
logger.log('ERROR', `[DataLoader] Failed to fetch latest ${rootType} for ${userId}: ${e.message}`);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
28
106
|
|
|
29
107
|
// =============================================================================
|
|
30
108
|
// 1. PORTFOLIOS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bulltrackers-module",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.732",
|
|
4
4
|
"description": "Helper Functions for Bulltrackers.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -38,24 +38,25 @@
|
|
|
38
38
|
"finance"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@google-cloud/bigquery": "^7.9.4",
|
|
41
42
|
"@google-cloud/firestore": "^7.11.3",
|
|
42
43
|
"@google-cloud/monitoring": "latest",
|
|
43
44
|
"@google-cloud/pubsub": "latest",
|
|
45
|
+
"@google-cloud/storage": "^7.18.0",
|
|
46
|
+
"@google-cloud/tasks": "^5.0.0",
|
|
44
47
|
"aiden-shared-calculations-unified": "^1.0.110",
|
|
45
48
|
"cors": "^2.8.5",
|
|
46
49
|
"dotenv": "latest",
|
|
47
50
|
"express": "^4.19.2",
|
|
48
51
|
"express-rate-limit": "^8.2.1",
|
|
52
|
+
"firebase-admin": "^13.6.0",
|
|
49
53
|
"google-auth-library": "^10.5.0",
|
|
50
54
|
"graphviz": "latest",
|
|
51
55
|
"node-graphviz": "^0.1.1",
|
|
52
56
|
"p-limit": "^3.1.0",
|
|
53
57
|
"require-all": "^3.0.0",
|
|
54
58
|
"sharedsetup": "latest",
|
|
55
|
-
"zod": "^4.3.5"
|
|
56
|
-
"@google-cloud/storage": "^7.18.0",
|
|
57
|
-
"@google-cloud/bigquery": "^7.3.0",
|
|
58
|
-
"@google-cloud/tasks": "^5.0.0"
|
|
59
|
+
"zod": "^4.3.5"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"bulltracker-deployer": "file:../bulltracker-deployer"
|