@yuants/app-virtual-exchange 0.18.5 → 0.18.7
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/dist/app-virtual-exchange.d.ts +1 -0
- package/dist/credential.js.map +1 -1
- package/dist/legacy-services.js.map +1 -1
- package/dist/position.js.map +1 -1
- package/dist/quote/__tests__/implementations.test.js +1 -1
- package/dist/quote/__tests__/implementations.test.js.map +1 -1
- package/dist/quote/benchmark/ForkedQuoteStateComparisonTest.js.map +1 -1
- package/dist/quote/benchmark/PerformanceTester.js.map +1 -1
- package/dist/quote/benchmark/QuoteStateComparisonTest.js.map +1 -1
- package/dist/quote/benchmark/QuoteStateTestRunner.js.map +1 -1
- package/dist/quote/benchmark/index.js.map +1 -1
- package/dist/quote/benchmark/test-helpers.js.map +1 -1
- package/dist/quote/benchmark/worker.js.map +1 -1
- package/dist/quote/implementations/v0.js.map +1 -1
- package/dist/quote/implementations/v1.js.map +1 -1
- package/dist/quote/implementations/v2.js.map +1 -1
- package/dist/quote/implementations/v3.js +1 -1
- package/dist/quote/implementations/v3.js.map +1 -1
- package/dist/quote/scheduler.js.map +1 -1
- package/dist/quote/service.js.map +1 -1
- package/dist/quote/state.benchmark.js.map +1 -1
- package/dist/series-collector/backwards-interest-rate.js.map +1 -1
- package/dist/series-collector/backwards-ohlc.js.map +1 -1
- package/dist/series-collector/discovery.js.map +1 -1
- package/dist/series-collector/forwards-interest-rate.js.map +1 -1
- package/dist/series-collector/forwards-ohlc.js.map +1 -1
- package/dist/series-collector/patch-interest-rate.js.map +1 -1
- package/dist/series-collector/patch-ohlc.js.map +1 -1
- package/dist/series-collector/setup.js.map +1 -1
- package/dist/series-data/fifo-queue.js.map +1 -1
- package/dist/series-data/scheduler.js.map +1 -1
- package/lib/credential.d.ts.map +1 -1
- package/lib/credential.js.map +1 -1
- package/lib/legacy-services.js.map +1 -1
- package/lib/position.d.ts.map +1 -1
- package/lib/position.js.map +1 -1
- package/lib/quote/__tests__/implementations.test.js +1 -1
- package/lib/quote/__tests__/implementations.test.js.map +1 -1
- package/lib/quote/benchmark/ForkedQuoteStateComparisonTest.js.map +1 -1
- package/lib/quote/benchmark/PerformanceTester.d.ts +0 -1
- package/lib/quote/benchmark/PerformanceTester.d.ts.map +1 -1
- package/lib/quote/benchmark/PerformanceTester.js.map +1 -1
- package/lib/quote/benchmark/QuoteStateComparisonTest.js.map +1 -1
- package/lib/quote/benchmark/QuoteStateTestRunner.js.map +1 -1
- package/lib/quote/benchmark/index.js +2 -2
- package/lib/quote/benchmark/index.js.map +1 -1
- package/lib/quote/benchmark/test-helpers.js +4 -5
- package/lib/quote/benchmark/test-helpers.js.map +1 -1
- package/lib/quote/benchmark/worker.js.map +1 -1
- package/lib/quote/implementations/v0.js +1 -2
- package/lib/quote/implementations/v0.js.map +1 -1
- package/lib/quote/implementations/v1.js.map +1 -1
- package/lib/quote/implementations/v2.js.map +1 -1
- package/lib/quote/implementations/v3.js +1 -1
- package/lib/quote/implementations/v3.js.map +1 -1
- package/lib/quote/scheduler.d.ts.map +1 -1
- package/lib/quote/scheduler.js.map +1 -1
- package/lib/quote/service.js.map +1 -1
- package/lib/quote/state.benchmark.js.map +1 -1
- package/lib/quote/types.d.ts +2 -2
- package/lib/quote/types.d.ts.map +1 -1
- package/lib/series-collector/backwards-interest-rate.d.ts +1 -2
- package/lib/series-collector/backwards-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/backwards-interest-rate.js.map +1 -1
- package/lib/series-collector/backwards-ohlc.d.ts +1 -2
- package/lib/series-collector/backwards-ohlc.d.ts.map +1 -1
- package/lib/series-collector/backwards-ohlc.js.map +1 -1
- package/lib/series-collector/discovery.js.map +1 -1
- package/lib/series-collector/forwards-interest-rate.d.ts +1 -2
- package/lib/series-collector/forwards-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/forwards-interest-rate.js.map +1 -1
- package/lib/series-collector/forwards-ohlc.d.ts +1 -2
- package/lib/series-collector/forwards-ohlc.d.ts.map +1 -1
- package/lib/series-collector/forwards-ohlc.js.map +1 -1
- package/lib/series-collector/patch-interest-rate.d.ts +1 -2
- package/lib/series-collector/patch-interest-rate.d.ts.map +1 -1
- package/lib/series-collector/patch-interest-rate.js.map +1 -1
- package/lib/series-collector/patch-ohlc.d.ts +1 -2
- package/lib/series-collector/patch-ohlc.d.ts.map +1 -1
- package/lib/series-collector/patch-ohlc.js.map +1 -1
- package/lib/series-collector/setup.js.map +1 -1
- package/lib/series-collector/sql-helpers.d.ts.map +1 -1
- package/lib/series-data/fifo-queue.d.ts.map +1 -1
- package/lib/series-data/fifo-queue.js.map +1 -1
- package/lib/series-data/scheduler.js.map +1 -1
- package/lib/tsdoc-metadata.json +11 -0
- package/package.json +42 -42
- package/temp/app-virtual-exchange.api.json +193 -0
- package/temp/app-virtual-exchange.api.md +9 -0
- package/temp/build/typescript/ts_KjrfbUqK.json +1 -0
- package/temp/test/jest/haste-map-76b16e3ab892e2fd05068740b7223d57-a6c52f003baf5bf33cffc52364f3bd7a-4ce9ff2cd20d69bbaecd1543c7e32e02 +0 -0
- package/temp/test/jest/perf-cache-76b16e3ab892e2fd05068740b7223d57-da39a3ee5e6b4b0d3255bfef95601890 +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/quote/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,gBAAgB,GAAG,CAAC,MAAgB,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3E,MAAM,eAAe,GAAG,CAAC,MAAmB,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAE7E,MAAM,sBAAsB,GAAG,CAC7B,UAAuB,EACvB,WAAqB,EACrB,MAAmB,EACnB,UAAkB,EACe,EAAE;IACnC,MAAM,UAAU,GAAoB,EAAE,CAAC;IACvC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/quote/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Terminal } from '@yuants/protocol';\nimport { IQuoteField } from '@yuants/exchange';\nimport { quoteState } from './state';\nimport { IQuoteKey, IQuoteRequire, IQuoteState, IQuoteUpdateAction } from './types';\nimport { markDirty } from './scheduler';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst normalizeStrings = (values: string[]) => [...new Set(values)].sort();\nconst normalizeFields = (values: IQuoteKey[]) => [...new Set(values)].sort();\n\nconst analyzeRequestedQuotes = (\n quoteState: IQuoteState,\n product_ids: string[],\n fields: IQuoteKey[],\n updated_at: number,\n): { needUpdate: IQuoteRequire[] } => {\n const needUpdate: IQuoteRequire[] = [];\n for (const product_id of product_ids) {\n for (const field of fields) {\n const tuple = quoteState.getValueTuple(product_id, field);\n if (tuple === undefined) {\n needUpdate.push({ product_id, field });\n continue;\n }\n if (tuple[1] < updated_at) {\n needUpdate.push({ product_id, field });\n }\n }\n }\n return { needUpdate };\n};\n\nterminal.server.provideService<IQuoteUpdateAction>('VEX/UpdateQuotes', {}, async (msg) => {\n quoteState.update(msg.req);\n return { res: { code: 0, message: 'OK' } };\n});\n\nterminal.server.provideService<{}, IQuoteUpdateAction>('VEX/DumpQuoteState', {}, async () => {\n return { res: { code: 0, message: 'OK', data: quoteState.dumpAsObject() } };\n});\n\nterminal.server.provideService<\n { product_ids: string[]; fields: IQuoteKey[]; updated_at: number },\n Record<string, Partial<Record<IQuoteKey, string>>>\n>(\n 'VEX/QueryQuotes',\n {\n type: 'object',\n required: ['product_ids', 'fields', 'updated_at'],\n properties: {\n product_ids: {\n type: 'array',\n items: { type: 'string' },\n },\n fields: {\n type: 'array',\n items: { type: 'string' },\n },\n updated_at: { type: 'number' },\n },\n },\n async (msg) => {\n const product_ids = normalizeStrings(msg.req.product_ids);\n const fields = normalizeFields(msg.req.fields);\n const { updated_at } = msg.req;\n\n const { needUpdate } = analyzeRequestedQuotes(quoteState, product_ids, fields, updated_at);\n for (const { product_id, field } of needUpdate) {\n markDirty(product_id, field as any as IQuoteField);\n }\n\n const data = quoteState.filterValues(product_ids, fields);\n return { res: { code: 0, message: 'OK', data } };\n },\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.benchmark.js","sourceRoot":"","sources":["../../src/quote/state.benchmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAE5F;;;GAGG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,cAAc;IACd,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"state.benchmark.js","sourceRoot":"","sources":["../../src/quote/state.benchmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AAE5F;;;GAGG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,cAAc;IACd,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,gBAAgB;IAChB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAE7C,MAAM,oBAAoB,GAAG,IAAI,8BAA8B,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAEvF,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,MAAM,oBAAoB,CAAC,sBAAsB,EAAE,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,MAAM,oBAAoB,CAAC,sBAAsB,EAAE,CAAC;IACtD,CAAC;AACH,CAAC;AAED,kBAAkB;AAClB,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["import { ForkedQuoteStateComparisonTest } from './benchmark/ForkedQuoteStateComparisonTest';\n\n/**\n * 主函数 - 命令行入口点\n * 仅支持 --fork-compare 和 --fork-compare --quick 模式\n */\nasync function main() {\n const args = process.argv.slice(2);\n\n // 检查是否使用正确的模式\n if (!args.includes('--fork-compare')) {\n console.log('使用方法:');\n console.log(' --fork-compare 运行完整的子进程隔离内存对比测试');\n console.log(' --fork-compare --quick 运行快速的子进程隔离内存对比测试');\n console.log('');\n console.log('注意:每个实现都在独立的子进程中运行,确保内存测试的公平性');\n return;\n }\n\n // 子进程隔离内存对比测试模式\n console.log('运行子进程隔离内存对比测试模式...');\n console.log('注意:每个实现都在独立的子进程中运行,确保内存测试的公平性');\n\n const forkedComparisonTest = new ForkedQuoteStateComparisonTest('Current', 'Baseline');\n\n if (args.includes('--quick')) {\n await forkedComparisonTest.runQuickComparisonTest();\n } else {\n await forkedComparisonTest.runComparisonTestSuite();\n }\n}\n\n// 如果直接运行此文件,则执行测试\nif (require.main === module) {\n main().catch(console.error);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/backwards-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAE1F,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,EACnD,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,IAAI,GAA+B,CAAC;IACpC,IAAI,SAAS,KAAK,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"backwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/backwards-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAE1F,MAAM,CAAC,MAAM,gCAAgC,GAAG,KAAK,EACnD,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,IAAI,GAA+B,CAAC;IACpC,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,iCAAiC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAE1E,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,SAAS;YACpB,IAAI,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,2CAA2C,EAC3C,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,2CAA2C,EAC3C,QAAQ,EACR,aAAa,UAAU,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CAClF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { IIngestInterestRateRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { formatTime } from '@yuants/utils';\nimport { findInterestRateStartTimeBackward } from './sql-helpers';\n\nconst terminal = Terminal.fromNodeEnv();\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'backward' });\n\nexport const handleIngestInterestRateBackward = async (\n product_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n let req: IIngestInterestRateRequest;\n if (direction === 'backward') {\n const startTime = await findInterestRateStartTimeBackward(terminal, product_id);\n const start_time = startTime ? new Date(startTime).getTime() : Date.now();\n\n req = {\n product_id: product_id,\n direction: 'backward',\n time: start_time,\n };\n } else {\n req = {\n product_id: product_id,\n direction: 'forward',\n time: 0,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Backward]',\n 'Request',\n `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Backward]',\n 'Result',\n `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/backwards-ohlc.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAE/D,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"backwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/backwards-ohlc.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,6DAA6D;AAC7D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAE/D,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAK/B,QAAQ,EACR,8DAA8D,SAAS,CACrE,SAAS,CACV,yDAAyD,CAC3D,CAAC;QACF,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAE/E,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,UAAU;QACV,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS;YACT,IAAI,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,mCAAmC,EACnC,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,cAAc,GAAG,CAAC,QAAQ,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CACpG,GAAG,CAAC,IAAI,CACT,EAAE,CACJ,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,YAAY,EACZ,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,mCAAmC,EACnC,UAAU,EACV,aAAa,SAAS,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACjF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// 解决 Backwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Backwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport { decodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport { IIngestOHLCRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { formatTime } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'backward' });\n\nexport const handleIngestOHLCBackward = async (\n series_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const { product_id, duration } = decodeOHLCSeriesId(series_id);\n\n let req: IIngestOHLCRequest;\n if (direction === 'backward') {\n const [record] = await requestSQL<\n {\n start_time: string;\n }[]\n >(\n terminal,\n `select start_time from series_data_range where series_id = ${escapeSQL(\n series_id,\n )} and table_name = 'ohlc_v2' order by start_time limit 1`,\n );\n const start_time = record ? new Date(record.start_time).getTime() : Date.now();\n\n req = {\n product_id,\n duration,\n direction: 'backward',\n time: start_time,\n };\n } else {\n // forward\n req = {\n product_id,\n duration,\n direction,\n time: 0,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Backward]',\n 'Request',\n `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(\n req.time,\n )}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>(\n 'IngestOHLC',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Backward]',\n 'Response',\n `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/series-collector/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAEL,0CAA0C,EAC1C,kCAAkC,GACnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,IAAI,EAAE;IAClD,MAAM,WAAW,GAAG,MAAM,UAAU,CAClC,QAAQ;IACR,aAAa;IACb,+DAA+D,CAChE,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC7D,KAAK,MAAM,YAAY,IAAI,QAAQ,CAAC,aAAa,EAAE;
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/series-collector/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAEL,0CAA0C,EAC1C,kCAAkC,GACnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,IAAI,EAAE;IAClD,MAAM,WAAW,GAAG,MAAM,UAAU,CAClC,QAAQ;IACR,aAAa;IACb,+DAA+D,CAChE,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC7D,KAAK,MAAM,YAAY,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClD,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;YACxE,IAAI,WAAW,CAAC,MAAM,KAAK,oBAAoB;gBAAE,SAAS;YAC1D,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,0CAA0C,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAE5E,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,WAAW,EAAE,CAAC;oBACzC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC;wBAAE,SAAS;oBAC7D,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;oBAAS,CAAC;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;IAC1C,MAAM,WAAW,GAAG,MAAM,UAAU,CAA2B,QAAQ,EAAE,gCAAgC,CAAC,CAAC;IAE3G,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC7D,KAAK,MAAM,YAAY,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;QAClD,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;YACxE,IAAI,WAAW,CAAC,MAAM,KAAK,YAAY;gBAAE,SAAS;YAClD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,kCAAkC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBAEpE,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,WAAW,EAAE,CAAC;oBACzC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC;wBAAE,SAAS;oBAC7D,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;wBAC1C,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;wBAC3D,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;oBAC5C,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC","sourcesContent":["import { encodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport {\n IInterestRateServiceMetadata,\n parseInterestRateServiceMetadataFromSchema,\n parseOHLCServiceMetadataFromSchema,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { requestSQL } from '@yuants/sql';\n\nconst terminal = Terminal.fromNodeEnv();\n\n/**\n * 列出所有支持利率的品种系列ID以及对应的 Service Metadata\n * @returns\n */\nexport const listInterestRateSeriesIds = async () => {\n const product_ids = await requestSQL<{ product_id: string }[]>(\n terminal,\n // 必须是支持利率的品种\n `select product_id from product where no_interest_rate = false`,\n );\n\n const series_ids = new Map<string, 'forward' | 'backward'>();\n for (const terminalInfo of terminal.terminalInfos) {\n for (const serviceInfo of Object.values(terminalInfo.serviceInfo || {})) {\n if (serviceInfo.method !== 'IngestInterestRate') continue;\n try {\n const meta = parseInterestRateServiceMetadataFromSchema(serviceInfo.schema);\n\n for (const { product_id } of product_ids) {\n if (!product_id.startsWith(meta.product_id_prefix)) continue;\n series_ids.set(product_id, meta.direction);\n }\n } finally {\n }\n }\n }\n\n return series_ids;\n};\n\n/**\n *\n * @returns\n */\nexport const listOHLCSeriesIds = async () => {\n const product_ids = await requestSQL<{ product_id: string }[]>(terminal, `select product_id from product`);\n\n const series_ids = new Map<string, 'forward' | 'backward'>();\n for (const terminalInfo of terminal.terminalInfos) {\n for (const serviceInfo of Object.values(terminalInfo.serviceInfo || {})) {\n if (serviceInfo.method !== 'IngestOHLC') continue;\n try {\n const meta = parseOHLCServiceMetadataFromSchema(serviceInfo.schema);\n\n for (const { product_id } of product_ids) {\n if (!product_id.startsWith(meta.product_id_prefix)) continue;\n for (const duration of meta.duration_list) {\n const series_id = encodeOHLCSeriesId(product_id, duration);\n series_ids.set(series_id, meta.direction);\n }\n }\n } finally {\n }\n }\n }\n\n return series_ids;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/forwards-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,EAClD,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,IAAI,GAA+B,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"forwards-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/forwards-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,EAClD,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,IAAI,GAA+B,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,8BAA8B,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvD,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,SAAS;YACpB,IAAI;SACL,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,WAAW;QACX,GAAG,GAAG;YACJ,UAAU;YACV,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;SACjB,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,0CAA0C,EAC1C,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,0CAA0C,EAC1C,QAAQ,EACR,aAAa,UAAU,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CAClF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { IIngestInterestRateRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { formatTime } from '@yuants/utils';\nimport { findInterestRateEndTimeForward } from './sql-helpers';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'forward' });\n\nexport const handleIngestInterestRateForward = async (\n product_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n let req: IIngestInterestRateRequest;\n if (direction === 'forward') {\n const endTime = await findInterestRateEndTimeForward(terminal, product_id);\n const time = endTime ? new Date(endTime).getTime() : 0;\n\n req = {\n product_id: product_id,\n direction: 'forward',\n time,\n };\n } else {\n // backward\n req = {\n product_id,\n direction: 'backward',\n time: Date.now(),\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Forward]',\n 'Request',\n `product_id=${req.product_id}, direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Forward]',\n 'Result',\n `series_id=${product_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/forwards-ohlc.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEhF,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"forwards-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/forwards-ohlc.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,4DAA4D;AAC5D,iDAAiD;AACjD,qCAAqC;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEhF,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,GAAuB,CAAC;IAC5B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAK/B,QAAQ,EACR,4DAA4D,SAAS,CACnE,SAAS,CACV,4DAA4D,CAC9D,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9D,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS,EAAE,SAAS;YACpB,IAAI;SACL,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,WAAW;QACX,GAAG,GAAG;YACJ,UAAU;YACV,QAAQ;YACR,SAAS;YACT,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE;SACjB,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,kCAAkC,EAClC,SAAS,EACT,cAAc,GAAG,CAAC,UAAU,cAAc,GAAG,CAAC,QAAQ,eAAe,GAAG,CAAC,SAAS,UAAU,UAAU,CACpG,GAAG,CAAC,IAAI,CACT,EAAE,CACJ,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,YAAY,EACZ,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,kCAAkC,EAClC,UAAU,EACV,aAAa,SAAS,oBAAoB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACjF,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// 解决 Forwards 拉取历史数据的调度器\n// 该文件会定期扫描所有 Terminal 的 ServiceInfo,提取出所有支持 Forwards 拉取的序列。\n// 然后对每个序列,向对应的 IngestOHLC Service 发送拉取请求,补齐历史数据。\n// 使用 Token Bucket 控制每个数据源的请求速率,避免过载。\n\nimport { decodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport { IIngestOHLCRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { formatTime } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'forward' });\n\nexport const handleIngestOHLCForward = async (\n series_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const { product_id, duration } = decodeOHLCSeriesId(series_id);\n let req: IIngestOHLCRequest;\n if (direction === 'forward') {\n const [record] = await requestSQL<\n {\n end_time: string;\n }[]\n >(\n terminal,\n `select end_time from series_data_range where series_id = ${escapeSQL(\n series_id,\n )} and table_name = 'ohlc_v2' order by end_time desc limit 1`,\n );\n\n const time = record ? new Date(record.end_time).getTime() : 0;\n\n req = {\n product_id,\n duration,\n direction: 'forward',\n time,\n };\n } else {\n // backward\n req = {\n product_id,\n duration,\n direction,\n time: Date.now(),\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Forward]',\n 'Request',\n `product_id=${req.product_id}, duration=${req.duration}, direction=${req.direction}, time=${formatTime(\n req.time,\n )}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>(\n 'IngestOHLC',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Forward]',\n 'Response',\n `series_id=${series_id}, ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patch-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/patch-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,uBAAuB;AACvB,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAC/B,QAAQ,EACR;;;;;;;;;;;wBAWoB,SAAS,CAAC,UAAU,CAAC;;;;;;;;;;KAUxC,CACF,CAAC;IAEF,SAAS;IACT,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAE3D,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,wCAAwC,EACxC,SAAS,EACT,UAAU,UAAU,UAAU,UAAU,CAAC,YAAY,CAAC,QAAQ,UAAU,CAAC,UAAU,CAAC,EAAE,CACvF,CAAC;IAEF,IAAI,GAA+B,CAAC;IAEpC,IAAI,SAAS,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"patch-interest-rate.js","sourceRoot":"","sources":["../../src/series-collector/patch-interest-rate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEzF,uBAAuB;AACvB,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,EAC1C,UAAkB,EAClB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAC/B,QAAQ,EACR;;;;;;;;;;;wBAWoB,SAAS,CAAC,UAAU,CAAC;;;;;;;;;;KAUxC,CACF,CAAC;IAEF,SAAS;IACT,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAE3D,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,wCAAwC,EACxC,SAAS,EACT,UAAU,UAAU,UAAU,UAAU,CAAC,YAAY,CAAC,QAAQ,UAAU,CAAC,UAAU,CAAC,EAAE,CACvF,CAAC;IAEF,IAAI,GAA+B,CAAC;IAEpC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,gBAAgB;QAChB,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,SAAkB;YAC7B,IAAI,EAAE,YAAY;SACnB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,SAAS,EAAE,UAAmB;YAC9B,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,wCAAwC,EACxC,UAAU,EACV,cAAc,EACd,aAAa,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAC3D,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,oBAAoB,EACpB,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,wCAAwC,EACxC,UAAU,EACV,qBAAqB,EACrB,kBAAkB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACzD,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { IIngestInterestRateRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { formatTime } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'interest_rate', task: 'forward' });\n\n// Patch 任务:查找数据缺口并进行补齐\nexport const handleInterestRatePatch = async (\n product_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const [record] = await requestSQL<{ gap_start_time: string; gap_end_time: string }[]>(\n terminal,\n `\nWITH reversed_ranges AS (\n SELECT \n start_time,\n end_time,\n LEAD(end_time) OVER (\n PARTITION BY table_name, series_id \n ORDER BY start_time DESC\n ) AS next_end_time -- 注意:倒序时 LEAD 是前一个区间\n FROM series_data_range\n WHERE table_name = 'interest_rate' \n AND series_id = ${escapeSQL(product_id)}\n)\nSELECT \n next_end_time AS gap_start_time, -- 前一个区间的结束时间\n start_time AS gap_end_time -- 当前区间的开始时间\nFROM reversed_ranges\nWHERE next_end_time IS NOT NULL \n AND start_time > next_end_time -- 有空缺\nORDER BY start_time DESC -- 从最新开始\nLIMIT 1;\n `,\n );\n\n // no gap\n if (!record) return;\n\n const gapStartTime = new Date(record.gap_start_time).getTime();\n const gapEndTime = new Date(record.gap_end_time).getTime();\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Patch]',\n 'FindGap',\n `series=${product_id}, from=${formatTime(gapStartTime)}, to=${formatTime(gapEndTime)}`,\n );\n\n let req: IIngestInterestRateRequest;\n\n if (direction === 'forward') {\n // forward patch\n req = {\n product_id: product_id,\n direction: 'forward' as const,\n time: gapStartTime,\n };\n } else {\n // backward patch\n req = {\n product_id: product_id,\n direction: 'backward' as const,\n time: gapEndTime,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Patch]',\n product_id,\n 'PatchRequest',\n `direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][InterestRate][Patch]',\n product_id,\n 'PatchBackwardResult',\n `ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patch-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/patch-ohlc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEhF,uBAAuB;AACvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAC/B,QAAQ,EACR;;;;;;;;;;;wBAWoB,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;KAUvC,CACF,CAAC;IAEF,SAAS;IACT,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAE3D,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,gCAAgC,EAChC,SAAS,EACT,UAAU,SAAS,UAAU,UAAU,CAAC,YAAY,CAAC,QAAQ,UAAU,CAAC,UAAU,CAAC,EAAE,CACtF,CAAC;IAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAE/D,IAAI,GAAuB,CAAC;IAE5B,IAAI,SAAS,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"patch-ohlc.js","sourceRoot":"","sources":["../../src/series-collector/patch-ohlc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO;KACnC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC;KAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAEhF,uBAAuB;AACvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACxC,SAAiB,EACjB,SAAiC,EACjC,MAAmB,EACnB,EAAE;;IACF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAC/B,QAAQ,EACR;;;;;;;;;;;wBAWoB,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;KAUvC,CACF,CAAC;IAEF,SAAS;IACT,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAE3D,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,gCAAgC,EAChC,SAAS,EACT,UAAU,SAAS,UAAU,UAAU,CAAC,YAAY,CAAC,QAAQ,UAAU,CAAC,UAAU,CAAC,EAAE,CACtF,CAAC;IAEF,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAE/D,IAAI,GAAuB,CAAC;IAE5B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,gBAAgB;QAChB,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,QAAQ;YACR,SAAS,EAAE,SAAkB;YAC7B,IAAI,EAAE,YAAY;SACnB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,GAAG,GAAG;YACJ,UAAU,EAAE,UAAU;YACtB,QAAQ;YACR,SAAS,EAAE,UAAmB;YAC9B,IAAI,EAAE,UAAU;SACjB,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,gCAAgC,EAChC,SAAS,EACT,cAAc,EACd,aAAa,GAAG,CAAC,SAAS,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAC3D,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CACtD,YAAY,EACZ,GAAG,CACJ,CAAC;IAEF,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAExC,OAAO,CAAC,IAAI,CACV,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EACtB,gCAAgC,EAChC,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GAAG,CAAC,WAAW,gBAAgB,UAAU,CACzD,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,UAAU,mCAAI,GAAG,CAC7B,cAAc,UAAU,CAAC,MAAA,MAAA,GAAG,CAAC,KAAK,0CAAE,QAAQ,mCAAI,GAAG,CAAC,EAAE,CACxD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { decodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport { IIngestOHLCRequest, ISeriesIngestResult } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { formatTime } from '@yuants/utils';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst ingestCounter = terminal.metrics\n .counter('series_collector_ingest_count', '')\n .labels({ terminal_id: terminal.terminal_id, type: 'ohlc', task: 'forward' });\n\n// Patch 任务:查找数据缺口并进行补齐\nexport const handleIngestOHLCPatch = async (\n series_id: string,\n direction: 'forward' | 'backward',\n signal: AbortSignal,\n) => {\n const [record] = await requestSQL<{ gap_start_time: string; gap_end_time: string }[]>(\n terminal,\n `\nWITH reversed_ranges AS (\n SELECT \n start_time,\n end_time,\n LEAD(end_time) OVER (\n PARTITION BY table_name, series_id \n ORDER BY start_time DESC\n ) AS next_end_time -- 注意:倒序时 LEAD 是前一个区间\n FROM series_data_range\n WHERE table_name = 'ohlc_v2' \n AND series_id = ${escapeSQL(series_id)}\n)\nSELECT \n next_end_time AS gap_start_time, -- 前一个区间的结束时间\n start_time AS gap_end_time -- 当前区间的开始时间\nFROM reversed_ranges\nWHERE next_end_time IS NOT NULL \n AND start_time > next_end_time -- 有空缺\nORDER BY start_time DESC -- 从最新开始\nLIMIT 1;\n `,\n );\n\n // no gap\n if (!record) return;\n\n const gapStartTime = new Date(record.gap_start_time).getTime();\n const gapEndTime = new Date(record.gap_end_time).getTime();\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Patch]',\n 'FindGap',\n `series=${series_id}, from=${formatTime(gapStartTime)}, to=${formatTime(gapEndTime)}`,\n );\n\n const { product_id, duration } = decodeOHLCSeriesId(series_id);\n\n let req: IIngestOHLCRequest;\n\n if (direction === 'forward') {\n // forward patch\n req = {\n product_id: product_id,\n duration,\n direction: 'forward' as const,\n time: gapStartTime,\n };\n } else {\n // backward patch\n req = {\n product_id: product_id,\n duration,\n direction: 'backward' as const,\n time: gapEndTime,\n };\n }\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Patch]',\n series_id,\n 'PatchRequest',\n `direction=${req.direction}, time=${formatTime(req.time)}`,\n );\n\n const res = await terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>(\n 'IngestOHLC',\n req,\n );\n\n ingestCounter.inc(res.wrote_count || 0);\n\n console.info(\n formatTime(Date.now()),\n '[SeriesCollector][OHLC][Patch]',\n series_id,\n 'PatchBackwardResult',\n `ingested_count=${res.wrote_count}, start_time=${formatTime(\n res.range?.start_time ?? NaN,\n )}, end_time=${formatTime(res.range?.end_time ?? NaN)}`,\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/series-collector/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,GAAG,GAAG;IACV,IAAI,EAAE;QACJ,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,uBAAuB;QAChC,QAAQ,EAAE,wBAAwB;QAClC,KAAK,EAAE,qBAAqB;KAC7B;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,+BAA+B;QACxC,QAAQ,EAAE,gCAAgC;QAC1C,KAAK,EAAE,uBAAuB;KAC/B;CACF,CAAC;AAEF,CAAC,KAAK,IAAI,EAAE;IACV,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,cAAc,CAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/series-collector/setup.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodePath, formatTime, tokenBucket } from '@yuants/utils';\nimport { handleIngestInterestRateBackward } from './backwards-interest-rate';\nimport { handleIngestOHLCBackward } from './backwards-ohlc';\nimport { listInterestRateSeriesIds, listOHLCSeriesIds } from './discovery';\nimport { handleIngestInterestRateForward } from './forwards-interest-rate';\nimport { handleIngestOHLCForward } from './forwards-ohlc';\nimport { handleInterestRatePatch } from './patch-interest-rate';\nimport { handleIngestOHLCPatch } from './patch-ohlc';\n\nconst api = {\n OHLC: {\n list: listOHLCSeriesIds,\n forward: handleIngestOHLCForward,\n backward: handleIngestOHLCBackward,\n patch: handleIngestOHLCPatch,\n },\n InterestRate: {\n list: listInterestRateSeriesIds,\n forward: handleIngestInterestRateForward,\n backward: handleIngestInterestRateBackward,\n patch: handleInterestRatePatch,\n },\n};\n\n(async () => {\n const abortController = new AbortController();\n const signal = abortController.signal;\n for (const type of ['OHLC', 'InterestRate'] as const) {\n const list = api[type].list;\n for (const task of ['forward', 'backward', 'patch'] as const) {\n const handler = api[type][task];\n (async () => {\n while (true) {\n await tokenBucket(`${type}:${task}`).acquire(1, signal);\n try {\n const tasks = await list();\n\n // const groups = Map.groupBy(tasks, item => decodePath(item[0])[0]);\n const groups = new Map<string, [string, 'forward' | 'backward'][]>();\n for (const item of tasks) {\n const [datasource_id] = decodePath(item[0]);\n let items = groups.get(datasource_id);\n if (!items) {\n items = [];\n groups.set(datasource_id, items);\n }\n items.push(item);\n }\n\n await Promise.all(\n Array.from(groups.entries()).map(async ([datasource_id, tasks]) => {\n for (const [series_id, direction] of tasks) {\n await tokenBucket(`${type}:${task}:${datasource_id}`).acquire(1, signal);\n await handler(series_id, direction, signal).catch((err) => {\n console.info(\n formatTime(Date.now()),\n `[SeriesCollector][${type}][${task}]`,\n series_id,\n 'Error',\n err,\n );\n });\n }\n }),\n );\n } catch (e) {}\n }\n })();\n }\n }\n})();\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fifo-queue.js","sourceRoot":"","sources":["../../src/series-data/fifo-queue.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,eAAe,GAAG,GAAiB,EAAE;IAChD,IAAI,KAAK,GAAQ,EAAE,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,OAAO;QACL,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO,SAAS,CAAC;YAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5B,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"fifo-queue.js","sourceRoot":"","sources":["../../src/series-data/fifo-queue.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,eAAe,GAAG,GAAiB,EAAE;IAChD,IAAI,KAAK,GAAQ,EAAE,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,OAAO;QACL,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO,SAAS,CAAC;YAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5B,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC3C,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,GAAG,CAAC,CAAC;YACX,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI;QAC/B,QAAQ,EAAE,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE;YACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["export interface IQueue<T> {\n enqueue: (value: T) => void;\n dequeue: () => T | undefined;\n size: () => number;\n snapshot: (limit?: number) => T[];\n}\n\nexport const createFifoQueue = <T>(): IQueue<T> => {\n let items: T[] = [];\n let head = 0;\n\n return {\n enqueue: (value) => {\n items.push(value);\n },\n dequeue: () => {\n if (head >= items.length) return undefined;\n const value = items[head++];\n if (head > 1024 && head * 2 > items.length) {\n items = items.slice(head);\n head = 0;\n }\n return value;\n },\n size: () => items.length - head,\n snapshot: (limit = 20) => {\n const safeLimit = Math.max(0, Math.floor(limit));\n return items.slice(head, head + safeLimit);\n },\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/series-data/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeInterestRateSeriesId } from '@yuants/data-interest-rate';\nimport { encodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport {\n IIngestInterestRateRequest,\n IIngestOHLCRequest,\n ISeriesIngestResult,\n parseInterestRateServiceMetadataFromSchema,\n parseOHLCServiceMetadataFromSchema,\n SeriesFetchDirection,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { convertDurationToOffset, encodePath, formatTime } from '@yuants/utils';\nimport { catchError, defer, EMPTY, filter, from, map, mergeMap, repeat, tap, timer, toArray } from 'rxjs';\nimport { createFifoQueue } from './fifo-queue';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst isEnabled = process.env.VEX_SERIES_DATA_ENABLED === '1';\nconst onlyProductIdPrefix = (process.env.VEX_SERIES_DATA_ONLY_PRODUCT_ID_PREFIX ?? '').trim();\n\nconst CONFIG = {\n tickIntervalMs: 1_000,\n scanFullLoopIntervalMs: 5 * 60_000,\n /**\n * Maximum number of inflight series data ingest requests.\n */\n maxInflight: 20,\n /**\n * Only run tail jobs when the global head backlog is below this threshold.\n */\n tailOnlyWhenGlobalHeadBelow: 20,\n defaultInterestRateHeadLagMs: 8 * 60 * 60_000,\n defaultForwardSeedWindowMs: 24 * 60 * 60_000,\n maxBackoffMs: 5 * 60_000,\n backoffStepMs: 5_000,\n} as const;\n\n// Per-capability bucket scheduler.\n//\n// Service Discovery -> Scan Products -> Schedule Series -> Tick -> Execute Job -> Merge Range -> Repeat\n//\n// 1) Service Discovery:\n// Subscribe `terminal.terminalInfos$`, find services with method `IngestOHLC` / `IngestInterestRate`,\n// parse schema -> capability metadata (product_id_prefix, direction, duration_list).\n//\n// 2) Capability buckets (capKey):\n// capKey = encodePath(method, product_id_prefix, direction)\n// - each cap has its own headQueue/tailQueue and runs serially (cap inflight=1)\n// - tick chooses a cap in round-robin; cap runs head first\n// - tail runs only when global head backlog is low (avoid hurting freshness)\n// - errors/backoff are isolated per-cap (a noisy cap won't block others)\n//\n// 3) Scan Products:\n// For each capability, scan `product` table by `product_id_prefix` (full scan) and expand product -> series:\n// - OHLC: product x duration_list\n// - InterestRate: product\n//\n// 4) Progress source of truth:\n// We do NOT depend on wrote_count/inserted_count to decide progress.\n// After each successful ingest, we merge `series_data_range` and recompute:\n// - segments[]: merged ranges (used for gap detection)\n// - union: { min(start), max(end) } (used for head/tail decisions; union does NOT mean continuous coverage)\n//\n// 5) Gap semantics:\n// - merge only on strict overlap: prev.end_time > next.start_time\n// - touch (prev.end_time == next.start_time): NOT merged, and NOT a gap\n// - gap only when prev.end_time < next.start_time\n// Tail will prioritize filling the nearest-now gap (by range boundaries).\n//\n// 6) Each request must overlap:\n// Because merge is strict-overlap only, a \"touching\" page would keep accumulating fragments.\n// Therefore we deliberately shift request `time` into the already-covered area by `overlapMs`:\n// - backward: time += overlapMs (clamp to <= now)\n// - forward: time -= overlapMs (clamp to >= 0)\n// Duplicate writes are OK (unique key / ON CONFLICT absorbs them).\n//\n// 7) Retry/backoff:\n// When request fails or returns no range, we apply backoff and reschedule,\n// otherwise the queue may be consumed to empty and appear \"stuck\".\n//\n// 8) Routing / load balancing:\n// Scheduler does not pin a request to a specific instance; it uses `terminal.client.requestForResponseData`\n// and relies on Terminal's schema-based service selection + load balancing.\n\ntype ISeriesType = 'ohlc' | 'interest_rate';\ntype IJobKind = 'head' | 'tail';\n\ntype IJob = {\n kind: IJobKind;\n seriesKey: string;\n};\n\ntype ISeriesState = {\n capKey: string;\n seriesKey: string;\n seriesType: ISeriesType;\n table_name: string;\n series_id: string;\n product_id: string;\n duration?: string;\n direction: SeriesFetchDirection;\n ranges: { startMs: number; endMs: number }[];\n union_start_ms?: number;\n union_end_ms?: number;\n last_window_ms?: number;\n};\n\ntype ICapability = {\n capKey: string;\n method: 'IngestOHLC' | 'IngestInterestRate';\n seriesType: ISeriesType;\n product_id_prefix: string;\n direction: SeriesFetchDirection;\n duration_list?: string[];\n nextScanAt: number;\n};\n\ntype ICapabilityState = {\n capKey: string;\n headQueue: ReturnType<typeof createFifoQueue<IJob>>;\n tailQueue: ReturnType<typeof createFifoQueue<IJob>>;\n pendingHead: Set<string>;\n pendingTail: Set<string>;\n inflight: boolean;\n nextEligibleAt: number;\n backoffMs: number;\n};\n\nconst capabilities: ICapability[] = [];\nconst mapCapKeyToCapability = new Map<string, ICapability>();\nconst mapCapKeyToState = new Map<string, ICapabilityState>();\n\nconst mapSeriesKeyToState = new Map<string, ISeriesState>();\n\nlet inflight = 0;\nlet scanIndex = 0;\nlet capRunIndex = 0;\nconst LOG_QUEUE_INTERVAL_MS = Number(process.env.VEX_SERIES_DATA_LOG_QUEUE_INTERVAL_MS ?? '10000');\n\nconst getOrCreateCapState = (capKey: string): ICapabilityState => {\n const existing = mapCapKeyToState.get(capKey);\n if (existing) return existing;\n const next: ICapabilityState = {\n capKey,\n headQueue: createFifoQueue<IJob>(),\n tailQueue: createFifoQueue<IJob>(),\n pendingHead: new Set<string>(),\n pendingTail: new Set<string>(),\n inflight: false,\n nextEligibleAt: 0,\n backoffMs: 0,\n };\n mapCapKeyToState.set(capKey, next);\n return next;\n};\n\nconst computeSeriesId = (seriesType: ISeriesType, product_id: string, duration?: string): string => {\n if (seriesType === 'ohlc') return encodeOHLCSeriesId(product_id, duration ?? '');\n return encodeInterestRateSeriesId(product_id);\n};\n\nconst getOrCreateSeriesState = (params: {\n capKey: string;\n seriesType: ISeriesType;\n product_id: string;\n duration?: string;\n direction: SeriesFetchDirection;\n}): ISeriesState => {\n const { capKey, seriesType, product_id, duration, direction } = params;\n const table_name = seriesType === 'ohlc' ? 'ohlc_v2' : 'interest_rate';\n const series_id = computeSeriesId(seriesType, product_id, duration);\n const seriesKey = encodePath(table_name, direction, product_id, duration ?? '');\n\n const existing = mapSeriesKeyToState.get(seriesKey);\n if (existing) {\n existing.capKey = capKey;\n return existing;\n }\n\n const next: ISeriesState = {\n capKey,\n seriesKey,\n seriesType,\n table_name,\n series_id,\n product_id,\n duration,\n direction,\n ranges: [],\n };\n mapSeriesKeyToState.set(seriesKey, next);\n return next;\n};\n\nconst computeHeadLagMs = (series: ISeriesState): number => {\n if (series.seriesType === 'interest_rate') return CONFIG.defaultInterestRateHeadLagMs;\n const offset = convertDurationToOffset(series.duration ?? '');\n if (!isFinite(offset) || offset <= 0) return 60_000;\n return Math.max(60_000, offset);\n};\n\nconst computeOverlapMs = (series: ISeriesState): number => {\n const maxOverlapMs = 60 * 60_000;\n let overlapMs = 60_000;\n if (series.seriesType === 'ohlc') {\n const offset = convertDurationToOffset(series.duration ?? '');\n if (isFinite(offset) && offset > 0) overlapMs = offset;\n } else {\n overlapMs = 60 * 60_000;\n }\n if (series.last_window_ms && isFinite(series.last_window_ms) && series.last_window_ms > 0) {\n overlapMs = Math.min(overlapMs, Math.max(1, series.last_window_ms - 1));\n }\n return Math.max(1, Math.min(maxOverlapMs, overlapMs));\n};\n\nconst applyOverlapToRequestTime = (series: ISeriesState, baseTime: number): number => {\n const hasAnyRange =\n series.union_start_ms !== undefined || series.union_end_ms !== undefined || series.ranges.length > 0;\n if (!hasAnyRange) return baseTime;\n const overlapMs = computeOverlapMs(series);\n if (series.direction === 'backward') return Math.min(baseTime + overlapMs, Date.now());\n return Math.max(0, baseTime - overlapMs);\n};\n\nconst computeBackoffMs = (current: number): number => {\n const next =\n current <= 0 ? CONFIG.backoffStepMs : Math.min(CONFIG.maxBackoffMs, current + CONFIG.backoffStepMs);\n return next;\n};\n\nconst enqueueCapJob = (capKey: string, kind: IJobKind, seriesKey: string) => {\n const capState = getOrCreateCapState(capKey);\n const pendingSet = kind === 'head' ? capState.pendingHead : capState.pendingTail;\n const queue = kind === 'head' ? capState.headQueue : capState.tailQueue;\n if (pendingSet.has(seriesKey)) return;\n pendingSet.add(seriesKey);\n queue.enqueue({ kind, seriesKey });\n};\n\nconst scheduleSeries = (series: ISeriesState) => {\n const now = Date.now();\n\n const headLagMs = computeHeadLagMs(series);\n const needHead = series.union_end_ms === undefined || now - series.union_end_ms > headLagMs;\n if (needHead) {\n enqueueCapJob(series.capKey, 'head', series.seriesKey);\n return;\n }\n\n if (series.union_start_ms === undefined) return;\n enqueueCapJob(series.capKey, 'tail', series.seriesKey);\n};\n\nconst mergeRangesAndGetUnion = async (\n series_id: string,\n table_name: string,\n): Promise<{\n segments: { startMs: number; endMs: number }[];\n union?: { startMs: number; endMs: number };\n}> => {\n const rows = await requestSQL<{ start_time: string; end_time: string }[]>(\n terminal,\n `\n WITH locked AS (\n SELECT series_id, table_name, start_time, end_time\n FROM series_data_range\n WHERE series_id = ${escapeSQL(series_id)} AND table_name = ${escapeSQL(table_name)}\n ORDER BY start_time ASC, end_time ASC\n FOR UPDATE\n ),\n ordered AS (\n SELECT\n start_time,\n end_time,\n max(end_time) OVER (\n ORDER BY start_time ASC, end_time ASC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS running_end\n FROM locked\n ),\n marks AS (\n SELECT\n start_time,\n end_time,\n running_end,\n CASE\n WHEN start_time >= COALESCE(\n lag(running_end) OVER (ORDER BY start_time ASC, end_time ASC),\n '-infinity'::timestamptz\n ) THEN 1\n ELSE 0\n END AS is_new_group\n FROM ordered\n ),\n groups AS (\n SELECT\n start_time,\n end_time,\n sum(is_new_group) OVER (\n ORDER BY start_time ASC, end_time ASC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS grp\n FROM marks\n ),\n merged AS (\n SELECT min(start_time) AS start_time, max(end_time) AS end_time\n FROM groups\n GROUP BY grp\n ),\n to_delete AS (\n SELECT l.series_id, l.table_name, l.start_time, l.end_time\n FROM locked l\n WHERE NOT EXISTS (\n SELECT 1\n FROM merged m\n WHERE m.start_time = l.start_time AND m.end_time = l.end_time\n )\n ),\n deleted AS (\n DELETE FROM series_data_range t\n USING to_delete d\n WHERE\n t.series_id = d.series_id\n AND t.table_name = d.table_name\n AND t.start_time = d.start_time\n AND t.end_time = d.end_time\n RETURNING 1\n ),\n to_insert AS (\n SELECT m.start_time, m.end_time\n FROM merged m\n WHERE NOT EXISTS (\n SELECT 1\n FROM locked l\n WHERE l.start_time = m.start_time AND l.end_time = m.end_time\n )\n ),\n inserted AS (\n INSERT INTO series_data_range (series_id, table_name, start_time, end_time)\n SELECT ${escapeSQL(series_id)}, ${escapeSQL(table_name)}, start_time, end_time\n FROM to_insert\n ON CONFLICT DO NOTHING\n RETURNING 1\n )\n SELECT start_time, end_time\n FROM series_data_range\n WHERE series_id = ${escapeSQL(series_id)} AND table_name = ${escapeSQL(table_name)}\n ORDER BY start_time ASC, end_time ASC;\n `,\n );\n\n if (rows.length === 0) return { segments: [] };\n const segments: { startMs: number; endMs: number }[] = [];\n let startMs = Number.POSITIVE_INFINITY;\n let endMs = Number.NEGATIVE_INFINITY;\n for (const r of rows) {\n const s = Date.parse(r.start_time);\n const e = Date.parse(r.end_time);\n if (!isNaN(s) && !isNaN(e) && e >= s) {\n segments.push({ startMs: s, endMs: e });\n startMs = Math.min(startMs, s);\n endMs = Math.max(endMs, e);\n }\n }\n if (!isFinite(startMs) || !isFinite(endMs)) return { segments };\n return { segments, union: { startMs, endMs } };\n};\n\nconst findNearestGap = (\n segments: { startMs: number; endMs: number }[],\n): { left: { startMs: number; endMs: number }; right: { startMs: number; endMs: number } } | undefined => {\n for (let i = segments.length - 2; i >= 0; i--) {\n const left = segments[i];\n const right = segments[i + 1];\n if (left.endMs < right.startMs) return { left, right };\n }\n};\n\nconst computeTailTime = (series: ISeriesState, now: number): number => {\n const gap = findNearestGap(series.ranges);\n if (gap) {\n return series.direction === 'backward' ? gap.right.startMs : gap.left.endMs;\n }\n\n const first = series.ranges[0];\n const mostRecent = series.ranges[series.ranges.length - 1];\n if (series.direction === 'backward') {\n return series.union_start_ms ?? first?.startMs ?? mostRecent?.startMs ?? now;\n }\n\n const windowMs = series.last_window_ms ?? CONFIG.defaultForwardSeedWindowMs;\n const start = series.union_start_ms ?? Math.max(0, now - windowMs);\n return Math.max(0, start - windowMs);\n};\n\nconst computeRequestTime = (series: ISeriesState, kind: IJobKind): number => {\n const now = Date.now();\n if (series.direction === 'backward') {\n if (kind === 'head') return applyOverlapToRequestTime(series, now);\n return applyOverlapToRequestTime(series, computeTailTime(series, now));\n }\n\n const windowMs = series.last_window_ms ?? CONFIG.defaultForwardSeedWindowMs;\n if (kind === 'head') {\n if (series.union_end_ms !== undefined) return applyOverlapToRequestTime(series, series.union_end_ms);\n return applyOverlapToRequestTime(series, Math.max(0, now - windowMs));\n }\n return applyOverlapToRequestTime(series, computeTailTime(series, now));\n};\n\nconst requestIngest = async (series: ISeriesState, time: number): Promise<ISeriesIngestResult> => {\n if (series.seriesType === 'ohlc') {\n const req: IIngestOHLCRequest = {\n product_id: series.product_id,\n duration: series.duration ?? '',\n direction: series.direction,\n time,\n };\n return terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>('IngestOHLC', req);\n }\n\n const req: IIngestInterestRateRequest = {\n product_id: series.product_id,\n direction: series.direction,\n time,\n };\n return terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n};\n\nconst executeJob = async (capState: ICapabilityState, job: IJob) => {\n const series = mapSeriesKeyToState.get(job.seriesKey);\n if (!series) return;\n\n if (job.kind === 'head') capState.pendingHead.delete(job.seriesKey);\n else capState.pendingTail.delete(job.seriesKey);\n\n try {\n // make sure each request overlaps existing ranges\n const time = computeRequestTime(series, job.kind);\n const result = await requestIngest(series, time);\n\n capState.backoffMs = 0;\n capState.nextEligibleAt = 0;\n\n if (!result.range) {\n capState.backoffMs = computeBackoffMs(capState.backoffMs);\n capState.nextEligibleAt = Date.now() + capState.backoffMs;\n scheduleSeries(series);\n return;\n }\n\n const startMs = Date.parse(result.range.start_time);\n const endMs = Date.parse(result.range.end_time);\n if (!isNaN(startMs) && !isNaN(endMs) && endMs > startMs) {\n series.last_window_ms = endMs - startMs;\n }\n\n const merged = await mergeRangesAndGetUnion(series.series_id, series.table_name);\n series.ranges = merged.segments;\n if (merged.union) {\n series.union_start_ms = merged.union.startMs;\n series.union_end_ms = merged.union.endMs;\n }\n\n scheduleSeries(series);\n } catch (e) {\n capState.backoffMs = computeBackoffMs(capState.backoffMs);\n capState.nextEligibleAt = Date.now() + capState.backoffMs;\n console.warn(\n formatTime(Date.now()),\n '[VEX][SeriesData]CapFailed',\n `cap=${capState.capKey}`,\n `backoff_ms=${capState.backoffMs}`,\n `${e}`,\n );\n scheduleSeries(series);\n }\n};\n\nconst computeGlobalHeadBacklog = (): number => {\n let total = 0;\n for (const s of mapCapKeyToState.values()) {\n total += s.headQueue.size();\n }\n return total;\n};\n\nconst pickNextRunnableCap = (now: number): ICapabilityState | undefined => {\n if (capabilities.length === 0) return;\n const n = capabilities.length;\n for (let i = 0; i < n; i++) {\n // Round-robin pick\n const cap = capabilities[capRunIndex++ % n];\n const capState = getOrCreateCapState(cap.capKey);\n if (capState.inflight) continue;\n if (capState.nextEligibleAt > now) continue;\n if (capState.headQueue.size() === 0 && capState.tailQueue.size() === 0) continue;\n return capState;\n }\n};\n\nconst dequeueFromCap = (\n capState: ICapabilityState,\n canRunTail: boolean,\n): { job: IJob; kind: IJobKind } | undefined => {\n const head = capState.headQueue.dequeue();\n if (head) return { job: head, kind: 'head' };\n if (!canRunTail) return;\n const tail = capState.tailQueue.dequeue();\n if (!tail) return;\n return { job: tail, kind: 'tail' };\n};\n\nconst scanProductsOnce = async () => {\n if (capabilities.length === 0) return;\n\n const now = Date.now();\n const cap = capabilities[scanIndex++ % capabilities.length];\n if (cap.nextScanAt > now) return;\n\n const where = [\n `product_id LIKE ${escapeSQL(`${cap.product_id_prefix}%`)}`,\n onlyProductIdPrefix ? `product_id LIKE ${escapeSQL(`${onlyProductIdPrefix}%`)}` : '',\n cap.seriesType === 'interest_rate' ? `COALESCE(no_interest_rate, false) = false` : '',\n ]\n .filter(Boolean)\n .join(' AND ');\n\n const rows = await requestSQL<{ product_id: string }[]>(\n terminal,\n `\n SELECT product_id\n FROM product\n WHERE ${where}\n ORDER BY product_id ASC\n `,\n );\n cap.nextScanAt = now + CONFIG.scanFullLoopIntervalMs;\n\n for (const row of rows) {\n if (cap.seriesType === 'ohlc') {\n for (const duration of cap.duration_list ?? []) {\n const series = getOrCreateSeriesState({\n capKey: cap.capKey,\n seriesType: 'ohlc',\n product_id: row.product_id,\n duration,\n direction: cap.direction,\n });\n scheduleSeries(series);\n }\n } else {\n const series = getOrCreateSeriesState({\n capKey: cap.capKey,\n seriesType: 'interest_rate',\n product_id: row.product_id,\n direction: cap.direction,\n });\n scheduleSeries(series);\n }\n }\n};\n\nconst tick = async () => {\n if (!isEnabled) return;\n\n try {\n await scanProductsOnce();\n } catch (e) {\n console.error(formatTime(Date.now()), '[VEX][SeriesData]ScanFailed', `${e}`);\n }\n\n const now = Date.now();\n while (inflight < CONFIG.maxInflight) {\n const capState = pickNextRunnableCap(now);\n if (!capState) return;\n\n const globalHeadBacklog = computeGlobalHeadBacklog();\n const canRunTail =\n globalHeadBacklog < CONFIG.tailOnlyWhenGlobalHeadBelow && capState.headQueue.size() === 0;\n const next = dequeueFromCap(capState, canRunTail);\n if (!next) return;\n\n capState.inflight = true;\n inflight++;\n executeJob(capState, next.job).finally(() => {\n capState.inflight = false;\n inflight--;\n });\n }\n};\n\nif (!isEnabled) {\n console.info(formatTime(Date.now()), '[VEX][SeriesData]Disabled', 'VEX_SERIES_DATA_ENABLED!=1');\n} else {\n terminal.server.provideService('VEX/SeriesData/Peek', {}, async () => {\n const now = Date.now();\n const caps = capabilities.map((cap) => {\n const s = getOrCreateCapState(cap.capKey);\n return {\n capKey: cap.capKey,\n method: cap.method,\n product_id_prefix: cap.product_id_prefix,\n direction: cap.direction,\n head_queue_size: s.headQueue.size(),\n tail_queue_size: s.tailQueue.size(),\n inflight: s.inflight,\n backoff_ms: s.backoffMs,\n nextEligibleAt: s.nextEligibleAt > now ? formatTime(s.nextEligibleAt) : undefined,\n };\n });\n return {\n res: {\n code: 0,\n message: 'OK',\n data: {\n enabled: true,\n only_product_id_prefix: onlyProductIdPrefix || undefined,\n inflight,\n cap_count: capabilities.length,\n global_head_backlog: computeGlobalHeadBacklog(),\n series_count: mapSeriesKeyToState.size,\n caps: caps.slice(0, 50),\n },\n },\n };\n });\n\n // Setup trace log\n timer(0, LOG_QUEUE_INTERVAL_MS).subscribe(() => {\n const now = Date.now();\n const caps = capabilities\n .map((cap) => {\n const s = getOrCreateCapState(cap.capKey);\n return {\n capKey: cap.capKey,\n head: s.headQueue.size(),\n tail: s.tailQueue.size(),\n inflight: s.inflight,\n backoffMs: s.backoffMs,\n nextEligibleAt: s.nextEligibleAt,\n };\n })\n .filter((x) => x.inflight || x.head > 0 || x.tail > 0 || x.nextEligibleAt > now)\n .slice(0, 20)\n .map(\n (x) =>\n `cap=${x.capKey} head=${x.head} tail=${x.tail} inflight=${x.inflight ? 1 : 0} backoff_ms=${\n x.backoffMs\n }${x.nextEligibleAt > now ? ` next=${formatTime(x.nextEligibleAt)}` : ''}`,\n );\n\n console.info(\n formatTime(now),\n '[VEX][SeriesData]Queues',\n `inflight=${inflight}`,\n `cap_count=${capabilities.length}`,\n `global_head_backlog=${computeGlobalHeadBacklog()}`,\n `series_count=${mapSeriesKeyToState.size}`,\n caps.length ? `caps=[${caps.join(' | ')}]` : 'caps=[]',\n );\n });\n\n terminal.terminalInfos$\n .pipe(\n mergeMap((terminalInfos) =>\n from(terminalInfos).pipe(\n mergeMap((terminalInfo) =>\n from(Object.values(terminalInfo.serviceInfo || {})).pipe(\n filter(\n (serviceInfo) =>\n serviceInfo.method === 'IngestOHLC' || serviceInfo.method === 'IngestInterestRate',\n ),\n map((serviceInfo): ICapability | undefined => {\n try {\n if (serviceInfo.method === 'IngestOHLC') {\n const meta = parseOHLCServiceMetadataFromSchema(serviceInfo.schema);\n const capKey = encodePath('IngestOHLC', meta.product_id_prefix, meta.direction);\n const existing = mapCapKeyToCapability.get(capKey);\n const duration_list = [...new Set(meta.duration_list)].sort();\n if (existing) {\n existing.duration_list = duration_list;\n return existing;\n }\n return {\n capKey,\n method: 'IngestOHLC',\n seriesType: 'ohlc',\n product_id_prefix: meta.product_id_prefix,\n direction: meta.direction,\n duration_list,\n nextScanAt: 0,\n };\n }\n\n const meta = parseInterestRateServiceMetadataFromSchema(serviceInfo.schema);\n const capKey = encodePath('IngestInterestRate', meta.product_id_prefix, meta.direction);\n const existing = mapCapKeyToCapability.get(capKey);\n if (existing) return existing;\n return {\n capKey,\n method: 'IngestInterestRate',\n seriesType: 'interest_rate',\n product_id_prefix: meta.product_id_prefix,\n direction: meta.direction,\n nextScanAt: 0,\n };\n } catch {\n console.info(\n formatTime(Date.now()),\n '[VEX][SeriesData]ParseServiceMetadataFailed',\n `method=${serviceInfo.method}`,\n `terminal_id=${terminalInfo.terminal_id}`,\n );\n return;\n }\n }),\n filter((x): x is Exclude<typeof x, undefined> => !!x),\n ),\n ),\n toArray(),\n tap((nextCaps) => {\n const nextMap = new Map<string, ICapability>();\n for (const cap of nextCaps) {\n nextMap.set(cap.capKey, cap);\n }\n mapCapKeyToCapability.clear();\n nextMap.forEach((v, k) => mapCapKeyToCapability.set(k, v));\n capabilities.length = 0;\n nextMap.forEach((v) => capabilities.push(v));\n }),\n ),\n ),\n )\n .subscribe();\n\n defer(() => from(tick()))\n .pipe(\n catchError((e) => {\n console.error(formatTime(Date.now()), '[VEX][SeriesData]TickError', `${e}`);\n return EMPTY;\n }),\n repeat({ delay: CONFIG.tickIntervalMs }),\n )\n .subscribe();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/series-data/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeInterestRateSeriesId } from '@yuants/data-interest-rate';\nimport { encodeOHLCSeriesId } from '@yuants/data-ohlc';\nimport {\n IIngestInterestRateRequest,\n IIngestOHLCRequest,\n ISeriesIngestResult,\n parseInterestRateServiceMetadataFromSchema,\n parseOHLCServiceMetadataFromSchema,\n SeriesFetchDirection,\n} from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { convertDurationToOffset, encodePath, formatTime } from '@yuants/utils';\nimport { catchError, defer, EMPTY, filter, from, map, mergeMap, repeat, tap, timer, toArray } from 'rxjs';\nimport { createFifoQueue } from './fifo-queue';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst isEnabled = process.env.VEX_SERIES_DATA_ENABLED === '1';\nconst onlyProductIdPrefix = (process.env.VEX_SERIES_DATA_ONLY_PRODUCT_ID_PREFIX ?? '').trim();\n\nconst CONFIG = {\n tickIntervalMs: 1_000,\n scanFullLoopIntervalMs: 5 * 60_000,\n /**\n * Maximum number of inflight series data ingest requests.\n */\n maxInflight: 20,\n /**\n * Only run tail jobs when the global head backlog is below this threshold.\n */\n tailOnlyWhenGlobalHeadBelow: 20,\n defaultInterestRateHeadLagMs: 8 * 60 * 60_000,\n defaultForwardSeedWindowMs: 24 * 60 * 60_000,\n maxBackoffMs: 5 * 60_000,\n backoffStepMs: 5_000,\n} as const;\n\n// Per-capability bucket scheduler.\n//\n// Service Discovery -> Scan Products -> Schedule Series -> Tick -> Execute Job -> Merge Range -> Repeat\n//\n// 1) Service Discovery:\n// Subscribe `terminal.terminalInfos$`, find services with method `IngestOHLC` / `IngestInterestRate`,\n// parse schema -> capability metadata (product_id_prefix, direction, duration_list).\n//\n// 2) Capability buckets (capKey):\n// capKey = encodePath(method, product_id_prefix, direction)\n// - each cap has its own headQueue/tailQueue and runs serially (cap inflight=1)\n// - tick chooses a cap in round-robin; cap runs head first\n// - tail runs only when global head backlog is low (avoid hurting freshness)\n// - errors/backoff are isolated per-cap (a noisy cap won't block others)\n//\n// 3) Scan Products:\n// For each capability, scan `product` table by `product_id_prefix` (full scan) and expand product -> series:\n// - OHLC: product x duration_list\n// - InterestRate: product\n//\n// 4) Progress source of truth:\n// We do NOT depend on wrote_count/inserted_count to decide progress.\n// After each successful ingest, we merge `series_data_range` and recompute:\n// - segments[]: merged ranges (used for gap detection)\n// - union: { min(start), max(end) } (used for head/tail decisions; union does NOT mean continuous coverage)\n//\n// 5) Gap semantics:\n// - merge only on strict overlap: prev.end_time > next.start_time\n// - touch (prev.end_time == next.start_time): NOT merged, and NOT a gap\n// - gap only when prev.end_time < next.start_time\n// Tail will prioritize filling the nearest-now gap (by range boundaries).\n//\n// 6) Each request must overlap:\n// Because merge is strict-overlap only, a \"touching\" page would keep accumulating fragments.\n// Therefore we deliberately shift request `time` into the already-covered area by `overlapMs`:\n// - backward: time += overlapMs (clamp to <= now)\n// - forward: time -= overlapMs (clamp to >= 0)\n// Duplicate writes are OK (unique key / ON CONFLICT absorbs them).\n//\n// 7) Retry/backoff:\n// When request fails or returns no range, we apply backoff and reschedule,\n// otherwise the queue may be consumed to empty and appear \"stuck\".\n//\n// 8) Routing / load balancing:\n// Scheduler does not pin a request to a specific instance; it uses `terminal.client.requestForResponseData`\n// and relies on Terminal's schema-based service selection + load balancing.\n\ntype ISeriesType = 'ohlc' | 'interest_rate';\ntype IJobKind = 'head' | 'tail';\n\ntype IJob = {\n kind: IJobKind;\n seriesKey: string;\n};\n\ntype ISeriesState = {\n capKey: string;\n seriesKey: string;\n seriesType: ISeriesType;\n table_name: string;\n series_id: string;\n product_id: string;\n duration?: string;\n direction: SeriesFetchDirection;\n ranges: { startMs: number; endMs: number }[];\n union_start_ms?: number;\n union_end_ms?: number;\n last_window_ms?: number;\n};\n\ntype ICapability = {\n capKey: string;\n method: 'IngestOHLC' | 'IngestInterestRate';\n seriesType: ISeriesType;\n product_id_prefix: string;\n direction: SeriesFetchDirection;\n duration_list?: string[];\n nextScanAt: number;\n};\n\ntype ICapabilityState = {\n capKey: string;\n headQueue: ReturnType<typeof createFifoQueue<IJob>>;\n tailQueue: ReturnType<typeof createFifoQueue<IJob>>;\n pendingHead: Set<string>;\n pendingTail: Set<string>;\n inflight: boolean;\n nextEligibleAt: number;\n backoffMs: number;\n};\n\nconst capabilities: ICapability[] = [];\nconst mapCapKeyToCapability = new Map<string, ICapability>();\nconst mapCapKeyToState = new Map<string, ICapabilityState>();\n\nconst mapSeriesKeyToState = new Map<string, ISeriesState>();\n\nlet inflight = 0;\nlet scanIndex = 0;\nlet capRunIndex = 0;\nconst LOG_QUEUE_INTERVAL_MS = Number(process.env.VEX_SERIES_DATA_LOG_QUEUE_INTERVAL_MS ?? '10000');\n\nconst getOrCreateCapState = (capKey: string): ICapabilityState => {\n const existing = mapCapKeyToState.get(capKey);\n if (existing) return existing;\n const next: ICapabilityState = {\n capKey,\n headQueue: createFifoQueue<IJob>(),\n tailQueue: createFifoQueue<IJob>(),\n pendingHead: new Set<string>(),\n pendingTail: new Set<string>(),\n inflight: false,\n nextEligibleAt: 0,\n backoffMs: 0,\n };\n mapCapKeyToState.set(capKey, next);\n return next;\n};\n\nconst computeSeriesId = (seriesType: ISeriesType, product_id: string, duration?: string): string => {\n if (seriesType === 'ohlc') return encodeOHLCSeriesId(product_id, duration ?? '');\n return encodeInterestRateSeriesId(product_id);\n};\n\nconst getOrCreateSeriesState = (params: {\n capKey: string;\n seriesType: ISeriesType;\n product_id: string;\n duration?: string;\n direction: SeriesFetchDirection;\n}): ISeriesState => {\n const { capKey, seriesType, product_id, duration, direction } = params;\n const table_name = seriesType === 'ohlc' ? 'ohlc_v2' : 'interest_rate';\n const series_id = computeSeriesId(seriesType, product_id, duration);\n const seriesKey = encodePath(table_name, direction, product_id, duration ?? '');\n\n const existing = mapSeriesKeyToState.get(seriesKey);\n if (existing) {\n existing.capKey = capKey;\n return existing;\n }\n\n const next: ISeriesState = {\n capKey,\n seriesKey,\n seriesType,\n table_name,\n series_id,\n product_id,\n duration,\n direction,\n ranges: [],\n };\n mapSeriesKeyToState.set(seriesKey, next);\n return next;\n};\n\nconst computeHeadLagMs = (series: ISeriesState): number => {\n if (series.seriesType === 'interest_rate') return CONFIG.defaultInterestRateHeadLagMs;\n const offset = convertDurationToOffset(series.duration ?? '');\n if (!isFinite(offset) || offset <= 0) return 60_000;\n return Math.max(60_000, offset);\n};\n\nconst computeOverlapMs = (series: ISeriesState): number => {\n const maxOverlapMs = 60 * 60_000;\n let overlapMs = 60_000;\n if (series.seriesType === 'ohlc') {\n const offset = convertDurationToOffset(series.duration ?? '');\n if (isFinite(offset) && offset > 0) overlapMs = offset;\n } else {\n overlapMs = 60 * 60_000;\n }\n if (series.last_window_ms && isFinite(series.last_window_ms) && series.last_window_ms > 0) {\n overlapMs = Math.min(overlapMs, Math.max(1, series.last_window_ms - 1));\n }\n return Math.max(1, Math.min(maxOverlapMs, overlapMs));\n};\n\nconst applyOverlapToRequestTime = (series: ISeriesState, baseTime: number): number => {\n const hasAnyRange =\n series.union_start_ms !== undefined || series.union_end_ms !== undefined || series.ranges.length > 0;\n if (!hasAnyRange) return baseTime;\n const overlapMs = computeOverlapMs(series);\n if (series.direction === 'backward') return Math.min(baseTime + overlapMs, Date.now());\n return Math.max(0, baseTime - overlapMs);\n};\n\nconst computeBackoffMs = (current: number): number => {\n const next =\n current <= 0 ? CONFIG.backoffStepMs : Math.min(CONFIG.maxBackoffMs, current + CONFIG.backoffStepMs);\n return next;\n};\n\nconst enqueueCapJob = (capKey: string, kind: IJobKind, seriesKey: string) => {\n const capState = getOrCreateCapState(capKey);\n const pendingSet = kind === 'head' ? capState.pendingHead : capState.pendingTail;\n const queue = kind === 'head' ? capState.headQueue : capState.tailQueue;\n if (pendingSet.has(seriesKey)) return;\n pendingSet.add(seriesKey);\n queue.enqueue({ kind, seriesKey });\n};\n\nconst scheduleSeries = (series: ISeriesState) => {\n const now = Date.now();\n\n const headLagMs = computeHeadLagMs(series);\n const needHead = series.union_end_ms === undefined || now - series.union_end_ms > headLagMs;\n if (needHead) {\n enqueueCapJob(series.capKey, 'head', series.seriesKey);\n return;\n }\n\n if (series.union_start_ms === undefined) return;\n enqueueCapJob(series.capKey, 'tail', series.seriesKey);\n};\n\nconst mergeRangesAndGetUnion = async (\n series_id: string,\n table_name: string,\n): Promise<{\n segments: { startMs: number; endMs: number }[];\n union?: { startMs: number; endMs: number };\n}> => {\n const rows = await requestSQL<{ start_time: string; end_time: string }[]>(\n terminal,\n `\n WITH locked AS (\n SELECT series_id, table_name, start_time, end_time\n FROM series_data_range\n WHERE series_id = ${escapeSQL(series_id)} AND table_name = ${escapeSQL(table_name)}\n ORDER BY start_time ASC, end_time ASC\n FOR UPDATE\n ),\n ordered AS (\n SELECT\n start_time,\n end_time,\n max(end_time) OVER (\n ORDER BY start_time ASC, end_time ASC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS running_end\n FROM locked\n ),\n marks AS (\n SELECT\n start_time,\n end_time,\n running_end,\n CASE\n WHEN start_time >= COALESCE(\n lag(running_end) OVER (ORDER BY start_time ASC, end_time ASC),\n '-infinity'::timestamptz\n ) THEN 1\n ELSE 0\n END AS is_new_group\n FROM ordered\n ),\n groups AS (\n SELECT\n start_time,\n end_time,\n sum(is_new_group) OVER (\n ORDER BY start_time ASC, end_time ASC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS grp\n FROM marks\n ),\n merged AS (\n SELECT min(start_time) AS start_time, max(end_time) AS end_time\n FROM groups\n GROUP BY grp\n ),\n to_delete AS (\n SELECT l.series_id, l.table_name, l.start_time, l.end_time\n FROM locked l\n WHERE NOT EXISTS (\n SELECT 1\n FROM merged m\n WHERE m.start_time = l.start_time AND m.end_time = l.end_time\n )\n ),\n deleted AS (\n DELETE FROM series_data_range t\n USING to_delete d\n WHERE\n t.series_id = d.series_id\n AND t.table_name = d.table_name\n AND t.start_time = d.start_time\n AND t.end_time = d.end_time\n RETURNING 1\n ),\n to_insert AS (\n SELECT m.start_time, m.end_time\n FROM merged m\n WHERE NOT EXISTS (\n SELECT 1\n FROM locked l\n WHERE l.start_time = m.start_time AND l.end_time = m.end_time\n )\n ),\n inserted AS (\n INSERT INTO series_data_range (series_id, table_name, start_time, end_time)\n SELECT ${escapeSQL(series_id)}, ${escapeSQL(table_name)}, start_time, end_time\n FROM to_insert\n ON CONFLICT DO NOTHING\n RETURNING 1\n )\n SELECT start_time, end_time\n FROM series_data_range\n WHERE series_id = ${escapeSQL(series_id)} AND table_name = ${escapeSQL(table_name)}\n ORDER BY start_time ASC, end_time ASC;\n `,\n );\n\n if (rows.length === 0) return { segments: [] };\n const segments: { startMs: number; endMs: number }[] = [];\n let startMs = Number.POSITIVE_INFINITY;\n let endMs = Number.NEGATIVE_INFINITY;\n for (const r of rows) {\n const s = Date.parse(r.start_time);\n const e = Date.parse(r.end_time);\n if (!isNaN(s) && !isNaN(e) && e >= s) {\n segments.push({ startMs: s, endMs: e });\n startMs = Math.min(startMs, s);\n endMs = Math.max(endMs, e);\n }\n }\n if (!isFinite(startMs) || !isFinite(endMs)) return { segments };\n return { segments, union: { startMs, endMs } };\n};\n\nconst findNearestGap = (\n segments: { startMs: number; endMs: number }[],\n): { left: { startMs: number; endMs: number }; right: { startMs: number; endMs: number } } | undefined => {\n for (let i = segments.length - 2; i >= 0; i--) {\n const left = segments[i];\n const right = segments[i + 1];\n if (left.endMs < right.startMs) return { left, right };\n }\n};\n\nconst computeTailTime = (series: ISeriesState, now: number): number => {\n const gap = findNearestGap(series.ranges);\n if (gap) {\n return series.direction === 'backward' ? gap.right.startMs : gap.left.endMs;\n }\n\n const first = series.ranges[0];\n const mostRecent = series.ranges[series.ranges.length - 1];\n if (series.direction === 'backward') {\n return series.union_start_ms ?? first?.startMs ?? mostRecent?.startMs ?? now;\n }\n\n const windowMs = series.last_window_ms ?? CONFIG.defaultForwardSeedWindowMs;\n const start = series.union_start_ms ?? Math.max(0, now - windowMs);\n return Math.max(0, start - windowMs);\n};\n\nconst computeRequestTime = (series: ISeriesState, kind: IJobKind): number => {\n const now = Date.now();\n if (series.direction === 'backward') {\n if (kind === 'head') return applyOverlapToRequestTime(series, now);\n return applyOverlapToRequestTime(series, computeTailTime(series, now));\n }\n\n const windowMs = series.last_window_ms ?? CONFIG.defaultForwardSeedWindowMs;\n if (kind === 'head') {\n if (series.union_end_ms !== undefined) return applyOverlapToRequestTime(series, series.union_end_ms);\n return applyOverlapToRequestTime(series, Math.max(0, now - windowMs));\n }\n return applyOverlapToRequestTime(series, computeTailTime(series, now));\n};\n\nconst requestIngest = async (series: ISeriesState, time: number): Promise<ISeriesIngestResult> => {\n if (series.seriesType === 'ohlc') {\n const req: IIngestOHLCRequest = {\n product_id: series.product_id,\n duration: series.duration ?? '',\n direction: series.direction,\n time,\n };\n return terminal.client.requestForResponseData<IIngestOHLCRequest, ISeriesIngestResult>('IngestOHLC', req);\n }\n\n const req: IIngestInterestRateRequest = {\n product_id: series.product_id,\n direction: series.direction,\n time,\n };\n return terminal.client.requestForResponseData<IIngestInterestRateRequest, ISeriesIngestResult>(\n 'IngestInterestRate',\n req,\n );\n};\n\nconst executeJob = async (capState: ICapabilityState, job: IJob) => {\n const series = mapSeriesKeyToState.get(job.seriesKey);\n if (!series) return;\n\n if (job.kind === 'head') capState.pendingHead.delete(job.seriesKey);\n else capState.pendingTail.delete(job.seriesKey);\n\n try {\n // make sure each request overlaps existing ranges\n const time = computeRequestTime(series, job.kind);\n const result = await requestIngest(series, time);\n\n capState.backoffMs = 0;\n capState.nextEligibleAt = 0;\n\n if (!result.range) {\n capState.backoffMs = computeBackoffMs(capState.backoffMs);\n capState.nextEligibleAt = Date.now() + capState.backoffMs;\n scheduleSeries(series);\n return;\n }\n\n const startMs = Date.parse(result.range.start_time);\n const endMs = Date.parse(result.range.end_time);\n if (!isNaN(startMs) && !isNaN(endMs) && endMs > startMs) {\n series.last_window_ms = endMs - startMs;\n }\n\n const merged = await mergeRangesAndGetUnion(series.series_id, series.table_name);\n series.ranges = merged.segments;\n if (merged.union) {\n series.union_start_ms = merged.union.startMs;\n series.union_end_ms = merged.union.endMs;\n }\n\n scheduleSeries(series);\n } catch (e) {\n capState.backoffMs = computeBackoffMs(capState.backoffMs);\n capState.nextEligibleAt = Date.now() + capState.backoffMs;\n console.warn(\n formatTime(Date.now()),\n '[VEX][SeriesData]CapFailed',\n `cap=${capState.capKey}`,\n `backoff_ms=${capState.backoffMs}`,\n `${e}`,\n );\n scheduleSeries(series);\n }\n};\n\nconst computeGlobalHeadBacklog = (): number => {\n let total = 0;\n for (const s of mapCapKeyToState.values()) {\n total += s.headQueue.size();\n }\n return total;\n};\n\nconst pickNextRunnableCap = (now: number): ICapabilityState | undefined => {\n if (capabilities.length === 0) return;\n const n = capabilities.length;\n for (let i = 0; i < n; i++) {\n // Round-robin pick\n const cap = capabilities[capRunIndex++ % n];\n const capState = getOrCreateCapState(cap.capKey);\n if (capState.inflight) continue;\n if (capState.nextEligibleAt > now) continue;\n if (capState.headQueue.size() === 0 && capState.tailQueue.size() === 0) continue;\n return capState;\n }\n};\n\nconst dequeueFromCap = (\n capState: ICapabilityState,\n canRunTail: boolean,\n): { job: IJob; kind: IJobKind } | undefined => {\n const head = capState.headQueue.dequeue();\n if (head) return { job: head, kind: 'head' };\n if (!canRunTail) return;\n const tail = capState.tailQueue.dequeue();\n if (!tail) return;\n return { job: tail, kind: 'tail' };\n};\n\nconst scanProductsOnce = async () => {\n if (capabilities.length === 0) return;\n\n const now = Date.now();\n const cap = capabilities[scanIndex++ % capabilities.length];\n if (cap.nextScanAt > now) return;\n\n const where = [\n `product_id LIKE ${escapeSQL(`${cap.product_id_prefix}%`)}`,\n onlyProductIdPrefix ? `product_id LIKE ${escapeSQL(`${onlyProductIdPrefix}%`)}` : '',\n cap.seriesType === 'interest_rate' ? `COALESCE(no_interest_rate, false) = false` : '',\n ]\n .filter(Boolean)\n .join(' AND ');\n\n const rows = await requestSQL<{ product_id: string }[]>(\n terminal,\n `\n SELECT product_id\n FROM product\n WHERE ${where}\n ORDER BY product_id ASC\n `,\n );\n cap.nextScanAt = now + CONFIG.scanFullLoopIntervalMs;\n\n for (const row of rows) {\n if (cap.seriesType === 'ohlc') {\n for (const duration of cap.duration_list ?? []) {\n const series = getOrCreateSeriesState({\n capKey: cap.capKey,\n seriesType: 'ohlc',\n product_id: row.product_id,\n duration,\n direction: cap.direction,\n });\n scheduleSeries(series);\n }\n } else {\n const series = getOrCreateSeriesState({\n capKey: cap.capKey,\n seriesType: 'interest_rate',\n product_id: row.product_id,\n direction: cap.direction,\n });\n scheduleSeries(series);\n }\n }\n};\n\nconst tick = async () => {\n if (!isEnabled) return;\n\n try {\n await scanProductsOnce();\n } catch (e) {\n console.error(formatTime(Date.now()), '[VEX][SeriesData]ScanFailed', `${e}`);\n }\n\n const now = Date.now();\n while (inflight < CONFIG.maxInflight) {\n const capState = pickNextRunnableCap(now);\n if (!capState) return;\n\n const globalHeadBacklog = computeGlobalHeadBacklog();\n const canRunTail =\n globalHeadBacklog < CONFIG.tailOnlyWhenGlobalHeadBelow && capState.headQueue.size() === 0;\n const next = dequeueFromCap(capState, canRunTail);\n if (!next) return;\n\n capState.inflight = true;\n inflight++;\n executeJob(capState, next.job).finally(() => {\n capState.inflight = false;\n inflight--;\n });\n }\n};\n\nif (!isEnabled) {\n console.info(formatTime(Date.now()), '[VEX][SeriesData]Disabled', 'VEX_SERIES_DATA_ENABLED!=1');\n} else {\n terminal.server.provideService('VEX/SeriesData/Peek', {}, async () => {\n const now = Date.now();\n const caps = capabilities.map((cap) => {\n const s = getOrCreateCapState(cap.capKey);\n return {\n capKey: cap.capKey,\n method: cap.method,\n product_id_prefix: cap.product_id_prefix,\n direction: cap.direction,\n head_queue_size: s.headQueue.size(),\n tail_queue_size: s.tailQueue.size(),\n inflight: s.inflight,\n backoff_ms: s.backoffMs,\n nextEligibleAt: s.nextEligibleAt > now ? formatTime(s.nextEligibleAt) : undefined,\n };\n });\n return {\n res: {\n code: 0,\n message: 'OK',\n data: {\n enabled: true,\n only_product_id_prefix: onlyProductIdPrefix || undefined,\n inflight,\n cap_count: capabilities.length,\n global_head_backlog: computeGlobalHeadBacklog(),\n series_count: mapSeriesKeyToState.size,\n caps: caps.slice(0, 50),\n },\n },\n };\n });\n\n // Setup trace log\n timer(0, LOG_QUEUE_INTERVAL_MS).subscribe(() => {\n const now = Date.now();\n const caps = capabilities\n .map((cap) => {\n const s = getOrCreateCapState(cap.capKey);\n return {\n capKey: cap.capKey,\n head: s.headQueue.size(),\n tail: s.tailQueue.size(),\n inflight: s.inflight,\n backoffMs: s.backoffMs,\n nextEligibleAt: s.nextEligibleAt,\n };\n })\n .filter((x) => x.inflight || x.head > 0 || x.tail > 0 || x.nextEligibleAt > now)\n .slice(0, 20)\n .map(\n (x) =>\n `cap=${x.capKey} head=${x.head} tail=${x.tail} inflight=${x.inflight ? 1 : 0} backoff_ms=${\n x.backoffMs\n }${x.nextEligibleAt > now ? ` next=${formatTime(x.nextEligibleAt)}` : ''}`,\n );\n\n console.info(\n formatTime(now),\n '[VEX][SeriesData]Queues',\n `inflight=${inflight}`,\n `cap_count=${capabilities.length}`,\n `global_head_backlog=${computeGlobalHeadBacklog()}`,\n `series_count=${mapSeriesKeyToState.size}`,\n caps.length ? `caps=[${caps.join(' | ')}]` : 'caps=[]',\n );\n });\n\n terminal.terminalInfos$\n .pipe(\n mergeMap((terminalInfos) =>\n from(terminalInfos).pipe(\n mergeMap((terminalInfo) =>\n from(Object.values(terminalInfo.serviceInfo || {})).pipe(\n filter(\n (serviceInfo) =>\n serviceInfo.method === 'IngestOHLC' || serviceInfo.method === 'IngestInterestRate',\n ),\n map((serviceInfo): ICapability | undefined => {\n try {\n if (serviceInfo.method === 'IngestOHLC') {\n const meta = parseOHLCServiceMetadataFromSchema(serviceInfo.schema);\n const capKey = encodePath('IngestOHLC', meta.product_id_prefix, meta.direction);\n const existing = mapCapKeyToCapability.get(capKey);\n const duration_list = [...new Set(meta.duration_list)].sort();\n if (existing) {\n existing.duration_list = duration_list;\n return existing;\n }\n return {\n capKey,\n method: 'IngestOHLC',\n seriesType: 'ohlc',\n product_id_prefix: meta.product_id_prefix,\n direction: meta.direction,\n duration_list,\n nextScanAt: 0,\n };\n }\n\n const meta = parseInterestRateServiceMetadataFromSchema(serviceInfo.schema);\n const capKey = encodePath('IngestInterestRate', meta.product_id_prefix, meta.direction);\n const existing = mapCapKeyToCapability.get(capKey);\n if (existing) return existing;\n return {\n capKey,\n method: 'IngestInterestRate',\n seriesType: 'interest_rate',\n product_id_prefix: meta.product_id_prefix,\n direction: meta.direction,\n nextScanAt: 0,\n };\n } catch {\n console.info(\n formatTime(Date.now()),\n '[VEX][SeriesData]ParseServiceMetadataFailed',\n `method=${serviceInfo.method}`,\n `terminal_id=${terminalInfo.terminal_id}`,\n );\n return;\n }\n }),\n filter((x): x is Exclude<typeof x, undefined> => !!x),\n ),\n ),\n toArray(),\n tap((nextCaps) => {\n const nextMap = new Map<string, ICapability>();\n for (const cap of nextCaps) {\n nextMap.set(cap.capKey, cap);\n }\n mapCapKeyToCapability.clear();\n nextMap.forEach((v, k) => mapCapKeyToCapability.set(k, v));\n capabilities.length = 0;\n nextMap.forEach((v) => capabilities.push(v));\n }),\n ),\n ),\n )\n .subscribe();\n\n defer(() => from(tick()))\n .pipe(\n catchError((e) => {\n console.error(formatTime(Date.now()), '[VEX][SeriesData]TickError', `${e}`);\n return EMPTY;\n }),\n repeat({ delay: CONFIG.tickIntervalMs }),\n )\n .subscribe();\n}\n"]}
|
package/lib/credential.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAQA,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;CACd;AAgGD,eAAO,MAAM,iBAAiB,6DAc7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,qCAQjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAQA,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;CACd;AAgGD,eAAO,MAAM,iBAAiB,6DAc7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,qCAQjC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAAU,MAAM,MAAM;;;;EAMzD,CAAC"}
|
package/lib/credential.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":";;;AAAA,yCAA4C;AAC5C,+CAAmD;AACnD,+CAA4C;AAC5C,2CAA+E;AAC/E,qCAAoD;AACpD,yCAAyC;AACzC,+BAA8E;AAO9E,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC;AAEzF;;;;GAIG;AACH,MAAM,6BAA6B,GAAG,IAAA,mBAAW,EAAC,KAAK,EAAE,IAAY,EAAE,EAAE;IACvE,MAAM,GAAG,GAAG,qCAAqC,IAAA,eAAS,EAAC,IAAI,CAAC,WAAW,CAAC;IAC5E,MAAM,GAAG,GAAG,MAAM,IAAA,gBAAU,EAAY,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAA,gBAAQ,EAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,SAAS,GAAG,MAAM,IAAA,mBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAwB,CAAC;IAC1F,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EAAC,KAAK,EAAE,aAAqB,EAAE,EAAE;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAwB,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,IAAA,0BAAe,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,KAAK,IAAI,EAAE;IACpC,MAAM,OAAO,GAAG,MAAM,IAAA,oBAAW,EAAC,QAAQ,EAAE;QAC1C,MAAM,EAAE,gBAAgB;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;KACtC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAA,+BAAuB,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxG,OAAO,OAAO,CAAC,GAAG,CAChB,CACE,MAAM,EACN,KAAK,EAML,EAAE;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE;
|
|
1
|
+
{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":";;;AAAA,yCAA4C;AAC5C,+CAAmD;AACnD,+CAA4C;AAC5C,2CAA+E;AAC/E,qCAAoD;AACpD,yCAAyC;AACzC,+BAA8E;AAO9E,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC;AAEzF;;;;GAIG;AACH,MAAM,6BAA6B,GAAG,IAAA,mBAAW,EAAC,KAAK,EAAE,IAAY,EAAE,EAAE;IACvE,MAAM,GAAG,GAAG,qCAAqC,IAAA,eAAS,EAAC,IAAI,CAAC,WAAW,CAAC;IAC5E,MAAM,GAAG,GAAG,MAAM,IAAA,gBAAU,EAAY,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAA,gBAAQ,EAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,SAAS,GAAG,MAAM,IAAA,mBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAwB,CAAC;IAC1F,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EAAC,KAAK,EAAE,aAAqB,EAAE,EAAE;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAwB,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,IAAA,0BAAe,EAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,KAAK,IAAI,EAAE;IACpC,MAAM,OAAO,GAAG,MAAM,IAAA,oBAAW,EAAC,QAAQ,EAAE;QAC1C,MAAM,EAAE,gBAAgB;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;KACtC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAA,+BAAuB,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxG,OAAO,OAAO,CAAC,GAAG,CAChB,CACE,MAAM,EACN,KAAK,EAML,EAAE;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO;gBACL,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI;gBACzB,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,UAAU;gBACnC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY;gBACvC,KAAK,EAAE,IAAI;aACZ,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI;gBACzB,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,IAAI;gBAClB,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE;aAC1B,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,QAAQ,CAAC,MAAM,CAAC,cAAc,CAC5B,gCAAgC,EAChC;IACE,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IAC7B,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC5B;CACF,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;IACZ,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,IAAA,oBAAW,EAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE,EAAE,UAAU,CAAC,CAAC;IAC1G,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;AAC3D,CAAC,CACF,CAAC;AAEF,wBAAwB;AACxB,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,4BAA4B,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE;IAC1E,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,EAAE,EAAE,EAAE,CAAC;AAC/E,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAiB,qBAAqB,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE;IACnF,MAAM,WAAW,GAAG,MAAM,IAAA,qBAAc,EAAC,yBAAiB,CAAC,CAAC;IAC5D,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;AAC5E,CAAC,CAAC,CAAC;AAEU,QAAA,iBAAiB,GAAG,IAAA,YAAK,EAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CACrE,IAAA,UAAG,EAAC,CAAC,CAAC,EAAE,EAAE;IACR,MAAM,GAAG,GAAG,IAAI,GAAG,EAA+B,CAAC;IACnD,IAAI,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC;IACnB,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;YACrC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC,EACF,IAAA,aAAM,EAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EACxB,IAAA,YAAK,EAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACtB,IAAA,kBAAW,EAAC,CAAC,CAAC,CACf,CAAC;AAEW,QAAA,qBAAqB,GAAG,yBAAiB,CAAC,IAAI,CACzD,IAAA,UAAG,EAAC,CAAC,WAAW,EAAE,EAAE;IAClB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QACjC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC,CAAC,CACH,CAAC;AAEF;;;;;;;GAOG;AACI,MAAM,uBAAuB,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;IAC5D,MAAM,UAAU,GAAG,MAAM,6BAA6B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,CAAC,UAAU;QAAE,MAAM,IAAA,gBAAQ,EAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/E,IAAI,CAAC,YAAY;QAAE,MAAM,IAAA,gBAAQ,EAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;AAC5C,CAAC,CAAC;AANW,QAAA,uBAAuB,2BAMlC","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { getCredentialId } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { ISecret, listSecrets, readSecret, writeSecret } from '@yuants/secret';\nimport { escapeSQL, requestSQL } from '@yuants/sql';\nimport { newError } from '@yuants/utils';\nimport { defer, firstValueFrom, map, repeat, retry, shareReplay } from 'rxjs';\n\ninterface IExchangeCredential {\n type: string;\n payload: any;\n}\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst credentialReader = process.env.NODE_UNIT_PUBLIC_KEY || terminal.keyPair.public_key;\n\n/**\n * 根据 secret sign 解析出对应的 exchange credential\n * 此处可以做缓存,因为同一个 secret sign 对应的 credential 信息永远不会变化,可以节约解密和后续 SQL 查询的开销\n * 得到 credential 后,此 credential 不一定是有效的,因为可能凭证信息已经过期或被撤销\n */\nconst secretSignToCredentialIdCache = createCache(async (sign: string) => {\n const sql = `SELECT * FROM secret WHERE sign = ${escapeSQL(sign)} LIMIT 1;`;\n const res = await requestSQL<ISecret[]>(terminal, sql);\n if (res.length === 0) throw newError('SECRET_NOT_FOUND', { sign });\n const secret = res[0];\n const decrypted = await readSecret(terminal, secret);\n const credential = JSON.parse(new TextDecoder().decode(decrypted)) as IExchangeCredential;\n return credential;\n});\n\n/**\n * 根据 credential 信息解析出对应的 credential ID\n * 此处可以做缓存,因为同一个 credential 永远对应同一个 credential ID,可以节约后续 SQL 查询的开销\n * 但是需要注意的是,credential ID 可能会因为凭证被撤销而失效,但是可以在下游调用其他服务时感知到,因此可以永久缓存\n */\nconst credentialIdCache = createCache(async (credentialKey: string) => {\n const credential = JSON.parse(credentialKey) as IExchangeCredential;\n const res = await getCredentialId(terminal, credential);\n return res.data;\n});\n\nconst listAllCredentials = async () => {\n const secrets = await listSecrets(terminal, {\n reader: credentialReader,\n tags: { type: 'exchange_credential' },\n });\n\n const results = await Promise.allSettled(secrets.map((secret) => getCredentialBySecretId(secret.sign)));\n return results.map(\n (\n result,\n index,\n ): {\n sign: string;\n credential: IExchangeCredential | null;\n credentialId: string | null;\n error: any;\n } => {\n if (result.status === 'fulfilled') {\n return {\n sign: secrets[index].sign,\n credential: result.value.credential,\n credentialId: result.value.credentialId,\n error: null,\n };\n } else {\n return {\n sign: secrets[index].sign,\n credential: null,\n credentialId: null,\n error: `${result.reason}`,\n };\n }\n },\n );\n};\n\nterminal.server.provideService<IExchangeCredential, ISecret>(\n 'VEX/RegisterExchangeCredential',\n {\n type: 'object',\n required: ['type', 'payload'],\n properties: {\n type: { type: 'string' },\n payload: { type: 'object' },\n },\n },\n async (msg) => {\n const credential = msg.req;\n const secretData = new TextEncoder().encode(JSON.stringify(credential));\n const secret = await writeSecret(terminal, credentialReader, { type: 'exchange_credential' }, secretData);\n return { res: { code: 0, message: 'OK', data: secret } };\n },\n);\n\n// For Debugging Purpose\nterminal.server.provideService('VEX/ListExchangeCredential', {}, async () => {\n return { res: { code: 0, message: 'OK', data: await listAllCredentials() } };\n});\n\nterminal.server.provideService<void, string[]>('VEX/ListCredentials', {}, async () => {\n const credentials = await firstValueFrom(validCredentials$);\n return { res: { code: 0, message: 'OK', data: [...credentials.keys()] } };\n});\n\nexport const validCredentials$ = defer(() => listAllCredentials()).pipe(\n map((x) => {\n const map = new Map<string, IExchangeCredential>();\n if (!x) return map;\n for (const xx of x) {\n if (xx.credentialId && xx.credential) {\n map.set(xx.credentialId, xx.credential);\n }\n }\n return map;\n }),\n repeat({ delay: 10000 }),\n retry({ delay: 5000 }),\n shareReplay(1),\n);\n\nexport const validCredentialTypes$ = validCredentials$.pipe(\n map((credentials) => {\n const types = new Set<string>();\n credentials.forEach((credential) => {\n types.add(credential.type);\n });\n return Array.from(types);\n }),\n);\n\n/**\n * 根据 secret sign 解析出对应的 credential 以及 credential ID\n * @param sign - secret sign\n * @returns 解析得到的 credential 以及对应的 credential ID\n * @throws 如果无法解析出对应的 credential 或 credential ID,则抛出异常\n *\n * 不依赖 List Credential 服务,可以及时感知凭证的新增和变更\n */\nexport const getCredentialBySecretId = async (sign: string) => {\n const credential = await secretSignToCredentialIdCache.query(sign);\n if (!credential) throw newError('CREDENTIAL_NOT_RESOLVED', { sign });\n const credentialId = await credentialIdCache.query(JSON.stringify(credential));\n if (!credentialId) throw newError('CREDENTIAL_ID_NOT_RESOLVED', { sign });\n return { sign, credential, credentialId };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":";;AAAA,uDAAiE;AACjE,mDAAyE;AACzE,+CAAkG;AAClG,+CAA4C;AAC5C,yCAAoD;AACpD,+BAAuC;AACvC,6CAAiD;AACjD,yCAA8D;AAE9D,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,8BAAiB;KACd,IAAI,CACH,IAAA,UAAG,EAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EACnC,IAAA,iBAAS,EACP,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EACZ,CAAC,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,EAAE,CAC9B,IAAI,iBAAU,CAAC,CAAC,GAAG,EAAE,EAAE;IACrB,OAAO,CAAC,IAAI,CAAC,2CAA2C,aAAa,EAAE,CAAC,CAAC;IACzE,4BAA4B;IAC5B;
|
|
1
|
+
{"version":3,"file":"legacy-services.js","sourceRoot":"","sources":["../src/legacy-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { cancelOrder, getOrders, getPositions, modifyOrder, submitOrder } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { listWatch, newError } from '@yuants/utils';\nimport { map, Observable } from 'rxjs';\nimport { validCredentials$ } from './credential';\nimport { polyfillOrders, polyfillPosition } from './position';\n\nconst terminal = Terminal.fromNodeEnv();\n\nvalidCredentials$\n .pipe(\n map((x) => Array.from(x.entries())),\n listWatch(\n ([id]) => id,\n ([credential_id, credential]) =>\n new Observable((sub) => {\n console.info(`Setting up VEX services for credential: ${credential_id}`);\n // Setup AccountInfo Service\n {\n const service = provideAccountInfoService(\n terminal,\n credential_id,\n async () => {\n const res = await getPositions(terminal, credential);\n if (!res.data) throw newError('FETCH_POSITIONS_FAILED', { credential_id, res });\n const polyfilledPositions = await polyfillPosition(res.data);\n polyfilledPositions.forEach((pos) => {\n pos.account_id = credential_id;\n });\n return polyfilledPositions;\n },\n {\n auto_refresh_interval: 1000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup Pending Orders Service\n {\n const service = providePendingOrdersService(\n terminal,\n credential_id,\n async () => {\n const res = await getOrders(terminal, credential);\n if (!res.data) throw newError('FETCH_ORDERS_FAILED', { credential_id, res });\n\n res.data.forEach((order) => {\n order.account_id = credential_id;\n });\n\n await polyfillOrders(res.data);\n\n return res.data;\n },\n {\n auto_refresh_interval: 10000,\n },\n );\n sub.add(() => {\n service.dispose$.next();\n });\n }\n // Setup SubmitOrder Service\n {\n const service = terminal.server.provideService<IOrder, { order_id: string }>(\n 'SubmitOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await submitOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup ModifyOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'ModifyOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await modifyOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n\n // Setup CancelOrder Service\n {\n const service = terminal.server.provideService<IOrder, void>(\n 'CancelOrder',\n {\n type: 'object',\n required: ['account_id'],\n properties: {\n account_id: { type: 'string', const: credential_id },\n },\n },\n async (msg) => {\n const [order] = await polyfillOrders([msg.req]);\n const res = await cancelOrder(terminal, credential, order);\n return { res };\n },\n );\n sub.add(() => {\n service.dispose();\n });\n }\n }),\n ),\n )\n .subscribe();\n"]}
|