bulltrackers-module 1.0.766 → 1.0.769
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-v2/UserPortfolioMetrics.js +50 -0
- package/functions/computation-system-v2/computations/BehavioralAnomaly.js +559 -227
- package/functions/computation-system-v2/computations/GlobalAumPerAsset30D.js +103 -0
- package/functions/computation-system-v2/computations/NewSectorExposure.js +82 -35
- package/functions/computation-system-v2/computations/NewSocialPost.js +52 -24
- package/functions/computation-system-v2/computations/PIDailyAssetAUM.js +134 -0
- package/functions/computation-system-v2/computations/PiFeatureVectors.js +227 -0
- package/functions/computation-system-v2/computations/PiRecommender.js +359 -0
- package/functions/computation-system-v2/computations/PopularInvestorProfileMetrics.js +354 -641
- package/functions/computation-system-v2/computations/SignedInUserList.js +51 -0
- package/functions/computation-system-v2/computations/SignedInUserMirrorHistory.js +138 -0
- package/functions/computation-system-v2/computations/SignedInUserPIProfileMetrics.js +106 -0
- package/functions/computation-system-v2/computations/SignedInUserProfileMetrics.js +324 -0
- package/functions/computation-system-v2/config/bulltrackers.config.js +40 -126
- package/functions/computation-system-v2/core-api.js +17 -9
- package/functions/computation-system-v2/data_schema_reference.MD +108 -0
- package/functions/computation-system-v2/devtools/builder/builder.js +362 -0
- package/functions/computation-system-v2/devtools/builder/examples/user-metrics.yaml +26 -0
- package/functions/computation-system-v2/devtools/index.js +36 -0
- package/functions/computation-system-v2/devtools/shared/MockDataFactory.js +235 -0
- package/functions/computation-system-v2/devtools/shared/SchemaTemplates.js +475 -0
- package/functions/computation-system-v2/devtools/shared/SystemIntrospector.js +517 -0
- package/functions/computation-system-v2/devtools/shared/index.js +16 -0
- package/functions/computation-system-v2/devtools/simulation/DAGAnalyzer.js +243 -0
- package/functions/computation-system-v2/devtools/simulation/MockDataFetcher.js +306 -0
- package/functions/computation-system-v2/devtools/simulation/MockStorageManager.js +336 -0
- package/functions/computation-system-v2/devtools/simulation/SimulationEngine.js +525 -0
- package/functions/computation-system-v2/devtools/simulation/SimulationServer.js +581 -0
- package/functions/computation-system-v2/devtools/simulation/index.js +17 -0
- package/functions/computation-system-v2/devtools/simulation/simulate.js +324 -0
- package/functions/computation-system-v2/devtools/vscode-computation/package.json +90 -0
- package/functions/computation-system-v2/devtools/vscode-computation/snippets/computation.json +128 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/extension.ts +401 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/codeActions.ts +152 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/completions.ts +207 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/diagnostics.ts +205 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/hover.ts +205 -0
- package/functions/computation-system-v2/devtools/vscode-computation/tsconfig.json +22 -0
- package/functions/computation-system-v2/docs/HowToCreateComputations.MD +602 -0
- package/functions/computation-system-v2/framework/core/Manifest.js +9 -16
- package/functions/computation-system-v2/framework/core/RunAnalyzer.js +2 -1
- package/functions/computation-system-v2/framework/data/DataFetcher.js +330 -126
- package/functions/computation-system-v2/framework/data/MaterializedViewManager.js +84 -0
- package/functions/computation-system-v2/framework/data/QueryBuilder.js +38 -38
- package/functions/computation-system-v2/framework/execution/Orchestrator.js +226 -153
- package/functions/computation-system-v2/framework/scheduling/ScheduleValidator.js +17 -19
- package/functions/computation-system-v2/framework/storage/StateRepository.js +32 -2
- package/functions/computation-system-v2/framework/storage/StorageManager.js +111 -83
- package/functions/computation-system-v2/framework/testing/ComputationTester.js +161 -66
- package/functions/computation-system-v2/handlers/dispatcher.js +57 -29
- package/functions/computation-system-v2/legacy/PiAssetRecommender.js.old +115 -0
- package/functions/computation-system-v2/legacy/PiSimilarityMatrix.js +104 -0
- package/functions/computation-system-v2/legacy/PiSimilarityVector.js +71 -0
- package/functions/computation-system-v2/scripts/debug_aggregation.js +25 -0
- package/functions/computation-system-v2/scripts/test-computation-dag.js +109 -0
- package/functions/computation-system-v2/scripts/test-invalidation-scenarios.js +234 -0
- package/functions/task-engine/helpers/data_storage_helpers.js +6 -6
- package/package.json +1 -1
- package/functions/computation-system-v2/computations/PopularInvestorRiskAssessment.js +0 -176
- package/functions/computation-system-v2/computations/PopularInvestorRiskMetrics.js +0 -294
- package/functions/computation-system-v2/computations/UserPortfolioSummary.js +0 -172
- package/functions/computation-system-v2/scripts/migrate-sectors.js +0 -73
- package/functions/computation-system-v2/test/analyze-results.js +0 -238
- package/functions/computation-system-v2/test/other/test-dependency-cascade.js +0 -150
- package/functions/computation-system-v2/test/other/test-dispatcher.js +0 -317
- package/functions/computation-system-v2/test/other/test-framework.js +0 -500
- package/functions/computation-system-v2/test/other/test-real-execution.js +0 -166
- package/functions/computation-system-v2/test/other/test-real-integration.js +0 -194
- package/functions/computation-system-v2/test/other/test-refactor-e2e.js +0 -131
- package/functions/computation-system-v2/test/other/test-results.json +0 -31
- package/functions/computation-system-v2/test/other/test-risk-metrics-computation.js +0 -329
- package/functions/computation-system-v2/test/other/test-scheduler.js +0 -204
- package/functions/computation-system-v2/test/other/test-storage.js +0 -449
- package/functions/computation-system-v2/test/run-pipeline-test.js +0 -554
- package/functions/computation-system-v2/test/test-full-pipeline.js +0 -227
- package/functions/computation-system-v2/test/test-worker-pool.js +0 -266
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Test Dispatcher Flow
|
|
3
|
-
*
|
|
4
|
-
* Tests the dispatcher and on-demand API handlers:
|
|
5
|
-
* 1. Schedule validation
|
|
6
|
-
* 2. Dispatcher request handling
|
|
7
|
-
* 3. On-demand request handling
|
|
8
|
-
* 4. Dependency blocking
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const path = require('path');
|
|
12
|
-
|
|
13
|
-
// Use real config
|
|
14
|
-
const config = require('../../config/bulltrackers.config');
|
|
15
|
-
|
|
16
|
-
// Add test computations
|
|
17
|
-
config.computations = [
|
|
18
|
-
require('../../computations/PopularInvestorProfileMetrics'),
|
|
19
|
-
require('../../computations/PopularInvestorRiskAssessment'),
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
// Override config for dispatcher
|
|
23
|
-
const dispatcherModule = require('../../handlers/dispatcher');
|
|
24
|
-
const onDemandModule = require('../../handlers/onDemand');
|
|
25
|
-
const { ManifestBuilder, ScheduleValidator } = require('../../framework');
|
|
26
|
-
|
|
27
|
-
// Mock response object
|
|
28
|
-
function createMockResponse() {
|
|
29
|
-
let statusCode = 200;
|
|
30
|
-
let body = null;
|
|
31
|
-
const headers = {};
|
|
32
|
-
|
|
33
|
-
const mock = {
|
|
34
|
-
set: (key, value) => {
|
|
35
|
-
headers[key] = value;
|
|
36
|
-
return mock;
|
|
37
|
-
},
|
|
38
|
-
status: (code) => {
|
|
39
|
-
statusCode = code;
|
|
40
|
-
return mock;
|
|
41
|
-
},
|
|
42
|
-
json: (data) => {
|
|
43
|
-
body = data;
|
|
44
|
-
return mock;
|
|
45
|
-
},
|
|
46
|
-
send: (data) => {
|
|
47
|
-
body = data;
|
|
48
|
-
return mock;
|
|
49
|
-
},
|
|
50
|
-
getStatus: () => statusCode,
|
|
51
|
-
getBody: () => body,
|
|
52
|
-
getHeaders: () => headers
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return mock;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================================================
|
|
59
|
-
// Test Schedule Validation
|
|
60
|
-
// ============================================================================
|
|
61
|
-
|
|
62
|
-
async function testScheduleValidation() {
|
|
63
|
-
console.log('\n=== Test Schedule Validation ===\n');
|
|
64
|
-
|
|
65
|
-
const validator = new ScheduleValidator(config);
|
|
66
|
-
|
|
67
|
-
// Test parsing
|
|
68
|
-
console.log('Testing schedule parsing...');
|
|
69
|
-
|
|
70
|
-
const schedule1 = validator.parseSchedule(undefined);
|
|
71
|
-
console.log(' Default schedule:', JSON.stringify(schedule1));
|
|
72
|
-
|
|
73
|
-
const schedule2 = validator.parseSchedule({ frequency: 'weekly', time: '06:00', dayOfWeek: 1 });
|
|
74
|
-
console.log(' Weekly Monday 6am:', JSON.stringify(schedule2));
|
|
75
|
-
|
|
76
|
-
// Test cron generation
|
|
77
|
-
console.log('\nTesting cron generation...');
|
|
78
|
-
console.log(' Daily 02:00:', validator.toCron(schedule1));
|
|
79
|
-
console.log(' Weekly Mon 06:00:', validator.toCron(schedule2));
|
|
80
|
-
|
|
81
|
-
// Test gap calculation
|
|
82
|
-
console.log('\nTesting gap calculation...');
|
|
83
|
-
const dep = { frequency: 'daily', time: '14:00' };
|
|
84
|
-
const comp = { frequency: 'daily', time: '14:15' };
|
|
85
|
-
console.log(' Gap between 14:00 and 14:15:', validator.calculateGap(dep, comp), 'minutes');
|
|
86
|
-
|
|
87
|
-
const comp2 = { frequency: 'daily', time: '14:00' };
|
|
88
|
-
console.log(' Gap between 14:00 and 14:00:', validator.calculateGap(dep, comp2), 'minutes');
|
|
89
|
-
|
|
90
|
-
const comp3 = { frequency: 'daily', time: '13:45' };
|
|
91
|
-
console.log(' Gap between 14:00 and 13:45:', validator.calculateGap(dep, comp3), 'minutes (negative!)');
|
|
92
|
-
|
|
93
|
-
console.log('\n✅ Schedule validation tests complete');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// ============================================================================
|
|
97
|
-
// Test Dispatcher
|
|
98
|
-
// ============================================================================
|
|
99
|
-
|
|
100
|
-
async function testDispatcher() {
|
|
101
|
-
console.log('\n=== Test Dispatcher ===\n');
|
|
102
|
-
|
|
103
|
-
// Initialize dispatcher
|
|
104
|
-
await dispatcherModule.initialize();
|
|
105
|
-
|
|
106
|
-
// Test 1: Unknown computation
|
|
107
|
-
console.log('Test 1: Unknown computation...');
|
|
108
|
-
const res1 = createMockResponse();
|
|
109
|
-
await dispatcherModule.dispatcherHandler(
|
|
110
|
-
{ body: { computationName: 'FakeComputation', targetDate: '2026-01-24' } },
|
|
111
|
-
res1
|
|
112
|
-
);
|
|
113
|
-
console.log(' Status:', res1.getStatus());
|
|
114
|
-
console.log(' Body:', JSON.stringify(res1.getBody()));
|
|
115
|
-
console.assert(res1.getStatus() === 400, 'Expected 400 for unknown computation');
|
|
116
|
-
console.assert(res1.getBody().reason === 'UNKNOWN_COMPUTATION', 'Expected UNKNOWN_COMPUTATION reason');
|
|
117
|
-
|
|
118
|
-
// Test 2: Missing computation name
|
|
119
|
-
console.log('\nTest 2: Missing computation name...');
|
|
120
|
-
const res2 = createMockResponse();
|
|
121
|
-
await dispatcherModule.dispatcherHandler(
|
|
122
|
-
{ body: { targetDate: '2026-01-24' } },
|
|
123
|
-
res2
|
|
124
|
-
);
|
|
125
|
-
console.log(' Status:', res2.getStatus());
|
|
126
|
-
console.log(' Body:', JSON.stringify(res2.getBody()));
|
|
127
|
-
console.assert(res2.getStatus() === 400, 'Expected 400 for missing computation');
|
|
128
|
-
|
|
129
|
-
// Test 3: Valid computation (may be blocked or runnable)
|
|
130
|
-
console.log('\nTest 3: Valid computation request...');
|
|
131
|
-
const res3 = createMockResponse();
|
|
132
|
-
await dispatcherModule.dispatcherHandler(
|
|
133
|
-
{ body: { computationName: 'PopularInvestorProfileMetrics', targetDate: '2026-01-24', source: 'scheduled' } },
|
|
134
|
-
res3
|
|
135
|
-
);
|
|
136
|
-
console.log(' Status:', res3.getStatus());
|
|
137
|
-
console.log(' Body:', JSON.stringify(res3.getBody()));
|
|
138
|
-
|
|
139
|
-
// Test 4: Dependent computation without dependency
|
|
140
|
-
console.log('\nTest 4: Dependent computation (may be blocked)...');
|
|
141
|
-
const res4 = createMockResponse();
|
|
142
|
-
await dispatcherModule.dispatcherHandler(
|
|
143
|
-
{ body: { computationName: 'PopularInvestorRiskAssessment', targetDate: '2026-01-20', source: 'scheduled' } },
|
|
144
|
-
res4
|
|
145
|
-
);
|
|
146
|
-
console.log(' Status:', res4.getStatus());
|
|
147
|
-
console.log(' Body:', JSON.stringify(res4.getBody()));
|
|
148
|
-
|
|
149
|
-
// For scheduled tasks, 503 means "retry later" (dependency not ready)
|
|
150
|
-
// For on-demand, 200 with blocked status
|
|
151
|
-
|
|
152
|
-
console.log('\n✅ Dispatcher tests complete');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// ============================================================================
|
|
156
|
-
// Test On-Demand API
|
|
157
|
-
// ============================================================================
|
|
158
|
-
|
|
159
|
-
async function testOnDemand() {
|
|
160
|
-
console.log('\n=== Test On-Demand API ===\n');
|
|
161
|
-
|
|
162
|
-
// Test 1: No auth header
|
|
163
|
-
console.log('Test 1: No auth header...');
|
|
164
|
-
const res1 = createMockResponse();
|
|
165
|
-
await onDemandModule.onDemandHandler(
|
|
166
|
-
{ method: 'POST', headers: {}, body: { computation: 'Test' } },
|
|
167
|
-
res1
|
|
168
|
-
);
|
|
169
|
-
console.log(' Status:', res1.getStatus());
|
|
170
|
-
console.log(' Body:', JSON.stringify(res1.getBody()));
|
|
171
|
-
console.assert(res1.getStatus() === 401, 'Expected 401 for no auth');
|
|
172
|
-
|
|
173
|
-
// Test 2: With mock auth (simple JWT)
|
|
174
|
-
console.log('\nTest 2: With mock auth...');
|
|
175
|
-
// Create a simple mock JWT (header.payload.signature)
|
|
176
|
-
const mockPayload = { sub: 'user123', email: 'test@example.com', user_type: 'POPULAR_INVESTOR' };
|
|
177
|
-
const mockJwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.' +
|
|
178
|
-
Buffer.from(JSON.stringify(mockPayload)).toString('base64') +
|
|
179
|
-
'.mock-signature';
|
|
180
|
-
|
|
181
|
-
const res2 = createMockResponse();
|
|
182
|
-
await onDemandModule.onDemandHandler(
|
|
183
|
-
{
|
|
184
|
-
method: 'POST',
|
|
185
|
-
headers: { authorization: `Bearer ${mockJwt}` },
|
|
186
|
-
body: { computation: 'PopularInvestorProfileMetrics', entityIds: ['user123'] }
|
|
187
|
-
},
|
|
188
|
-
res2
|
|
189
|
-
);
|
|
190
|
-
console.log(' Status:', res2.getStatus());
|
|
191
|
-
console.log(' Body:', JSON.stringify(res2.getBody()));
|
|
192
|
-
|
|
193
|
-
// Test 3: Rate limiting
|
|
194
|
-
console.log('\nTest 3: Rate limiting...');
|
|
195
|
-
const checkRateLimit = onDemandModule._checkRateLimit;
|
|
196
|
-
|
|
197
|
-
// First 5 should succeed
|
|
198
|
-
for (let i = 0; i < 5; i++) {
|
|
199
|
-
const result = checkRateLimit('test-rate-user');
|
|
200
|
-
console.assert(result.allowed === true, `Request ${i + 1} should be allowed`);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// 6th should be blocked
|
|
204
|
-
const blockedResult = checkRateLimit('test-rate-user');
|
|
205
|
-
console.log(' 6th request blocked:', !blockedResult.allowed);
|
|
206
|
-
console.log(' Retry after:', blockedResult.retryAfter, 'seconds');
|
|
207
|
-
console.assert(blockedResult.allowed === false, '6th request should be blocked');
|
|
208
|
-
|
|
209
|
-
// Test 4: Entity access validation
|
|
210
|
-
console.log('\nTest 4: Entity access validation...');
|
|
211
|
-
const validateAccess = onDemandModule._validateEntityAccess;
|
|
212
|
-
|
|
213
|
-
const user = { id: 'user123' };
|
|
214
|
-
|
|
215
|
-
const access1 = validateAccess(user, ['user123']);
|
|
216
|
-
console.log(' Own data access:', access1.allowed);
|
|
217
|
-
console.assert(access1.allowed === true, 'Should allow own data');
|
|
218
|
-
|
|
219
|
-
const access2 = validateAccess(user, ['other-user']);
|
|
220
|
-
console.log(' Other user access:', access2.allowed);
|
|
221
|
-
console.assert(access2.allowed === false, 'Should deny other user data');
|
|
222
|
-
|
|
223
|
-
console.log('\n✅ On-Demand API tests complete');
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// ============================================================================
|
|
227
|
-
// Test Manifest Schedule Integration
|
|
228
|
-
// ============================================================================
|
|
229
|
-
|
|
230
|
-
async function testManifestSchedule() {
|
|
231
|
-
console.log('\n=== Test Manifest Schedule Integration ===\n');
|
|
232
|
-
|
|
233
|
-
// Create test computations with schedules
|
|
234
|
-
class TestComp1 {
|
|
235
|
-
static getConfig() {
|
|
236
|
-
return {
|
|
237
|
-
name: 'TestComp1',
|
|
238
|
-
requires: {},
|
|
239
|
-
dependencies: [],
|
|
240
|
-
schedule: { frequency: 'daily', time: '14:00' }
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
static validateConfig() { return { valid: true }; }
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
class TestComp2 {
|
|
247
|
-
static getConfig() {
|
|
248
|
-
return {
|
|
249
|
-
name: 'TestComp2',
|
|
250
|
-
requires: {},
|
|
251
|
-
dependencies: ['TestComp1'],
|
|
252
|
-
schedule: { frequency: 'daily', time: '14:15' } // Good: 15 min after dep
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
static validateConfig() { return { valid: true }; }
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
class TestComp3 {
|
|
259
|
-
static getConfig() {
|
|
260
|
-
return {
|
|
261
|
-
name: 'TestComp3',
|
|
262
|
-
requires: {},
|
|
263
|
-
dependencies: ['TestComp1'],
|
|
264
|
-
schedule: { frequency: 'daily', time: '14:05' } // Bad: only 5 min after dep
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
static validateConfig() { return { valid: true }; }
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const testConfig = {
|
|
271
|
-
...config,
|
|
272
|
-
scheduling: { dependencyGapMinutes: 15, default: { frequency: 'daily', time: '02:00' } }
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const builder = new ManifestBuilder(testConfig, { log: (l, m) => {
|
|
276
|
-
if (l === 'WARN' || l === 'ERROR') {
|
|
277
|
-
console.log(` [${l}] ${m}`);
|
|
278
|
-
}
|
|
279
|
-
}});
|
|
280
|
-
|
|
281
|
-
console.log('Building manifest with schedule validation...');
|
|
282
|
-
const manifest = builder.build([TestComp1, TestComp2, TestComp3]);
|
|
283
|
-
|
|
284
|
-
console.log('\nManifest entries:');
|
|
285
|
-
for (const entry of manifest) {
|
|
286
|
-
console.log(` - ${entry.originalName}: Pass ${entry.pass}, Schedule: ${JSON.stringify(entry.schedule)}`);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
console.log('\n✅ Manifest schedule integration test complete');
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// ============================================================================
|
|
293
|
-
// Main
|
|
294
|
-
// ============================================================================
|
|
295
|
-
|
|
296
|
-
async function main() {
|
|
297
|
-
console.log('╔════════════════════════════════════════════════════════════╗');
|
|
298
|
-
console.log('║ Computation System v2 - Dispatcher Tests ║');
|
|
299
|
-
console.log('╚════════════════════════════════════════════════════════════╝');
|
|
300
|
-
|
|
301
|
-
try {
|
|
302
|
-
await testScheduleValidation();
|
|
303
|
-
await testManifestSchedule();
|
|
304
|
-
await testDispatcher();
|
|
305
|
-
await testOnDemand();
|
|
306
|
-
|
|
307
|
-
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
|
308
|
-
console.log('║ All Tests Passed! ✅ ║');
|
|
309
|
-
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
|
310
|
-
|
|
311
|
-
} catch (error) {
|
|
312
|
-
console.error('\n❌ Test failed:', error);
|
|
313
|
-
process.exit(1);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
main();
|