@harperfast/harper 5.3.0-alpha.1 → 5.3.0-beta.2
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/bin/cliOperations.ts +12 -0
- package/bin/restart.ts +66 -6
- package/components/Application.ts +1134 -112
- package/components/DESIGN.md +421 -0
- package/components/OptionsWatcher.ts +368 -102
- package/components/Scope.ts +20 -1
- package/components/componentLoader.ts +43 -4
- package/components/deploymentOperations.ts +4 -1
- package/components/deploymentRecorder.ts +9 -2
- package/components/mcp/DESIGN.md +109 -0
- package/components/mcp/audit.ts +21 -17
- package/components/operations.js +284 -52
- package/components/operationsValidation.js +49 -2
- package/components/packageComponent.ts +25 -1
- package/components/requestRestart.ts +11 -0
- package/config/DESIGN.md +306 -0
- package/config/RootConfigWatcher.ts +191 -37
- package/config/configReadRetry.ts +62 -0
- package/config/configUtils.ts +78 -26
- package/config/parseConfigFile.ts +34 -0
- package/config/readConfigFileSync.ts +44 -0
- package/config/watcherArming.ts +59 -0
- package/config-root.schema.json +4 -0
- package/dataLayer/DESIGN.md +179 -0
- package/dataLayer/harperBridge/ResourceBridge.ts +28 -2
- package/dataLayer/restoreMarker.ts +92 -25
- package/dist/bin/cliOperations.js +13 -0
- package/dist/bin/cliOperations.js.map +1 -1
- package/dist/bin/restart.js +42 -6
- package/dist/bin/restart.js.map +1 -1
- package/dist/components/Application.d.ts +104 -9
- package/dist/components/Application.js +954 -102
- package/dist/components/Application.js.map +1 -1
- package/dist/components/OptionsWatcher.d.ts +4 -1
- package/dist/components/OptionsWatcher.js +378 -104
- package/dist/components/OptionsWatcher.js.map +1 -1
- package/dist/components/Scope.js +15 -1
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.js +35 -3
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/deploymentOperations.js +4 -1
- package/dist/components/deploymentOperations.js.map +1 -1
- package/dist/components/deploymentRecorder.d.ts +4 -2
- package/dist/components/deploymentRecorder.js +1 -0
- package/dist/components/deploymentRecorder.js.map +1 -1
- package/dist/components/mcp/audit.d.ts +2 -1
- package/dist/components/mcp/audit.js +21 -17
- package/dist/components/mcp/audit.js.map +1 -1
- package/dist/components/operations.d.ts +28 -0
- package/dist/components/operations.js +263 -54
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +48 -2
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/components/packageComponent.js +24 -0
- package/dist/components/packageComponent.js.map +1 -1
- package/dist/components/requestRestart.d.ts +1 -0
- package/dist/components/requestRestart.js +7 -0
- package/dist/components/requestRestart.js.map +1 -1
- package/dist/config/RootConfigWatcher.d.ts +2 -0
- package/dist/config/RootConfigWatcher.js +189 -35
- package/dist/config/RootConfigWatcher.js.map +1 -1
- package/dist/config/configReadRetry.d.ts +8 -0
- package/dist/config/configReadRetry.js +62 -0
- package/dist/config/configReadRetry.js.map +1 -0
- package/dist/config/configUtils.d.ts +10 -9
- package/dist/config/configUtils.js +63 -27
- package/dist/config/configUtils.js.map +1 -1
- package/dist/config/parseConfigFile.d.ts +4 -0
- package/dist/config/parseConfigFile.js +35 -0
- package/dist/config/parseConfigFile.js.map +1 -0
- package/dist/config/readConfigFileSync.d.ts +1 -0
- package/dist/config/readConfigFileSync.js +47 -0
- package/dist/config/readConfigFileSync.js.map +1 -0
- package/dist/config/watcherArming.d.ts +15 -0
- package/dist/config/watcherArming.js +59 -0
- package/dist/config/watcherArming.js.map +1 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.js +21 -2
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/restoreMarker.d.ts +21 -8
- package/dist/dataLayer/restoreMarker.js +94 -27
- package/dist/dataLayer/restoreMarker.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/json/systemSchema.json +3 -0
- package/dist/resources/DatabaseTransaction.d.ts +25 -0
- package/dist/resources/DatabaseTransaction.js +224 -18
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/LMDBTransaction.d.ts +2 -1
- package/dist/resources/LMDBTransaction.js +22 -3
- package/dist/resources/LMDBTransaction.js.map +1 -1
- package/dist/resources/PrimaryRocksDatabase.js +22 -6
- package/dist/resources/PrimaryRocksDatabase.js.map +1 -1
- package/dist/resources/RecordEncoder.d.ts +1 -1
- package/dist/resources/RecordEncoder.js +46 -10
- package/dist/resources/RecordEncoder.js.map +1 -1
- package/dist/resources/Resource.js +97 -13
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +8 -0
- package/dist/resources/RocksIndexStore.js +2 -1
- package/dist/resources/RocksIndexStore.js.map +1 -1
- package/dist/resources/RocksTransactionLogStore.d.ts +10 -0
- package/dist/resources/RocksTransactionLogStore.js +104 -33
- package/dist/resources/RocksTransactionLogStore.js.map +1 -1
- package/dist/resources/Table.d.ts +58 -7
- package/dist/resources/Table.js +1143 -348
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.d.ts +3 -0
- package/dist/resources/analytics/write.js +49 -16
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/auditStore.d.ts +170 -0
- package/dist/resources/auditStore.js +457 -11
- package/dist/resources/auditStore.js.map +1 -1
- package/dist/resources/crdt.d.ts +10 -0
- package/dist/resources/crdt.js +22 -0
- package/dist/resources/crdt.js.map +1 -1
- package/dist/resources/dataLoader.js +3 -4
- package/dist/resources/dataLoader.js.map +1 -1
- package/dist/resources/databases.d.ts +16 -13
- package/dist/resources/databases.js +625 -177
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/derivedIndexRegistry.d.ts +5 -0
- package/dist/resources/derivedIndexRegistry.js +68 -0
- package/dist/resources/derivedIndexRegistry.js.map +1 -0
- package/dist/resources/derivedIndexRuntime.d.ts +215 -0
- package/dist/resources/derivedIndexRuntime.js +2027 -0
- package/dist/resources/derivedIndexRuntime.js.map +1 -0
- package/dist/resources/graphql.js +3 -2
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +102 -9
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +867 -39
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
- package/dist/resources/indexes/fullTextDerivedIndex.d.ts +81 -0
- package/dist/resources/indexes/fullTextDerivedIndex.js +1004 -0
- package/dist/resources/indexes/fullTextDerivedIndex.js.map +1 -0
- package/dist/resources/indexes/fullTextNativeBinding.d.ts +78 -0
- package/dist/resources/indexes/fullTextNativeBinding.js +85 -0
- package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -0
- package/dist/resources/indexes/hnswDerivedIndex.d.ts +67 -0
- package/dist/resources/indexes/hnswDerivedIndex.js +464 -0
- package/dist/resources/indexes/hnswDerivedIndex.js.map +1 -0
- package/dist/resources/indexes/hnswPlaneBinding.d.ts +65 -0
- package/dist/resources/indexes/hnswPlaneBinding.js +91 -0
- package/dist/resources/indexes/hnswPlaneBinding.js.map +1 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +24 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +149 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -0
- package/dist/resources/nodeIdMapping.d.ts +5 -0
- package/dist/resources/nodeIdMapping.js +49 -0
- package/dist/resources/nodeIdMapping.js.map +1 -1
- package/dist/resources/recordLock.d.ts +47 -4
- package/dist/resources/recordLock.js +138 -7
- package/dist/resources/recordLock.js.map +1 -1
- package/dist/resources/recordLockCoordinator.d.ts +557 -0
- package/dist/resources/recordLockCoordinator.js +2597 -0
- package/dist/resources/recordLockCoordinator.js.map +1 -0
- package/dist/resources/replayLogs.js +5 -0
- package/dist/resources/replayLogs.js.map +1 -1
- package/dist/resources/replicatedApplyFailure.d.ts +16 -0
- package/dist/resources/replicatedApplyFailure.js +63 -0
- package/dist/resources/replicatedApplyFailure.js.map +1 -0
- package/dist/resources/scheduler/scheduler.js +3 -3
- package/dist/resources/scheduler/scheduler.js.map +1 -1
- package/dist/resources/search.d.ts +10 -4
- package/dist/resources/search.js +160 -40
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/tracked.d.ts +5 -1
- package/dist/resources/tracked.js +74 -23
- package/dist/resources/tracked.js.map +1 -1
- package/dist/resources/transactionBroadcast.js +4 -6
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/security/auth.js +59 -23
- package/dist/security/auth.js.map +1 -1
- package/dist/security/deferredAuthentication.d.ts +11 -0
- package/dist/security/deferredAuthentication.js +25 -3
- package/dist/security/deferredAuthentication.js.map +1 -1
- package/dist/security/jsLoader.js +9 -4
- package/dist/security/jsLoader.js.map +1 -1
- package/dist/server/REST.js +39 -5
- package/dist/server/REST.js.map +1 -1
- package/dist/server/http.d.ts +5 -1
- package/dist/server/http.js +34 -2
- package/dist/server/http.js.map +1 -1
- package/dist/server/mqtt.js +5 -1
- package/dist/server/mqtt.js.map +1 -1
- package/dist/server/serverHelpers/Headers.d.ts +2 -0
- package/dist/server/serverHelpers/Headers.js +6 -0
- package/dist/server/serverHelpers/Headers.js.map +1 -1
- package/dist/server/serverHelpers/NodeAdapterResponse.d.ts +48 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js +220 -0
- package/dist/server/serverHelpers/NodeAdapterResponse.js.map +1 -0
- package/dist/server/serverHelpers/Request.d.ts +5 -10
- package/dist/server/serverHelpers/Request.js +38 -136
- package/dist/server/serverHelpers/Request.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.d.ts +2 -0
- package/dist/server/serverHelpers/contentTypes.js +189 -15
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/serverUtilities.d.ts +3 -3
- package/dist/server/serverHelpers/serverUtilities.js +110 -20
- package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/server/serverHelpers/uwsServer.js +4 -1
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/serverHelpers/webSocketCloseReason.d.ts +2 -0
- package/dist/server/serverHelpers/webSocketCloseReason.js +29 -0
- package/dist/server/serverHelpers/webSocketCloseReason.js.map +1 -0
- package/dist/server/storageReclamation.js +1 -1
- package/dist/server/storageReclamation.js.map +1 -1
- package/dist/server/threads/isolatedApplications.d.ts +47 -0
- package/dist/server/threads/isolatedApplications.js +171 -0
- package/dist/server/threads/isolatedApplications.js.map +1 -0
- package/dist/server/threads/logRotationTransport.d.ts +1 -0
- package/dist/server/threads/logRotationTransport.js +33 -0
- package/dist/server/threads/logRotationTransport.js.map +1 -0
- package/dist/server/threads/manageThreads.d.ts +64 -6
- package/dist/server/threads/manageThreads.js +261 -12
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/server/threads/socketRouter.d.ts +1 -0
- package/dist/server/threads/socketRouter.js +196 -13
- package/dist/server/threads/socketRouter.js.map +1 -1
- package/dist/server/threads/threadServer.js +30 -7
- package/dist/server/threads/threadServer.js.map +1 -1
- package/dist/utility/errors/hdbError.d.ts +24 -0
- package/dist/utility/errors/hdbError.js +58 -1
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/utility/hdbTerms.d.ts +2 -0
- package/dist/utility/hdbTerms.js +2 -0
- package/dist/utility/hdbTerms.js.map +1 -1
- package/dist/utility/logging/harper_logger.js +218 -38
- package/dist/utility/logging/harper_logger.js.map +1 -1
- package/dist/utility/logging/logGenerationCoordinator.d.ts +35 -0
- package/dist/utility/logging/logGenerationCoordinator.js +184 -0
- package/dist/utility/logging/logGenerationCoordinator.js.map +1 -0
- package/dist/utility/logging/logRotation.d.ts +46 -0
- package/dist/utility/logging/logRotation.js +365 -0
- package/dist/utility/logging/logRotation.js.map +1 -0
- package/dist/utility/logging/logRotator.d.ts +1 -1
- package/dist/utility/logging/logRotator.js +172 -92
- package/dist/utility/logging/logRotator.js.map +1 -1
- package/dist/utility/npmUtilities.js +6 -4
- package/dist/utility/npmUtilities.js.map +1 -1
- package/dist/utility/watcherFallback.d.ts +0 -45
- package/dist/utility/watcherFallback.js +1 -125
- package/dist/utility/watcherFallback.js.map +1 -1
- package/dist/validation/configValidator.js +6 -3
- package/dist/validation/configValidator.js.map +1 -1
- package/index.ts +9 -0
- package/json/systemSchema.json +3 -0
- package/npm-shrinkwrap.json +177 -87
- package/package.json +13 -5
- package/resources/DESIGN.md +689 -19
- package/resources/DatabaseTransaction.ts +230 -17
- package/resources/LMDBTransaction.ts +21 -3
- package/resources/PrimaryRocksDatabase.ts +20 -7
- package/resources/RecordEncoder.ts +52 -10
- package/resources/Resource.ts +97 -13
- package/resources/ResourceInterface.ts +8 -0
- package/resources/RocksIndexStore.ts +2 -1
- package/resources/RocksTransactionLogStore.ts +111 -31
- package/resources/Table.ts +1273 -396
- package/resources/analytics/DESIGN.md +38 -0
- package/resources/analytics/write.ts +50 -17
- package/resources/auditStore.ts +460 -11
- package/resources/crdt.ts +22 -0
- package/resources/dataLoader.ts +3 -4
- package/resources/databases.ts +611 -147
- package/resources/derivedIndexRegistry.ts +56 -0
- package/resources/derivedIndexRuntime.ts +2292 -0
- package/resources/graphql.ts +3 -2
- package/resources/indexes/DESIGN.md +833 -0
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +924 -46
- package/resources/indexes/fullTextDerivedIndex.ts +1165 -0
- package/resources/indexes/fullTextNativeBinding.ts +146 -0
- package/resources/indexes/hnswDerivedIndex.ts +531 -0
- package/resources/indexes/hnswPlaneBinding.ts +174 -0
- package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +181 -0
- package/resources/nodeIdMapping.ts +50 -0
- package/resources/record-locks.md +1407 -0
- package/resources/recordLock.ts +173 -7
- package/resources/recordLockCoordinator.ts +3082 -0
- package/resources/replayLogs.ts +5 -0
- package/resources/replicatedApplyFailure.ts +77 -0
- package/resources/scheduler/DESIGN.md +40 -0
- package/resources/scheduler/scheduler.ts +4 -4
- package/resources/search.ts +169 -49
- package/resources/tracked.ts +73 -22
- package/resources/transactionBroadcast.ts +4 -4
- package/security/DESIGN.md +175 -0
- package/security/auth.ts +53 -24
- package/security/deferredAuthentication.ts +24 -2
- package/security/jsLoader.ts +9 -4
- package/server/DESIGN.md +275 -0
- package/server/REST.ts +42 -6
- package/server/http.ts +34 -2
- package/server/mqtt.ts +6 -4
- package/server/serverHelpers/Headers.ts +5 -1
- package/server/serverHelpers/NodeAdapterResponse.ts +221 -0
- package/server/serverHelpers/Request.ts +33 -131
- package/server/serverHelpers/contentTypes.ts +188 -15
- package/server/serverHelpers/serverUtilities.ts +157 -27
- package/server/serverHelpers/uwsServer.ts +4 -1
- package/server/serverHelpers/webSocketCloseReason.ts +25 -0
- package/server/storageReclamation.ts +2 -2
- package/server/threads/isolatedApplications.ts +157 -0
- package/server/threads/logRotationTransport.ts +40 -0
- package/server/threads/manageThreads.js +254 -12
- package/server/threads/socketRouter.ts +217 -11
- package/server/threads/threadServer.js +30 -7
- package/studio/web/assets/{Chat-BnCBegQz.js → Chat-DADFFGe_.js} +1 -1
- package/studio/web/assets/{FloatingChat-CoDW1ySS.js → FloatingChat-D_mI-rZ7.js} +3 -3
- package/studio/web/assets/{apiToken-Bwk5BLXW.js → apiToken-c2NiSDHa.js} +1 -1
- package/studio/web/assets/{applications-DHxGi7JH.js → applications-DktUqh7G.js} +1 -1
- package/studio/web/assets/{cssMode-s0cWI-_M.js → cssMode-Cs_75Xhw.js} +1 -1
- package/studio/web/assets/{editor-DNcRHK54.js → editor-19b-Y1IN.js} +1 -1
- package/studio/web/assets/{html-Bdssedlg.js → html-DiYEQMpB.js} +1 -1
- package/studio/web/assets/{htmlMode-CoDlJ3fw.js → htmlMode-CmR0y7P_.js} +1 -1
- package/studio/web/assets/{index-D6sxmFLR.js → index-Dm0rfkJ7.js} +5 -5
- package/studio/web/assets/{index.lazy-tmU5BS8s.js → index.lazy-7vqt2CC3.js} +1 -1
- package/studio/web/assets/{javascript-B8meVSTH.js → javascript-BWtCFuOt.js} +1 -1
- package/studio/web/assets/{jsonMode-DpIPd35T.js → jsonMode-Buzzbv9y.js} +1 -1
- package/studio/web/assets/{languageServices-C_5FMJzQ.js → languageServices-SqsFWfTM.js} +1 -1
- package/studio/web/assets/{lspLanguageFeatures-BIzNBzPK.js → lspLanguageFeatures-EMV5cmjo.js} +1 -1
- package/studio/web/assets/{notifications-CvZivSbh.js → notifications-CAB-LZWT.js} +1 -1
- package/studio/web/assets/{notifications-CQf18QKb.js → notifications-DRzmSRxM.js} +1 -1
- package/studio/web/assets/{profile-DdOwtntb.js → profile-BNKAl79n.js} +1 -1
- package/studio/web/assets/{regions-n69fwagr.js → regions-CUow_Zw2.js} +1 -1
- package/studio/web/assets/{register-PfWTCXWB.js → register-Dkt3WUMp.js} +2 -2
- package/studio/web/assets/{setComponentFile-Bg6O7X0S.js → setComponentFile-BZRfMD0N.js} +1 -1
- package/studio/web/assets/{setup-CUx_aUDl.js → setup-D_yiEPO2.js} +2 -2
- package/studio/web/assets/{status-D7BVKqX9.js → status-DhHh1Ge-.js} +1 -1
- package/studio/web/assets/{toggleHighContrast-DBSyXzMr.js → toggleHighContrast-D7L1PDtV.js} +1 -1
- package/studio/web/assets/{tsMode-BByKCjBS.js → tsMode-CCwLk1YS.js} +1 -1
- package/studio/web/assets/{typescript-DDLnLpw9.js → typescript-BP1j1mjn.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-31CHGaHk.js → useEntityRestURL-D7bnYxLw.js} +1 -1
- package/studio/web/assets/{workers-pR3jRY9D.js → workers-tOuCNT17.js} +1 -1
- package/studio/web/assets/{xml-2iRnMhQO.js → xml-BSG_3mQT.js} +1 -1
- package/studio/web/assets/{yaml-Bf92gJpd.js → yaml-DxiLprBB.js} +1 -1
- package/studio/web/index.html +1 -1
- package/utility/DESIGN.md +55 -0
- package/utility/errors/hdbError.ts +54 -0
- package/utility/hdbTerms.ts +2 -0
- package/utility/logging/harper_logger.ts +210 -30
- package/utility/logging/logGenerationCoordinator.ts +196 -0
- package/utility/logging/logRotation.ts +367 -0
- package/utility/logging/logRotator.ts +196 -91
- package/utility/npmUtilities.ts +6 -4
- package/utility/watcherFallback.ts +0 -122
- package/validation/configValidator.ts +6 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# resources/analytics/ — Design notes
|
|
2
|
+
|
|
3
|
+
Analytics recording and aggregation.
|
|
4
|
+
|
|
5
|
+
**Read this when:** touching `write.ts` aggregation or the raw-analytics cursor.
|
|
6
|
+
|
|
7
|
+
Index of every design note: [DESIGN.md](../../DESIGN.md).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Analytics aggregation resumes from a raw cursor, which is not a clock (`resources/analytics/write.ts`)
|
|
12
|
+
|
|
13
|
+
`aggregation()` rolls up the raw reports in `hdb_raw_analytics` one `toPeriod` window at a time —
|
|
14
|
+
it stops at `firstForPeriod + toPeriod` so one cycle's main-thread msgpackr decode stays bounded
|
|
15
|
+
(#1538) — and resumes, exclusive, from `rawCursor`. Two rules hold that cursor:
|
|
16
|
+
|
|
17
|
+
- **It only ever moves to a record a cycle actually read.** It used to be one variable with the
|
|
18
|
+
cadence marker, stamped with the cycle's end-of-run `Date.now()`, which discarded the remainder of
|
|
19
|
+
a backlog longer than one window and every report written while the cycle ran, because nothing
|
|
20
|
+
reads below the cursor again.
|
|
21
|
+
- **A cycle that reads nothing leaves it where it is.** An empty scan is not proof that nothing is
|
|
22
|
+
there: `recordAnalytics` does not await its `primaryStore.put`, so a report can be uncommitted and
|
|
23
|
+
invisible to the scan while carrying a key older than anything the cycle could compare against. No
|
|
24
|
+
wall-clock reading is safe to put in the cursor for the same reason.
|
|
25
|
+
|
|
26
|
+
`lastAggregationTime` stays a pure cadence marker, stamped `now` at the end of every completed
|
|
27
|
+
cycle, so an idle node still aggregates once per period (#1538). A cycle that stopped at its window
|
|
28
|
+
edge sets `aggregationBehind`, which lets the next tick skip that guard: a backlog then drains one
|
|
29
|
+
window per half-period tick instead of waiting out the cadence it is already behind on.
|
|
30
|
+
|
|
31
|
+
Cycles must not overlap. `setInterval` does not await its async callback, so `runAggregationCycle`
|
|
32
|
+
holds a single-flight flag — two cycles reading the same cursor roll the same window up twice and
|
|
33
|
+
double every count in it.
|
|
34
|
+
|
|
35
|
+
Still open: `findLastAggregationTime` seeds both markers after a restart from the newest stored
|
|
36
|
+
analytics record, whose `time` is an end-of-cycle stamp, so a restart mid-drain can skip the rest of
|
|
37
|
+
the backlog; and `storeMetric` discards `table.put()`'s result, so the cursor advances past raw
|
|
38
|
+
records whose aggregate rows failed to commit. Both need a cursor persisted with the rows.
|
|
@@ -157,6 +157,10 @@ function sendAnalytics() {
|
|
|
157
157
|
analyticsStart ||= performance.now();
|
|
158
158
|
sendAnalyticsTimeout = setTimeout(async () => {
|
|
159
159
|
sendAnalyticsTimeout = null;
|
|
160
|
+
// Rotate before the first yield below: a sample recorded mid-flush would otherwise be added to
|
|
161
|
+
// an entry already reported, and dropped with it.
|
|
162
|
+
const reportingActions = activeActions;
|
|
163
|
+
activeActions = new Map();
|
|
160
164
|
const period = performance.now() - analyticsStart;
|
|
161
165
|
analyticsStart = 0;
|
|
162
166
|
const metrics = [];
|
|
@@ -166,7 +170,7 @@ function sendAnalytics() {
|
|
|
166
170
|
threadId,
|
|
167
171
|
metrics,
|
|
168
172
|
};
|
|
169
|
-
for (const [_name, action] of
|
|
173
|
+
for (const [_name, action] of reportingActions) {
|
|
170
174
|
if (action.values) {
|
|
171
175
|
const values = action.values.subarray(0, (action.values as any).index);
|
|
172
176
|
values.sort();
|
|
@@ -239,7 +243,6 @@ function sendAnalytics() {
|
|
|
239
243
|
for (const listener of analyticsListeners) {
|
|
240
244
|
listener(metrics);
|
|
241
245
|
}
|
|
242
|
-
activeActions = new Map();
|
|
243
246
|
if (parentPort)
|
|
244
247
|
parentPort.postMessage({
|
|
245
248
|
type: ANALYTICS_REPORT_TYPE,
|
|
@@ -874,6 +877,12 @@ async function storeNodeStorageMetric(analyticsTable: Table) {
|
|
|
874
877
|
const MAX_LAST_AGGREGATION_SCAN = 1000;
|
|
875
878
|
// Time of this node's last completed aggregation, tracked in O(1) across cycles within a process.
|
|
876
879
|
let lastAggregationTime: number | undefined;
|
|
880
|
+
// Resume point into the raw analytics table: it moves only over records a cycle read, so it is not
|
|
881
|
+
// a clock and never passes an unread report.
|
|
882
|
+
let rawCursor: number | undefined;
|
|
883
|
+
// A cycle stopped at its window edge with raw records still behind it, so the next one skips the
|
|
884
|
+
// cadence guard and drains the next window.
|
|
885
|
+
let aggregationBehind = false;
|
|
877
886
|
|
|
878
887
|
/**
|
|
879
888
|
* Find the time of the local node's most recent aggregation record by scanning back from the
|
|
@@ -898,13 +907,31 @@ export function findLastAggregationTime(
|
|
|
898
907
|
return undefined;
|
|
899
908
|
}
|
|
900
909
|
|
|
910
|
+
let aggregationRunning = false;
|
|
911
|
+
|
|
912
|
+
/** Two cycles reading the same cursor roll the same window up twice, and the scheduler does not
|
|
913
|
+
* await its callback. */
|
|
914
|
+
export async function runAggregationCycle(fromPeriod, toPeriod = 60000) {
|
|
915
|
+
if (aggregationRunning) return;
|
|
916
|
+
aggregationRunning = true;
|
|
917
|
+
try {
|
|
918
|
+
await aggregation(fromPeriod, toPeriod);
|
|
919
|
+
} finally {
|
|
920
|
+
aggregationRunning = false;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
901
924
|
async function aggregation(fromPeriod, toPeriod = 60000) {
|
|
902
925
|
const rawAnalyticsTable = getRawAnalyticsTable();
|
|
903
926
|
const analyticsTable = getAnalyticsTable();
|
|
904
927
|
const taskQueueLatency = (async () => {
|
|
905
928
|
const start = performance.now();
|
|
906
929
|
// measure how long it takes to enqueue and get a callback from a simple/fast task:
|
|
907
|
-
|
|
930
|
+
// The result is discarded — only the round trip is being measured — so a missing file is not a
|
|
931
|
+
// failure. It rejects whenever the probe races a rotation, which the write-path size guard
|
|
932
|
+
// makes a routine event rather than a once-a-minute one, and an unhandled rejection here takes
|
|
933
|
+
// the process down over a latency measurement.
|
|
934
|
+
await stat(getLogFilePath()).catch(() => {});
|
|
908
935
|
const delay = performance.now() - start;
|
|
909
936
|
if (delay > 5000) {
|
|
910
937
|
log.warn?.('Unusually high task queue latency on the main thread of ' + Math.round(delay) + 'ms');
|
|
@@ -917,28 +944,35 @@ async function aggregation(fromPeriod, toPeriod = 60000) {
|
|
|
917
944
|
// first never touch the table. On the first cycle after boot we seed it once from the table
|
|
918
945
|
// via a bounded reverse scan (see findLastAggregationTime). Caching the seeded value keeps
|
|
919
946
|
// the next cycle O(1) even when this run early-returns below as "too recent"; a bound-hit
|
|
920
|
-
// (no match) leaves it undefined so we don't early-return, proceed to aggregate, and
|
|
921
|
-
// marker
|
|
947
|
+
// (no match) leaves it undefined so we don't early-return, proceed to aggregate, and stamp the
|
|
948
|
+
// cadence marker at the end of the cycle instead (#1538).
|
|
922
949
|
let lastForPeriod = lastAggregationTime;
|
|
923
950
|
if (lastForPeriod === undefined) {
|
|
924
951
|
lastForPeriod = findLastAggregationTime(analyticsTable.primaryStore, localNodeId);
|
|
925
|
-
if (lastForPeriod !== undefined)
|
|
952
|
+
if (lastForPeriod !== undefined) {
|
|
953
|
+
lastAggregationTime = lastForPeriod;
|
|
954
|
+
rawCursor ??= lastForPeriod;
|
|
955
|
+
}
|
|
926
956
|
}
|
|
927
957
|
// was the last aggregation too recent to calculate a whole period?
|
|
928
|
-
if (lastForPeriod !== undefined && Date.now() - toPeriod < lastForPeriod) return;
|
|
958
|
+
if (!aggregationBehind && lastForPeriod !== undefined && Date.now() - toPeriod < lastForPeriod) return;
|
|
929
959
|
let firstForPeriod;
|
|
930
960
|
const aggregateActions = new Map();
|
|
931
961
|
const distributions = new Map();
|
|
932
962
|
const threadsToAverage = [];
|
|
933
|
-
let lastTime: number;
|
|
963
|
+
let lastTime: number | undefined;
|
|
964
|
+
let stoppedAtWindowEdge = false;
|
|
934
965
|
for (const { key, value } of rawAnalyticsTable.primaryStore.getRange({
|
|
935
|
-
start:
|
|
966
|
+
start: rawCursor || false,
|
|
936
967
|
exclusiveStart: true,
|
|
937
968
|
end: Infinity,
|
|
938
969
|
})) {
|
|
939
970
|
if (!value) continue;
|
|
940
971
|
if (firstForPeriod) {
|
|
941
|
-
if (key > firstForPeriod + toPeriod)
|
|
972
|
+
if (key > firstForPeriod + toPeriod) {
|
|
973
|
+
stoppedAtWindowEdge = true;
|
|
974
|
+
break; // outside the period of interest
|
|
975
|
+
}
|
|
942
976
|
} else firstForPeriod = key;
|
|
943
977
|
lastTime = key;
|
|
944
978
|
const { metrics, threadId } = value;
|
|
@@ -1084,12 +1118,11 @@ async function aggregation(fromPeriod, toPeriod = 60000) {
|
|
|
1084
1118
|
};
|
|
1085
1119
|
storeMetric(analyticsTable, cruMetric);
|
|
1086
1120
|
lastResourceUsage = resourceUsage;
|
|
1087
|
-
//
|
|
1088
|
-
//
|
|
1089
|
-
//
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
// scan-based behavior rather than letting a stale marker run aggregation on every tick (#1538).
|
|
1121
|
+
// The cursor may only pass records this cycle read, and nothing reads below it again: the scan
|
|
1122
|
+
// covers one `toPeriod` window, and a raw report whose `put` has not committed is invisible to
|
|
1123
|
+
// it however recent its key is. An empty scan therefore leaves the cursor where it was.
|
|
1124
|
+
if (lastTime !== undefined) rawCursor = lastTime;
|
|
1125
|
+
aggregationBehind = stoppedAtWindowEdge;
|
|
1093
1126
|
lastAggregationTime = now;
|
|
1094
1127
|
|
|
1095
1128
|
// `system` is set as non-enumerable on the object returned by getDatabases() so most
|
|
@@ -1201,7 +1234,7 @@ function startScheduledTasks() {
|
|
|
1201
1234
|
const aggregateRetentionMs = envGet(CONFIG_PARAMS.ANALYTICS_AGGREGATERETENTIONMS) ?? AGGREGATE_EXPIRATION;
|
|
1202
1235
|
setInterval(
|
|
1203
1236
|
async () => {
|
|
1204
|
-
await
|
|
1237
|
+
await runAggregationCycle(analyticsDelay, AGGREGATE_PERIOD);
|
|
1205
1238
|
await cleanup(getRawAnalyticsTable(), rawRetentionMs);
|
|
1206
1239
|
// 0 means "keep forever" — skip aggregate cleanup, matching storageInterval: 0 convention
|
|
1207
1240
|
if (aggregateRetentionMs) await cleanup(getAnalyticsTable(), aggregateRetentionMs);
|