bulltrackers-module 1.0.739 → 1.0.740
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.
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core System API
|
|
3
|
+
* Contains the business logic and orchestrator management.
|
|
4
|
+
* Separated from index.js to prevent circular dependencies with handlers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Orchestrator } = require('./framework');
|
|
8
|
+
const config = require('./config/bulltrackers.config');
|
|
9
|
+
const { ManifestBuilder } = require('./framework/core/Manifest');
|
|
10
|
+
const { Computation } = require('./framework/core/Computation');
|
|
11
|
+
|
|
12
|
+
// Add computations to config
|
|
13
|
+
config.computations = [
|
|
14
|
+
require('./computations/UserPortfolioSummary'),
|
|
15
|
+
require('./computations/PopularInvestorProfileMetrics'),
|
|
16
|
+
require('./computations/PopularInvestorRiskAssessment'),
|
|
17
|
+
require('./computations/PopularInvestorRiskMetrics'),
|
|
18
|
+
// Add more computations here as they're migrated
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Singleton orchestrator instance
|
|
22
|
+
let orchestrator = null;
|
|
23
|
+
|
|
24
|
+
async function getOrchestrator(customConfig = null, logger = null) {
|
|
25
|
+
if (!orchestrator || customConfig) {
|
|
26
|
+
const cfg = customConfig || config;
|
|
27
|
+
orchestrator = new Orchestrator(cfg, logger);
|
|
28
|
+
}
|
|
29
|
+
return orchestrator;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function analyze(options) {
|
|
33
|
+
const { date, config: customConfig = null, logger = null } = options;
|
|
34
|
+
const orch = await getOrchestrator(customConfig, logger);
|
|
35
|
+
return orch.analyze({ date });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function execute(options) {
|
|
39
|
+
const { date, pass = null, computation = null, dryRun = false, entities = null, config: customConfig = null, logger = null } = options;
|
|
40
|
+
const orch = await getOrchestrator(customConfig, logger);
|
|
41
|
+
return orch.execute({ date, pass, computation, dryRun, entities });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function runComputation(options) {
|
|
45
|
+
const { date, computation, entityIds = null, dryRun = false, force = false, useWorkerPool, config: customConfig = null, logger = null } = options;
|
|
46
|
+
const orch = await getOrchestrator(customConfig, logger);
|
|
47
|
+
|
|
48
|
+
if (!orch.manifest) await orch.initialize();
|
|
49
|
+
|
|
50
|
+
const normalizedName = computation.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
51
|
+
const entry = orch.manifest.find(c => c.name === normalizedName);
|
|
52
|
+
|
|
53
|
+
if (!entry) throw new Error(`Computation not found: ${computation}`);
|
|
54
|
+
|
|
55
|
+
return orch.runSingle(entry, date, { entityIds, dryRun, force, useWorkerPool });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function getManifest(options = {}) {
|
|
59
|
+
const { config: customConfig = null, logger = null } = options;
|
|
60
|
+
const orch = await getOrchestrator(customConfig, logger);
|
|
61
|
+
if (!orch.manifest) await orch.initialize();
|
|
62
|
+
return orch.manifest;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function warmCache(options = {}) {
|
|
66
|
+
const { config: customConfig = null, logger = null } = options;
|
|
67
|
+
const orch = await getOrchestrator(customConfig, logger);
|
|
68
|
+
const allTables = Object.keys(orch.config.tables);
|
|
69
|
+
return orch.schemaRegistry.warmCache(allTables);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function reset() {
|
|
73
|
+
orchestrator = null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
analyze,
|
|
78
|
+
execute,
|
|
79
|
+
runComputation,
|
|
80
|
+
getManifest,
|
|
81
|
+
warmCache,
|
|
82
|
+
reset,
|
|
83
|
+
getOrchestrator,
|
|
84
|
+
config,
|
|
85
|
+
ManifestBuilder,
|
|
86
|
+
Computation,
|
|
87
|
+
...require('./framework')
|
|
88
|
+
};
|
|
@@ -1,9 +1,35 @@
|
|
|
1
|
+
Here is the updated `admin.md` file. I have replaced the hardcoded placeholder URL with a dynamic variable (`$FUNCTION_URL`) and corrected the token generation command to remove the invalid `--audiences` flag.
|
|
2
|
+
|
|
3
|
+
This version is copy-paste ready for your terminal.
|
|
4
|
+
|
|
5
|
+
### `computation-system-v2/docs/admin.md`
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
1
8
|
# Admin Test Endpoint
|
|
2
9
|
|
|
3
10
|
## Deploy
|
|
4
11
|
|
|
5
12
|
```bash
|
|
6
13
|
node deploy.mjs ComputeAdminTest
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Setup (Run Before Testing)
|
|
18
|
+
|
|
19
|
+
First, retrieve your function's actual URL and generate an authentication token.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 1. Get the Function URL dynamically
|
|
23
|
+
# (Adjust region if not in europe-west1)
|
|
24
|
+
FUNCTION_URL=$(gcloud functions describe compute-admin-test \
|
|
25
|
+
--region=europe-west1 \
|
|
26
|
+
--format="value(serviceConfig.uri)")
|
|
27
|
+
|
|
28
|
+
# 2. Generate an Identity Token (Standard User account)
|
|
29
|
+
TOKEN=$(gcloud auth print-identity-token)
|
|
30
|
+
|
|
31
|
+
echo "Targeting: $FUNCTION_URL"
|
|
32
|
+
|
|
7
33
|
```
|
|
8
34
|
|
|
9
35
|
## Usage Examples
|
|
@@ -11,81 +37,81 @@ node deploy.mjs ComputeAdminTest
|
|
|
11
37
|
### 1. Check System Status
|
|
12
38
|
|
|
13
39
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
curl -X POST \
|
|
17
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
40
|
+
curl -X POST "$FUNCTION_URL" \
|
|
18
41
|
-H "Authorization: Bearer $TOKEN" \
|
|
19
42
|
-H "Content-Type: application/json" \
|
|
20
43
|
-d '{"action": "status"}'
|
|
44
|
+
|
|
21
45
|
```
|
|
22
46
|
|
|
23
47
|
### 2. Analyze What Would Run
|
|
24
48
|
|
|
25
49
|
```bash
|
|
26
|
-
curl -X POST \
|
|
27
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
50
|
+
curl -X POST "$FUNCTION_URL" \
|
|
28
51
|
-H "Authorization: Bearer $TOKEN" \
|
|
29
52
|
-H "Content-Type: application/json" \
|
|
30
53
|
-d '{"action": "analyze", "date": "2026-01-25"}'
|
|
54
|
+
|
|
31
55
|
```
|
|
32
56
|
|
|
33
57
|
### 3. Run Full Computation
|
|
34
58
|
|
|
35
59
|
```bash
|
|
36
|
-
curl -X POST \
|
|
37
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
60
|
+
curl -X POST "$FUNCTION_URL" \
|
|
38
61
|
-H "Authorization: Bearer $TOKEN" \
|
|
39
62
|
-H "Content-Type: application/json" \
|
|
40
63
|
-d '{"action": "run", "computation": "UserPortfolioSummary", "date": "2026-01-25", "force": true}'
|
|
64
|
+
|
|
41
65
|
```
|
|
42
66
|
|
|
43
67
|
### 4. Run Limited Test
|
|
44
68
|
|
|
45
69
|
```bash
|
|
46
|
-
curl -X POST \
|
|
47
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
70
|
+
curl -X POST "$FUNCTION_URL" \
|
|
48
71
|
-H "Authorization: Bearer $TOKEN" \
|
|
49
72
|
-H "Content-Type: application/json" \
|
|
50
73
|
-d '{"action": "run_limited", "computation": "UserPortfolioSummary", "date": "2026-01-25", "limit": 5}'
|
|
74
|
+
|
|
51
75
|
```
|
|
52
76
|
|
|
53
77
|
### 5. Test Specific Entities
|
|
54
78
|
|
|
55
79
|
```bash
|
|
56
|
-
curl -X POST \
|
|
57
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
80
|
+
curl -X POST "$FUNCTION_URL" \
|
|
58
81
|
-H "Authorization: Bearer $TOKEN" \
|
|
59
82
|
-H "Content-Type: application/json" \
|
|
60
83
|
-d '{"action": "run", "computation": "UserPortfolioSummary", "date": "2026-01-25", "entityIds": ["user-123", "user-456"], "force": true}'
|
|
84
|
+
|
|
61
85
|
```
|
|
62
86
|
|
|
63
87
|
### 6. Test Worker Directly
|
|
64
88
|
|
|
65
89
|
```bash
|
|
66
|
-
curl -X POST \
|
|
67
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
90
|
+
curl -X POST "$FUNCTION_URL" \
|
|
68
91
|
-H "Authorization: Bearer $TOKEN" \
|
|
69
92
|
-H "Content-Type: application/json" \
|
|
70
93
|
-d '{"action": "test_worker", "computation": "UserPortfolioSummary", "date": "2026-01-25", "entityIds": ["user-123"]}'
|
|
94
|
+
|
|
71
95
|
```
|
|
72
96
|
|
|
73
97
|
### 7. Test with Worker Pool Override
|
|
74
98
|
|
|
75
99
|
```bash
|
|
76
|
-
curl -X POST \
|
|
77
|
-
"https://europe-west1-stocks-12345.cloudfunctions.net/compute-admin-test" \
|
|
100
|
+
curl -X POST "$FUNCTION_URL" \
|
|
78
101
|
-H "Authorization: Bearer $TOKEN" \
|
|
79
102
|
-H "Content-Type: application/json" \
|
|
80
103
|
-d '{"action": "run", "computation": "UserPortfolioSummary", "date": "2026-01-25", "useWorkerPool": true, "force": true}'
|
|
104
|
+
|
|
81
105
|
```
|
|
82
106
|
|
|
83
107
|
## Available Actions
|
|
84
108
|
|
|
85
109
|
| Action | Description |
|
|
86
|
-
|
|
110
|
+
| --- | --- |
|
|
87
111
|
| `status` | List all computations and system status |
|
|
88
112
|
| `analyze` | Check what would run for a given date |
|
|
89
113
|
| `run` | Execute a full computation |
|
|
90
114
|
| `run_limited` | Execute on N random entities (safer for testing) |
|
|
91
|
-
| `test_worker` | Direct test of worker function logic |
|
|
115
|
+
| `test_worker` | Direct test of worker function logic |
|
|
116
|
+
|
|
117
|
+
```
|
|
@@ -1,184 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Computation System v2 Entry Point
|
|
3
|
-
*
|
|
4
|
-
* const { execute, analyze, runComputation } = require('./computation-system-v2');
|
|
5
|
-
* * // Analyze what can run
|
|
6
|
-
* const report = await analyze({ date: '2026-01-24' });
|
|
7
|
-
* * // Execute computations (Monolith/Scheduler mode)
|
|
8
|
-
* const result = await execute({ date: '2026-01-24' });
|
|
9
|
-
* * // Run single computation (Worker mode)
|
|
10
|
-
* const task = await runComputation({
|
|
11
|
-
* date: '2026-01-24',
|
|
12
|
-
* computation: 'UserPortfolioSummary'
|
|
13
|
-
* });
|
|
3
|
+
* Exports both the Core API and the Cloud Function Handlers.
|
|
14
4
|
*/
|
|
15
5
|
|
|
16
|
-
const
|
|
17
|
-
const config = require('./config/bulltrackers.config');
|
|
18
|
-
const { ManifestBuilder } = require('./framework/core/Manifest');
|
|
19
|
-
const { Computation } = require('./framework/core/Computation');
|
|
20
|
-
|
|
21
|
-
// Add computations to config
|
|
22
|
-
// These are loaded from computation-system-v2/computations folder
|
|
23
|
-
config.computations = [
|
|
24
|
-
require('./computations/UserPortfolioSummary'),
|
|
25
|
-
require('./computations/PopularInvestorProfileMetrics'),
|
|
26
|
-
require('./computations/PopularInvestorRiskAssessment'),
|
|
27
|
-
require('./computations/PopularInvestorRiskMetrics'),
|
|
28
|
-
// Add more computations here as they're migrated
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
// Singleton orchestrator instance
|
|
32
|
-
let orchestrator = null;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get or create the orchestrator instance.
|
|
36
|
-
* @param {Object} [customConfig] - Override default config
|
|
37
|
-
* @param {Object} [logger] - Custom logger
|
|
38
|
-
* @returns {Promise<Orchestrator>}
|
|
39
|
-
*/
|
|
40
|
-
async function getOrchestrator(customConfig = null, logger = null) {
|
|
41
|
-
if (!orchestrator || customConfig) {
|
|
42
|
-
const cfg = customConfig || config;
|
|
43
|
-
orchestrator = new Orchestrator(cfg, logger);
|
|
44
|
-
// Note: Orchestrator initializes lazily on first execute/analyze call,
|
|
45
|
-
// but we can force it here if needed.
|
|
46
|
-
}
|
|
47
|
-
return orchestrator;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Analyze what can run for a given date.
|
|
52
|
-
* @param {Object} options
|
|
53
|
-
* @param {string} options.date - Target date (YYYY-MM-DD)
|
|
54
|
-
* @param {Object} [options.config] - Override config
|
|
55
|
-
* @param {Object} [options.logger] - Custom logger
|
|
56
|
-
* @returns {Promise<Object>} Analysis report
|
|
57
|
-
*/
|
|
58
|
-
async function analyze(options) {
|
|
59
|
-
const { date, config: customConfig = null, logger = null } = options;
|
|
60
|
-
const orch = await getOrchestrator(customConfig, logger);
|
|
61
|
-
return orch.analyze({ date });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Execute computations for a given date.
|
|
66
|
-
* (Used by Scheduler or Monolithic runs)
|
|
67
|
-
*/
|
|
68
|
-
async function execute(options) {
|
|
69
|
-
const {
|
|
70
|
-
date,
|
|
71
|
-
pass = null,
|
|
72
|
-
computation = null,
|
|
73
|
-
dryRun = false,
|
|
74
|
-
entities = null,
|
|
75
|
-
config: customConfig = null,
|
|
76
|
-
logger = null
|
|
77
|
-
} = options;
|
|
78
|
-
|
|
79
|
-
const orch = await getOrchestrator(customConfig, logger);
|
|
80
|
-
return orch.execute({ date, pass, computation, dryRun, entities });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* WORKER ENTRY POINT: Run a single computation.
|
|
85
|
-
* (Used by Cloud Functions / Dispatcher)
|
|
86
|
-
*
|
|
87
|
-
* @param {Object} options
|
|
88
|
-
* @param {string} options.date - Target date (YYYY-MM-DD)
|
|
89
|
-
* @param {string} options.computation - Computation name
|
|
90
|
-
* @param {string[]} [options.entityIds] - Specific entities to run (null = all)
|
|
91
|
-
* @param {boolean} [options.dryRun] - If true, don't persist results
|
|
92
|
-
* @param {boolean} [options.force] - If true, bypass up-to-date checks
|
|
93
|
-
* @param {boolean} [options.useWorkerPool] - Override worker pool setting (undefined = use config)
|
|
94
|
-
* @param {Object} [options.config] - Override config
|
|
95
|
-
* @param {Object} [options.logger] - Custom logger
|
|
96
|
-
*/
|
|
97
|
-
async function runComputation(options) {
|
|
98
|
-
const {
|
|
99
|
-
date,
|
|
100
|
-
computation,
|
|
101
|
-
entityIds = null,
|
|
102
|
-
dryRun = false,
|
|
103
|
-
force = false,
|
|
104
|
-
useWorkerPool, // Runtime override for worker pool
|
|
105
|
-
config: customConfig = null,
|
|
106
|
-
logger = null
|
|
107
|
-
} = options;
|
|
108
|
-
|
|
109
|
-
const orch = await getOrchestrator(customConfig, logger);
|
|
110
|
-
|
|
111
|
-
// 1. Ensure manifest is built
|
|
112
|
-
if (!orch.manifest) await orch.initialize();
|
|
113
|
-
|
|
114
|
-
// 2. Find the specific entry
|
|
115
|
-
// We normalize to handle case-insensitivity
|
|
116
|
-
const normalizedName = computation.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
117
|
-
const entry = orch.manifest.find(c => c.name === normalizedName);
|
|
118
|
-
|
|
119
|
-
if (!entry) {
|
|
120
|
-
throw new Error(`Computation not found: ${computation}`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// 3. Delegate to Orchestrator's runSingle
|
|
124
|
-
// This handles dependencies, data fetching, middleware, etc.
|
|
125
|
-
return orch.runSingle(entry, date, {
|
|
126
|
-
entityIds,
|
|
127
|
-
dryRun,
|
|
128
|
-
force,
|
|
129
|
-
useWorkerPool // Pass override to Orchestrator
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Get the manifest (list of all computations with metadata).
|
|
135
|
-
*/
|
|
136
|
-
async function getManifest(options = {}) {
|
|
137
|
-
const { config: customConfig = null, logger = null } = options;
|
|
138
|
-
const orch = await getOrchestrator(customConfig, logger);
|
|
139
|
-
if (!orch.manifest) await orch.initialize();
|
|
140
|
-
return orch.manifest;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Warm the schema cache for all tables.
|
|
145
|
-
*/
|
|
146
|
-
async function warmCache(options = {}) {
|
|
147
|
-
const { config: customConfig = null, logger = null } = options;
|
|
148
|
-
const orch = await getOrchestrator(customConfig, logger);
|
|
149
|
-
const allTables = Object.keys(orch.config.tables);
|
|
150
|
-
return orch.schemaRegistry.warmCache(allTables);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Reset the singleton (useful for testing).
|
|
155
|
-
*/
|
|
156
|
-
function reset() {
|
|
157
|
-
orchestrator = null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Import handlers for Cloud Functions
|
|
6
|
+
const coreApi = require('./core-api');
|
|
161
7
|
const handlers = require('./handlers');
|
|
162
8
|
|
|
163
9
|
module.exports = {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
execute,
|
|
167
|
-
ManifestBuilder,
|
|
168
|
-
Computation,
|
|
169
|
-
|
|
170
|
-
runComputation, // <--- New Method
|
|
171
|
-
getManifest,
|
|
172
|
-
warmCache,
|
|
173
|
-
reset,
|
|
174
|
-
|
|
175
|
-
// For advanced usage
|
|
176
|
-
getOrchestrator,
|
|
177
|
-
config,
|
|
178
|
-
|
|
179
|
-
// Cloud Function handlers
|
|
180
|
-
...handlers,
|
|
181
|
-
|
|
182
|
-
// Re-export framework components
|
|
183
|
-
...require('./framework')
|
|
10
|
+
...coreApi,
|
|
11
|
+
...handlers
|
|
184
12
|
};
|