@synnaxlabs/client 0.56.2 → 0.57.0
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/client-B08VDLSA.js +14463 -0
- package/dist/client-B08VDLSA.js.map +1 -0
- package/dist/client.js +1128 -14876
- package/dist/client.js.map +1 -0
- package/dist/src/access/client.d.ts +10 -1
- package/dist/src/access/client.d.ts.map +1 -1
- package/dist/src/access/enforce.d.ts.map +1 -1
- package/dist/src/access/external.d.ts +1 -0
- package/dist/src/access/external.d.ts.map +1 -1
- package/dist/src/access/granted.d.ts +39 -0
- package/dist/src/access/granted.d.ts.map +1 -0
- package/dist/src/access/policy/client.d.ts +136 -147
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/types.gen.d.ts +15 -68
- package/dist/src/access/policy/types.gen.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts +77 -58
- package/dist/src/access/role/client.d.ts.map +1 -1
- package/dist/src/access/role/types.gen.d.ts +8 -14
- package/dist/src/access/role/types.gen.d.ts.map +1 -1
- package/dist/src/actions/actions.d.ts +5 -6
- package/dist/src/actions/actions.d.ts.map +1 -1
- package/dist/src/actions/controller.d.ts +194 -0
- package/dist/src/actions/controller.d.ts.map +1 -0
- package/dist/src/actions/external.d.ts +1 -0
- package/dist/src/actions/external.d.ts.map +1 -1
- package/dist/src/arc/actions.d.ts +575 -0
- package/dist/src/arc/actions.d.ts.map +1 -0
- package/dist/src/arc/actions.gen.d.ts +1439 -0
- package/dist/src/arc/actions.gen.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts +97 -13
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/compiler/types.gen.d.ts +3 -3
- package/dist/src/arc/compiler/types.gen.d.ts.map +1 -1
- package/dist/src/arc/external.d.ts +2 -0
- package/dist/src/arc/external.d.ts.map +1 -1
- package/dist/src/arc/graph/types.gen.d.ts +45 -597
- package/dist/src/arc/graph/types.gen.d.ts.map +1 -1
- package/dist/src/arc/ir/index.d.ts +1 -1
- package/dist/src/arc/ir/index.d.ts.map +1 -1
- package/dist/src/arc/ir/ir.d.ts +2 -0
- package/dist/src/arc/ir/ir.d.ts.map +1 -0
- package/dist/src/arc/ir/types.gen.d.ts +58 -2807
- package/dist/src/arc/ir/types.gen.d.ts.map +1 -1
- package/dist/src/arc/module/types.gen.d.ts +18 -1090
- package/dist/src/arc/module/types.gen.d.ts.map +1 -1
- package/dist/src/arc/program/types.gen.d.ts +18 -1090
- package/dist/src/arc/program/types.gen.d.ts.map +1 -1
- package/dist/src/arc/text/types.gen.d.ts +54 -1
- package/dist/src/arc/text/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types/types.gen.d.ts +35 -153
- package/dist/src/arc/types/types.gen.d.ts.map +1 -1
- package/dist/src/arc/types.gen.d.ts +98 -2278
- package/dist/src/arc/types.gen.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +14 -2
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/client.d.ts +113 -75
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/external.d.ts +0 -1
- package/dist/src/channel/external.d.ts.map +1 -1
- package/dist/src/channel/payload.d.ts +65 -56
- package/dist/src/channel/payload.d.ts.map +1 -1
- package/dist/src/channel/types.gen.d.ts +26 -73
- package/dist/src/channel/types.gen.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts +1 -3
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +55 -27
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/client.d.ts +146 -0
- package/dist/src/connection/client.d.ts.map +1 -0
- package/dist/src/connection/external.d.ts +3 -0
- package/dist/src/connection/external.d.ts.map +1 -0
- package/dist/src/connection/index.d.ts +1 -1
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/status.d.ts +252 -0
- package/dist/src/connection/status.d.ts.map +1 -0
- package/dist/src/control/client.d.ts +31 -7
- package/dist/src/control/client.d.ts.map +1 -1
- package/dist/src/control/state.d.ts +47 -16
- package/dist/src/control/state.d.ts.map +1 -1
- package/dist/src/device/client.d.ts +59 -17
- package/dist/src/device/client.d.ts.map +1 -1
- package/dist/src/device/types.gen.d.ts +17 -67
- package/dist/src/device/types.gen.d.ts.map +1 -1
- package/dist/src/errors.d.ts +17 -20
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/ethercat/external.d.ts +2 -0
- package/dist/src/ethercat/external.d.ts.map +1 -0
- package/dist/src/ethercat/index.d.ts +2 -0
- package/dist/src/ethercat/index.d.ts.map +1 -0
- package/dist/src/ethercat/types.gen.d.ts +243 -0
- package/dist/src/ethercat/types.gen.d.ts.map +1 -0
- package/dist/src/framer/adapter.d.ts +8 -5
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/benchutil.d.ts +19 -0
- package/dist/src/framer/benchutil.d.ts.map +1 -0
- package/dist/src/framer/cache/cache.d.ts +38 -0
- package/dist/src/framer/cache/cache.d.ts.map +1 -0
- package/dist/src/framer/cache/dynamic.d.ts +71 -0
- package/dist/src/framer/cache/dynamic.d.ts.map +1 -0
- package/dist/src/framer/cache/reader.d.ts +43 -0
- package/dist/src/framer/cache/reader.d.ts.map +1 -0
- package/dist/src/framer/cache/static.d.ts +66 -0
- package/dist/src/framer/cache/static.d.ts.map +1 -0
- package/dist/src/framer/cache/streamer.d.ts +86 -0
- package/dist/src/framer/cache/streamer.d.ts.map +1 -0
- package/dist/src/framer/cache/transform.d.ts +18 -0
- package/dist/src/framer/cache/transform.d.ts.map +1 -0
- package/dist/src/framer/cache/unary.d.ts +37 -0
- package/dist/src/framer/cache/unary.d.ts.map +1 -0
- package/dist/src/framer/client.d.ts +35 -14
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/codec.d.ts.map +1 -1
- package/dist/src/framer/deleter.d.ts +3 -2
- package/dist/src/framer/deleter.d.ts.map +1 -1
- package/dist/src/framer/external.d.ts +6 -0
- package/dist/src/framer/external.d.ts.map +1 -1
- package/dist/src/framer/feed.d.ts +40 -0
- package/dist/src/framer/feed.d.ts.map +1 -0
- package/dist/src/framer/frame.d.ts +16 -20
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/hardened.d.ts +70 -0
- package/dist/src/framer/hardened.d.ts.map +1 -0
- package/dist/src/framer/iterator.d.ts +36 -43
- package/dist/src/framer/iterator.d.ts.map +1 -1
- package/dist/src/framer/reader.d.ts +3 -2
- package/dist/src/framer/reader.d.ts.map +1 -1
- package/dist/src/framer/streamer.d.ts +132 -205
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +130 -161
- package/dist/src/framer/writer.d.ts.map +1 -1
- package/dist/src/group/client.d.ts +66 -9
- package/dist/src/group/client.d.ts.map +1 -1
- package/dist/src/group/types.gen.d.ts +2 -2
- package/dist/src/http/external.d.ts +2 -0
- package/dist/src/http/external.d.ts.map +1 -0
- package/dist/src/http/index.d.ts +2 -0
- package/dist/src/http/index.d.ts.map +1 -0
- package/dist/src/http/types.gen.d.ts +451 -0
- package/dist/src/http/types.gen.d.ts.map +1 -0
- package/dist/src/imex/client.d.ts +88 -0
- package/dist/src/imex/client.d.ts.map +1 -0
- package/dist/src/imex/index.d.ts +2 -0
- package/dist/src/imex/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +18 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/client.d.ts +55 -36
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/label/external.d.ts +2 -0
- package/dist/src/label/external.d.ts.map +1 -1
- package/dist/src/label/payload.d.ts +4 -46
- package/dist/src/label/payload.d.ts.map +1 -1
- package/dist/src/label/store.d.ts +8 -0
- package/dist/src/label/store.d.ts.map +1 -0
- package/dist/src/label/types.gen.d.ts +45 -0
- package/dist/src/label/types.gen.d.ts.map +1 -0
- package/dist/src/labjack/external.d.ts +2 -0
- package/dist/src/labjack/external.d.ts.map +1 -0
- package/dist/src/labjack/index.d.ts +2 -0
- package/dist/src/labjack/index.d.ts.map +1 -0
- package/dist/src/labjack/types.gen.d.ts +442 -0
- package/dist/src/labjack/types.gen.d.ts.map +1 -0
- package/dist/src/lineplot/actions.d.ts +914 -0
- package/dist/src/lineplot/actions.d.ts.map +1 -0
- package/dist/src/lineplot/actions.gen.d.ts +4208 -0
- package/dist/src/lineplot/actions.gen.d.ts.map +1 -0
- package/dist/src/lineplot/client.d.ts +66 -16
- package/dist/src/lineplot/client.d.ts.map +1 -1
- package/dist/src/lineplot/external.d.ts +3 -0
- package/dist/src/lineplot/external.d.ts.map +1 -1
- package/dist/src/lineplot/line.d.ts +16 -0
- package/dist/src/lineplot/line.d.ts.map +1 -0
- package/dist/src/lineplot/types.gen.d.ts +837 -14
- package/dist/src/lineplot/types.gen.d.ts.map +1 -1
- package/dist/src/log/actions.d.ts +271 -0
- package/dist/src/log/actions.d.ts.map +1 -0
- package/dist/src/log/actions.gen.d.ts +1529 -0
- package/dist/src/log/actions.gen.d.ts.map +1 -0
- package/dist/src/log/client.d.ts +66 -16
- package/dist/src/log/client.d.ts.map +1 -1
- package/dist/src/log/external.d.ts +2 -0
- package/dist/src/log/external.d.ts.map +1 -1
- package/dist/src/log/types.gen.d.ts +139 -14
- package/dist/src/log/types.gen.d.ts.map +1 -1
- package/dist/src/modbus/external.d.ts +2 -0
- package/dist/src/modbus/external.d.ts.map +1 -0
- package/dist/src/modbus/index.d.ts +2 -0
- package/dist/src/modbus/index.d.ts.map +1 -0
- package/dist/src/modbus/types.gen.d.ts +280 -0
- package/dist/src/modbus/types.gen.d.ts.map +1 -0
- package/dist/src/ni/external.d.ts +2 -0
- package/dist/src/ni/external.d.ts.map +1 -0
- package/dist/src/ni/index.d.ts +2 -0
- package/dist/src/ni/index.d.ts.map +1 -0
- package/dist/src/ni/types.gen.d.ts +21029 -0
- package/dist/src/ni/types.gen.d.ts.map +1 -0
- package/dist/src/node/index.d.ts +2 -0
- package/dist/src/node/index.d.ts.map +1 -0
- package/dist/src/node/types.gen.d.ts +4 -0
- package/dist/src/node/types.gen.d.ts.map +1 -0
- package/dist/src/ontology/client.d.ts +314 -67
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/external.d.ts +1 -0
- package/dist/src/ontology/external.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +60 -18
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/store.d.ts +32 -0
- package/dist/src/ontology/store.d.ts.map +1 -0
- package/dist/src/ontology/types.gen.d.ts +3 -2
- package/dist/src/ontology/types.gen.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +16 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/opcua/external.d.ts +2 -0
- package/dist/src/opcua/external.d.ts.map +1 -0
- package/dist/src/opcua/index.d.ts +2 -0
- package/dist/src/opcua/index.d.ts.map +1 -0
- package/dist/src/opcua/types.gen.d.ts +82 -0
- package/dist/src/opcua/types.gen.d.ts.map +1 -0
- package/dist/src/pagerduty/external.d.ts +2 -0
- package/dist/src/pagerduty/external.d.ts.map +1 -0
- package/dist/src/pagerduty/index.d.ts +2 -0
- package/dist/src/pagerduty/index.d.ts.map +1 -0
- package/dist/src/pagerduty/types.gen.d.ts +30 -0
- package/dist/src/pagerduty/types.gen.d.ts.map +1 -0
- package/dist/src/panel/actions.d.ts +273 -0
- package/dist/src/panel/actions.d.ts.map +1 -0
- package/dist/src/panel/actions.gen.d.ts +1255 -0
- package/dist/src/panel/actions.gen.d.ts.map +1 -0
- package/dist/src/panel/client.d.ts +148 -0
- package/dist/src/panel/client.d.ts.map +1 -0
- package/dist/src/panel/external.d.ts +6 -0
- package/dist/src/panel/external.d.ts.map +1 -0
- package/dist/src/panel/index.d.ts +2 -0
- package/dist/src/panel/index.d.ts.map +1 -0
- package/dist/src/panel/tree.d.ts +50 -0
- package/dist/src/panel/tree.d.ts.map +1 -0
- package/dist/src/panel/types.gen.d.ts +370 -0
- package/dist/src/panel/types.gen.d.ts.map +1 -0
- package/dist/src/project/client.d.ts +89 -0
- package/dist/src/project/client.d.ts.map +1 -0
- package/dist/src/project/external.d.ts.map +1 -0
- package/dist/src/project/index.d.ts +2 -0
- package/dist/src/project/index.d.ts.map +1 -0
- package/dist/src/project/types.gen.d.ts +27 -0
- package/dist/src/project/types.gen.d.ts.map +1 -0
- package/dist/src/query/cache.d.ts +132 -0
- package/dist/src/query/cache.d.ts.map +1 -0
- package/dist/src/query/deleted.d.ts +20 -0
- package/dist/src/query/deleted.d.ts.map +1 -0
- package/dist/src/query/derived.d.ts +33 -0
- package/dist/src/query/derived.d.ts.map +1 -0
- package/dist/src/query/external.d.ts +10 -0
- package/dist/src/query/external.d.ts.map +1 -0
- package/dist/src/query/index.d.ts +2 -0
- package/dist/src/query/index.d.ts.map +1 -0
- package/dist/src/query/query.d.ts +235 -0
- package/dist/src/query/query.d.ts.map +1 -0
- package/dist/src/query/retriever.d.ts +135 -0
- package/dist/src/query/retriever.d.ts.map +1 -0
- package/dist/src/query/streamer.d.ts +67 -0
- package/dist/src/query/streamer.d.ts.map +1 -0
- package/dist/src/query/table.d.ts +219 -0
- package/dist/src/query/table.d.ts.map +1 -0
- package/dist/src/query/types.d.ts +35 -0
- package/dist/src/query/types.d.ts.map +1 -0
- package/dist/src/query/write.d.ts +21 -0
- package/dist/src/query/write.d.ts.map +1 -0
- package/dist/src/rack/client.d.ts +58 -20
- package/dist/src/rack/client.d.ts.map +1 -1
- package/dist/src/rack/types.gen.d.ts +11 -12
- package/dist/src/rack/types.gen.d.ts.map +1 -1
- package/dist/src/range/alias/types.gen.d.ts +2 -3
- package/dist/src/range/alias/types.gen.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts +138 -27
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv/client.d.ts +7 -4
- package/dist/src/ranger/kv/client.d.ts.map +1 -1
- package/dist/src/ranger/payload.d.ts +3 -0
- package/dist/src/ranger/payload.d.ts.map +1 -1
- package/dist/src/ranger/types.gen.d.ts +45 -101
- package/dist/src/ranger/types.gen.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -74
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/schematic/actions.d.ts +90 -33
- package/dist/src/schematic/actions.d.ts.map +1 -1
- package/dist/src/schematic/actions.gen.d.ts +207 -114
- package/dist/src/schematic/actions.gen.d.ts.map +1 -1
- package/dist/src/schematic/client.d.ts +70 -68
- package/dist/src/schematic/client.d.ts.map +1 -1
- package/dist/src/schematic/symbol/client.d.ts +133 -27
- package/dist/src/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/schematic/symbol/types.gen.d.ts +258 -153
- package/dist/src/schematic/symbol/types.gen.d.ts.map +1 -1
- package/dist/src/schematic/types.gen.d.ts +17 -96
- package/dist/src/schematic/types.gen.d.ts.map +1 -1
- package/dist/src/status/client.d.ts +69 -14
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/external.d.ts +2 -0
- package/dist/src/status/external.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +2 -36
- package/dist/src/status/payload.d.ts.map +1 -1
- package/dist/src/status/status.d.ts +65 -0
- package/dist/src/status/status.d.ts.map +1 -0
- package/dist/src/status/types.gen.d.ts +58 -0
- package/dist/src/status/types.gen.d.ts.map +1 -0
- package/dist/src/table/actions.d.ts +72 -13
- package/dist/src/table/actions.d.ts.map +1 -1
- package/dist/src/table/actions.gen.d.ts +221 -137
- package/dist/src/table/actions.gen.d.ts.map +1 -1
- package/dist/src/table/client.d.ts +64 -40
- package/dist/src/table/client.d.ts.map +1 -1
- package/dist/src/table/types.gen.d.ts +20 -55
- package/dist/src/table/types.gen.d.ts.map +1 -1
- package/dist/src/task/client.d.ts +149 -28
- package/dist/src/task/client.d.ts.map +1 -1
- package/dist/src/task/types.gen.d.ts +71 -89
- package/dist/src/task/types.gen.d.ts.map +1 -1
- package/dist/src/testutil/access.d.ts +27 -1
- package/dist/src/testutil/access.d.ts.map +1 -1
- package/dist/src/testutil/channels.d.ts +2 -0
- package/dist/src/testutil/channels.d.ts.map +1 -1
- package/dist/src/testutil/client.d.ts +5 -0
- package/dist/src/testutil/client.d.ts.map +1 -1
- package/dist/src/testutil/connection.d.ts +10 -0
- package/dist/src/testutil/connection.d.ts.map +1 -0
- package/dist/src/testutil/index.d.ts +9 -0
- package/dist/src/testutil/index.d.ts.map +1 -0
- package/dist/src/testutil/panels.d.ts +8 -0
- package/dist/src/testutil/panels.d.ts.map +1 -0
- package/dist/src/testutil/proxy.d.ts +29 -0
- package/dist/src/testutil/proxy.d.ts.map +1 -0
- package/dist/src/testutil/query.d.ts +7 -0
- package/dist/src/testutil/query.d.ts.map +1 -0
- package/dist/src/testutil/telem.d.ts +4 -0
- package/dist/src/testutil/telem.d.ts.map +1 -1
- package/dist/src/transport.d.ts +10 -4
- package/dist/src/transport.d.ts.map +1 -1
- package/dist/src/user/client.d.ts +29 -28
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/external.d.ts +1 -1
- package/dist/src/user/external.d.ts.map +1 -1
- package/dist/src/user/types.gen.d.ts +4 -4
- package/dist/src/util/retrieve.d.ts +2 -2
- package/dist/src/util/retrieve.d.ts.map +1 -1
- package/dist/src/util/telem.d.ts.map +1 -1
- package/dist/src/view/client.d.ts +30 -14
- package/dist/src/view/client.d.ts.map +1 -1
- package/dist/src/view/types.gen.d.ts +7 -15
- package/dist/src/view/types.gen.d.ts.map +1 -1
- package/dist/testutil.js +189 -0
- package/dist/testutil.js.map +1 -0
- package/package.json +40 -17
- package/src/access/client.ts +14 -3
- package/src/access/enforce.ts +0 -3
- package/src/access/external.ts +1 -0
- package/src/access/granted.ts +114 -0
- package/src/access/policy/client.ts +135 -43
- package/src/access/policy/types.gen.ts +9 -11
- package/src/access/role/client.ts +160 -38
- package/src/access/role/types.gen.ts +8 -12
- package/src/actions/actions.ts +5 -6
- package/src/actions/controller.ts +626 -0
- package/src/actions/external.ts +11 -0
- package/src/arc/actions.gen.ts +313 -0
- package/src/arc/actions.ts +192 -0
- package/src/arc/client.ts +424 -41
- package/src/arc/compiler/types.gen.ts +5 -6
- package/src/arc/external.ts +2 -0
- package/src/arc/graph/types.gen.ts +24 -22
- package/src/arc/ir/index.ts +1 -1
- package/{eslint.config.ts → src/arc/ir/ir.ts} +1 -4
- package/src/arc/ir/types.gen.ts +42 -41
- package/src/arc/text/types.gen.ts +21 -2
- package/src/arc/types/types.gen.ts +40 -32
- package/src/arc/types.gen.ts +31 -29
- package/src/auth/auth.ts +40 -8
- package/src/channel/client.ts +529 -132
- package/src/channel/external.ts +0 -1
- package/src/channel/payload.ts +30 -3
- package/src/channel/types.gen.ts +37 -48
- package/src/channel/writer.ts +2 -11
- package/src/client.ts +215 -91
- package/src/connection/client.ts +495 -0
- package/src/connection/external.ts +34 -0
- package/src/connection/index.ts +1 -1
- package/src/connection/status.ts +442 -0
- package/src/control/client.ts +84 -12
- package/src/control/state.ts +17 -36
- package/src/device/client.ts +293 -41
- package/src/device/types.gen.ts +15 -26
- package/src/errors.ts +45 -22
- package/src/{workspace → ethercat}/external.ts +1 -2
- package/src/{workspace → ethercat}/index.ts +1 -1
- package/src/ethercat/types.gen.ts +151 -0
- package/src/framer/adapter.ts +60 -37
- package/src/framer/benchutil.ts +67 -0
- package/src/framer/cache/cache.ts +115 -0
- package/src/framer/cache/dynamic.ts +279 -0
- package/src/framer/cache/reader.ts +160 -0
- package/src/framer/cache/static.ts +215 -0
- package/src/framer/cache/streamer.ts +391 -0
- package/src/framer/cache/transform.ts +31 -0
- package/src/framer/cache/unary.ts +104 -0
- package/src/framer/client.ts +71 -43
- package/src/framer/codec.ts +55 -18
- package/src/framer/deleter.ts +4 -6
- package/src/framer/external.ts +10 -0
- package/src/framer/feed.ts +108 -0
- package/src/framer/frame.ts +13 -23
- package/src/framer/hardened.ts +283 -0
- package/src/framer/iterator.ts +31 -42
- package/src/framer/reader.ts +11 -11
- package/src/framer/streamer.ts +18 -178
- package/src/framer/writer.ts +39 -59
- package/src/group/client.ts +158 -23
- package/src/http/external.ts +10 -0
- package/src/{cluster → http}/index.ts +1 -1
- package/src/http/types.gen.ts +245 -0
- package/src/imex/client.ts +125 -0
- package/src/imex/index.ts +10 -0
- package/src/index.ts +18 -6
- package/src/label/client.ts +193 -54
- package/src/label/external.ts +2 -0
- package/src/label/payload.ts +4 -9
- package/src/label/store.ts +28 -0
- package/src/label/types.gen.ts +31 -0
- package/src/labjack/external.ts +10 -0
- package/src/labjack/index.ts +10 -0
- package/src/labjack/types.gen.ts +251 -0
- package/src/lineplot/actions.gen.ts +880 -0
- package/src/lineplot/actions.ts +535 -0
- package/src/lineplot/client.ts +224 -52
- package/src/lineplot/external.ts +3 -0
- package/src/lineplot/line.ts +80 -0
- package/src/lineplot/types.gen.ts +225 -12
- package/src/log/actions.gen.ts +474 -0
- package/src/log/actions.ts +242 -0
- package/src/log/client.ts +223 -52
- package/src/log/external.ts +2 -0
- package/src/log/types.gen.ts +45 -14
- package/src/modbus/external.ts +10 -0
- package/src/modbus/index.ts +10 -0
- package/src/modbus/types.gen.ts +185 -0
- package/src/ni/external.ts +10 -0
- package/src/ni/index.ts +10 -0
- package/src/ni/types.gen.ts +1632 -0
- package/src/node/index.ts +10 -0
- package/src/{cluster → node}/types.gen.ts +2 -2
- package/src/ontology/client.ts +408 -99
- package/src/ontology/external.ts +7 -0
- package/src/ontology/payload.ts +48 -7
- package/src/ontology/store.ts +83 -0
- package/src/ontology/types.gen.ts +2 -1
- package/src/ontology/writer.ts +1 -0
- package/src/opcua/external.ts +10 -0
- package/src/opcua/index.ts +10 -0
- package/src/opcua/types.gen.ts +65 -0
- package/src/pagerduty/external.ts +10 -0
- package/src/pagerduty/index.ts +10 -0
- package/src/pagerduty/types.gen.ts +41 -0
- package/src/panel/actions.gen.ts +267 -0
- package/src/panel/actions.ts +357 -0
- package/src/panel/client.ts +327 -0
- package/src/panel/external.ts +14 -0
- package/src/panel/index.ts +10 -0
- package/src/panel/tree.ts +163 -0
- package/src/panel/types.gen.ts +164 -0
- package/src/project/client.ts +273 -0
- package/src/project/external.ts +11 -0
- package/src/project/index.ts +10 -0
- package/src/project/types.gen.ts +40 -0
- package/src/query/cache.ts +326 -0
- package/src/query/deleted.ts +38 -0
- package/src/query/derived.ts +101 -0
- package/src/query/external.ts +51 -0
- package/src/query/index.ts +10 -0
- package/src/query/query.ts +865 -0
- package/src/query/retriever.ts +308 -0
- package/src/query/streamer.ts +207 -0
- package/src/query/table.ts +625 -0
- package/src/query/types.ts +54 -0
- package/src/query/write.ts +42 -0
- package/src/rack/client.ts +233 -45
- package/src/rack/types.gen.ts +15 -16
- package/src/range/alias/types.gen.ts +2 -3
- package/src/ranger/client.ts +581 -70
- package/src/ranger/kv/client.ts +52 -21
- package/src/ranger/payload.ts +3 -0
- package/src/ranger/types.gen.ts +21 -23
- package/src/ranger/writer.ts +4 -8
- package/src/schematic/actions.gen.ts +62 -53
- package/src/schematic/actions.ts +44 -42
- package/src/schematic/client.ts +226 -70
- package/src/schematic/symbol/client.ts +277 -48
- package/src/schematic/symbol/types.gen.ts +22 -34
- package/src/schematic/types.gen.ts +22 -29
- package/src/status/client.ts +321 -44
- package/src/status/external.ts +2 -0
- package/src/status/payload.ts +1 -23
- package/src/status/status.ts +241 -0
- package/src/status/types.gen.ts +108 -0
- package/src/table/actions.gen.ts +96 -63
- package/src/table/actions.ts +44 -19
- package/src/table/client.ts +220 -56
- package/src/table/types.gen.ts +24 -31
- package/src/task/client.ts +580 -101
- package/src/task/types.gen.ts +68 -75
- package/src/testutil/access.ts +102 -6
- package/src/testutil/channels.ts +29 -0
- package/src/testutil/client.ts +27 -2
- package/src/testutil/connection.ts +47 -0
- package/src/testutil/index.ts +17 -0
- package/src/testutil/panels.ts +26 -0
- package/src/testutil/proxy.ts +106 -0
- package/src/testutil/query.ts +28 -0
- package/src/testutil/telem.ts +17 -1
- package/src/transport.ts +18 -7
- package/src/user/client.ts +165 -64
- package/src/user/external.ts +1 -1
- package/src/user/types.gen.ts +5 -5
- package/src/util/retrieve.ts +4 -4
- package/src/util/telem.ts +0 -1
- package/src/view/client.ts +120 -37
- package/src/view/types.gen.ts +8 -11
- package/.turbo/turbo-build.log +0 -20
- package/.vscode/settings.json +0 -3
- package/CONTRIBUTING.md +0 -47
- package/dist/client.cjs +0 -118
- package/dist/eslint.config.d.ts +0 -4
- package/dist/eslint.config.d.ts.map +0 -1
- package/dist/src/access/enforce.spec.d.ts +0 -2
- package/dist/src/access/enforce.spec.d.ts.map +0 -1
- package/dist/src/access/policy/access.spec.d.ts +0 -2
- package/dist/src/access/policy/access.spec.d.ts.map +0 -1
- package/dist/src/access/role/role.spec.d.ts +0 -2
- package/dist/src/access/role/role.spec.d.ts.map +0 -1
- package/dist/src/actions/actions.spec.d.ts +0 -2
- package/dist/src/actions/actions.spec.d.ts.map +0 -1
- package/dist/src/arc/access.spec.d.ts +0 -2
- package/dist/src/arc/access.spec.d.ts.map +0 -1
- package/dist/src/arc/arc.spec.d.ts +0 -2
- package/dist/src/arc/arc.spec.d.ts.map +0 -1
- package/dist/src/arc/lsp.spec.d.ts +0 -2
- package/dist/src/arc/lsp.spec.d.ts.map +0 -1
- package/dist/src/auth/auth.spec.d.ts +0 -2
- package/dist/src/auth/auth.spec.d.ts.map +0 -1
- package/dist/src/channel/access.spec.d.ts +0 -2
- package/dist/src/channel/access.spec.d.ts.map +0 -1
- package/dist/src/channel/batchRetriever.spec.d.ts +0 -2
- package/dist/src/channel/batchRetriever.spec.d.ts.map +0 -1
- package/dist/src/channel/channel.spec.d.ts +0 -2
- package/dist/src/channel/channel.spec.d.ts.map +0 -1
- package/dist/src/channel/payload.spec.d.ts +0 -2
- package/dist/src/channel/payload.spec.d.ts.map +0 -1
- package/dist/src/channel/retriever.d.ts +0 -64
- package/dist/src/channel/retriever.d.ts.map +0 -1
- package/dist/src/cluster/index.d.ts +0 -2
- package/dist/src/cluster/index.d.ts.map +0 -1
- package/dist/src/cluster/types.gen.d.ts +0 -4
- package/dist/src/cluster/types.gen.d.ts.map +0 -1
- package/dist/src/connection/checker.d.ts +0 -86
- package/dist/src/connection/checker.d.ts.map +0 -1
- package/dist/src/connection/connection.spec.d.ts +0 -2
- package/dist/src/connection/connection.spec.d.ts.map +0 -1
- package/dist/src/connection.spec.d.ts +0 -2
- package/dist/src/connection.spec.d.ts.map +0 -1
- package/dist/src/control/state.spec.d.ts +0 -2
- package/dist/src/control/state.spec.d.ts.map +0 -1
- package/dist/src/device/access.spec.d.ts +0 -2
- package/dist/src/device/access.spec.d.ts.map +0 -1
- package/dist/src/device/device.spec.d.ts +0 -2
- package/dist/src/device/device.spec.d.ts.map +0 -1
- package/dist/src/device/payload.spec.d.ts +0 -2
- package/dist/src/device/payload.spec.d.ts.map +0 -1
- package/dist/src/errors.spec.d.ts +0 -2
- package/dist/src/errors.spec.d.ts.map +0 -1
- package/dist/src/framer/adapter.spec.d.ts +0 -2
- package/dist/src/framer/adapter.spec.d.ts.map +0 -1
- package/dist/src/framer/client.spec.d.ts +0 -2
- package/dist/src/framer/client.spec.d.ts.map +0 -1
- package/dist/src/framer/codec.spec.d.ts +0 -2
- package/dist/src/framer/codec.spec.d.ts.map +0 -1
- package/dist/src/framer/deleter.spec.d.ts +0 -2
- package/dist/src/framer/deleter.spec.d.ts.map +0 -1
- package/dist/src/framer/frame.spec.d.ts +0 -2
- package/dist/src/framer/frame.spec.d.ts.map +0 -1
- package/dist/src/framer/iterator.spec.d.ts +0 -2
- package/dist/src/framer/iterator.spec.d.ts.map +0 -1
- package/dist/src/framer/reader.spec.d.ts +0 -2
- package/dist/src/framer/reader.spec.d.ts.map +0 -1
- package/dist/src/framer/streamer.spec.d.ts +0 -2
- package/dist/src/framer/streamer.spec.d.ts.map +0 -1
- package/dist/src/framer/writer.spec.d.ts +0 -2
- package/dist/src/framer/writer.spec.d.ts.map +0 -1
- package/dist/src/group/access.spec.d.ts +0 -2
- package/dist/src/group/access.spec.d.ts.map +0 -1
- package/dist/src/group/group.spec.d.ts +0 -2
- package/dist/src/group/group.spec.d.ts.map +0 -1
- package/dist/src/label/access.spec.d.ts +0 -2
- package/dist/src/label/access.spec.d.ts.map +0 -1
- package/dist/src/label/label.spec.d.ts +0 -2
- package/dist/src/label/label.spec.d.ts.map +0 -1
- package/dist/src/lineplot/access.spec.d.ts +0 -2
- package/dist/src/lineplot/access.spec.d.ts.map +0 -1
- package/dist/src/lineplot/lineplot.spec.d.ts +0 -2
- package/dist/src/lineplot/lineplot.spec.d.ts.map +0 -1
- package/dist/src/log/access.spec.d.ts +0 -2
- package/dist/src/log/access.spec.d.ts.map +0 -1
- package/dist/src/log/log.spec.d.ts +0 -2
- package/dist/src/log/log.spec.d.ts.map +0 -1
- package/dist/src/ontology/ontology.spec.d.ts +0 -2
- package/dist/src/ontology/ontology.spec.d.ts.map +0 -1
- package/dist/src/rack/access.spec.d.ts +0 -2
- package/dist/src/rack/access.spec.d.ts.map +0 -1
- package/dist/src/rack/rack.spec.d.ts +0 -2
- package/dist/src/rack/rack.spec.d.ts.map +0 -1
- package/dist/src/ranger/access.spec.d.ts +0 -2
- package/dist/src/ranger/access.spec.d.ts.map +0 -1
- package/dist/src/ranger/alias/payload.spec.d.ts +0 -2
- package/dist/src/ranger/alias/payload.spec.d.ts.map +0 -1
- package/dist/src/ranger/ranger.spec.d.ts +0 -2
- package/dist/src/ranger/ranger.spec.d.ts.map +0 -1
- package/dist/src/schematic/access.spec.d.ts +0 -2
- package/dist/src/schematic/access.spec.d.ts.map +0 -1
- package/dist/src/schematic/actions.spec.d.ts +0 -2
- package/dist/src/schematic/actions.spec.d.ts.map +0 -1
- package/dist/src/schematic/schematic.spec.d.ts +0 -2
- package/dist/src/schematic/schematic.spec.d.ts.map +0 -1
- package/dist/src/schematic/symbol/access.spec.d.ts +0 -2
- package/dist/src/schematic/symbol/access.spec.d.ts.map +0 -1
- package/dist/src/schematic/symbol/client.spec.d.ts +0 -2
- package/dist/src/schematic/symbol/client.spec.d.ts.map +0 -1
- package/dist/src/status/access.spec.d.ts +0 -2
- package/dist/src/status/access.spec.d.ts.map +0 -1
- package/dist/src/status/status.spec.d.ts +0 -2
- package/dist/src/status/status.spec.d.ts.map +0 -1
- package/dist/src/table/access.spec.d.ts +0 -2
- package/dist/src/table/access.spec.d.ts.map +0 -1
- package/dist/src/table/table.spec.d.ts +0 -2
- package/dist/src/table/table.spec.d.ts.map +0 -1
- package/dist/src/task/access.spec.d.ts +0 -2
- package/dist/src/task/access.spec.d.ts.map +0 -1
- package/dist/src/task/payload.spec.d.ts +0 -2
- package/dist/src/task/payload.spec.d.ts.map +0 -1
- package/dist/src/task/task.spec.d.ts +0 -2
- package/dist/src/task/task.spec.d.ts.map +0 -1
- package/dist/src/user/access.spec.d.ts +0 -2
- package/dist/src/user/access.spec.d.ts.map +0 -1
- package/dist/src/user/user.spec.d.ts +0 -2
- package/dist/src/user/user.spec.d.ts.map +0 -1
- package/dist/src/util/retrieve.spec.d.ts +0 -2
- package/dist/src/util/retrieve.spec.d.ts.map +0 -1
- package/dist/src/view/view.spec.d.ts +0 -2
- package/dist/src/view/view.spec.d.ts.map +0 -1
- package/dist/src/workspace/access.spec.d.ts +0 -2
- package/dist/src/workspace/access.spec.d.ts.map +0 -1
- package/dist/src/workspace/client.d.ts +0 -36
- package/dist/src/workspace/client.d.ts.map +0 -1
- package/dist/src/workspace/external.d.ts.map +0 -1
- package/dist/src/workspace/index.d.ts +0 -2
- package/dist/src/workspace/index.d.ts.map +0 -1
- package/dist/src/workspace/types.gen.d.ts +0 -34
- package/dist/src/workspace/types.gen.d.ts.map +0 -1
- package/dist/src/workspace/workspace.spec.d.ts +0 -2
- package/dist/src/workspace/workspace.spec.d.ts.map +0 -1
- package/examples/node/basicReadWrite.js +0 -86
- package/examples/node/createChannels.js +0 -50
- package/examples/node/createRange.js +0 -67
- package/examples/node/package-lock.json +0 -133
- package/examples/node/package.json +0 -17
- package/examples/node/readLatest.js +0 -76
- package/examples/node/seriesAndFrames.js +0 -173
- package/examples/node/streamRead.js +0 -50
- package/examples/node/streamWrite.js +0 -87
- package/src/access/enforce.spec.ts +0 -188
- package/src/access/policy/access.spec.ts +0 -147
- package/src/access/role/role.spec.ts +0 -95
- package/src/actions/actions.spec.ts +0 -229
- package/src/arc/access.spec.ts +0 -149
- package/src/arc/arc.spec.ts +0 -44
- package/src/arc/lsp.spec.ts +0 -717
- package/src/auth/auth.spec.ts +0 -101
- package/src/channel/access.spec.ts +0 -116
- package/src/channel/batchRetriever.spec.ts +0 -115
- package/src/channel/channel.spec.ts +0 -352
- package/src/channel/payload.spec.ts +0 -117
- package/src/channel/retriever.ts +0 -252
- package/src/connection/checker.ts +0 -203
- package/src/connection/connection.spec.ts +0 -152
- package/src/connection.spec.ts +0 -145
- package/src/control/state.spec.ts +0 -22
- package/src/device/access.spec.ts +0 -159
- package/src/device/device.spec.ts +0 -461
- package/src/device/payload.spec.ts +0 -142
- package/src/errors.spec.ts +0 -71
- package/src/framer/adapter.spec.ts +0 -620
- package/src/framer/client.spec.ts +0 -180
- package/src/framer/codec.spec.ts +0 -383
- package/src/framer/deleter.spec.ts +0 -103
- package/src/framer/frame.spec.ts +0 -973
- package/src/framer/iterator.spec.ts +0 -169
- package/src/framer/reader.spec.ts +0 -865
- package/src/framer/streamer.spec.ts +0 -871
- package/src/framer/writer.spec.ts +0 -486
- package/src/group/access.spec.ts +0 -77
- package/src/group/group.spec.ts +0 -65
- package/src/label/access.spec.ts +0 -109
- package/src/label/label.spec.ts +0 -83
- package/src/lineplot/access.spec.ts +0 -134
- package/src/lineplot/lineplot.spec.ts +0 -120
- package/src/log/access.spec.ts +0 -132
- package/src/log/log.spec.ts +0 -106
- package/src/ontology/ontology.spec.ts +0 -521
- package/src/rack/access.spec.ts +0 -102
- package/src/rack/rack.spec.ts +0 -171
- package/src/ranger/access.spec.ts +0 -115
- package/src/ranger/alias/payload.spec.ts +0 -52
- package/src/ranger/ranger.spec.ts +0 -343
- package/src/schematic/access.spec.ts +0 -134
- package/src/schematic/actions.spec.ts +0 -699
- package/src/schematic/schematic.spec.ts +0 -340
- package/src/schematic/symbol/access.spec.ts +0 -172
- package/src/schematic/symbol/client.spec.ts +0 -160
- package/src/status/access.spec.ts +0 -129
- package/src/status/status.spec.ts +0 -448
- package/src/table/access.spec.ts +0 -128
- package/src/table/table.spec.ts +0 -651
- package/src/task/access.spec.ts +0 -131
- package/src/task/payload.spec.ts +0 -113
- package/src/task/task.spec.ts +0 -657
- package/src/user/access.spec.ts +0 -107
- package/src/user/user.spec.ts +0 -290
- package/src/util/retrieve.spec.ts +0 -49
- package/src/view/view.spec.ts +0 -165
- package/src/workspace/access.spec.ts +0 -108
- package/src/workspace/client.ts +0 -112
- package/src/workspace/types.gen.ts +0 -46
- package/src/workspace/workspace.spec.ts +0 -111
- package/tsconfig.json +0 -5
- package/tsconfig.vite.json +0 -4
- package/vite.config.ts +0 -29
- /package/dist/src/{workspace → project}/external.d.ts +0 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { alamos } from "@synnaxlabs/alamos";
|
|
11
|
+
import {
|
|
12
|
+
DataType,
|
|
13
|
+
math,
|
|
14
|
+
MultiSeries,
|
|
15
|
+
Series,
|
|
16
|
+
type TimeSpan,
|
|
17
|
+
TimeStamp,
|
|
18
|
+
} from "@synnaxlabs/x";
|
|
19
|
+
|
|
20
|
+
import { IDENTITY_TRANSFORM, type Transform } from "@/framer/cache/transform";
|
|
21
|
+
|
|
22
|
+
/** Response from a write to the {@link Dynamic} cache. */
|
|
23
|
+
export interface WriteResponse {
|
|
24
|
+
/** Series flushed because the write did not fit in the current buffer. */
|
|
25
|
+
flushed: MultiSeries;
|
|
26
|
+
/** A list of series that were allocated during the write. */
|
|
27
|
+
allocated: MultiSeries;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Props for the {@link Dynamic} cache. */
|
|
31
|
+
export interface DynamicProps {
|
|
32
|
+
/**
|
|
33
|
+
* Sets the maximum size of the buffer that the cache will maintain before flushing
|
|
34
|
+
* data out to the caller.
|
|
35
|
+
*/
|
|
36
|
+
dynamicBufferSize: number | TimeSpan;
|
|
37
|
+
/** Applied to every series before it enters a buffer. Defaults to identity. */
|
|
38
|
+
transform?: Transform;
|
|
39
|
+
/** Used for logging. */
|
|
40
|
+
instrumentation?: alamos.Instrumentation;
|
|
41
|
+
/** Pulls the current time. */
|
|
42
|
+
now?: () => TimeStamp;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Bounds for dynamically calculated buffer sizes.
|
|
46
|
+
const MIN_SIZE = 100;
|
|
47
|
+
const MAX_SIZE = 1e6;
|
|
48
|
+
// Size used until enough writes have arrived to estimate a rate.
|
|
49
|
+
const DEF_SIZE = 1e4;
|
|
50
|
+
const MAX_DEF_WRITES = 100;
|
|
51
|
+
|
|
52
|
+
// Variable-rate types allocate bytes, not samples. Rough bytes-per-sample estimate.
|
|
53
|
+
const VARIABLE_DT_MULTIPLIER = 40;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A cache for channel data that maintains a single, rolling Series as a buffer
|
|
57
|
+
* for channel data. The buffer's data type is derived from the first written series,
|
|
58
|
+
* so the cache needs no channel metadata.
|
|
59
|
+
*/
|
|
60
|
+
export class Dynamic {
|
|
61
|
+
private readonly props: Required<Omit<DynamicProps, "now">>;
|
|
62
|
+
|
|
63
|
+
private counter = 0;
|
|
64
|
+
private curr: Series | null = null;
|
|
65
|
+
/** End timestamp of the last fully written stamped series in the current buffer.
|
|
66
|
+
* Null when the buffer holds unstamped or partially written data, in which case
|
|
67
|
+
* the flush falls back to the wall clock. */
|
|
68
|
+
private currDataEnd: TimeStamp | null = null;
|
|
69
|
+
private avgRate: number = 0;
|
|
70
|
+
private timeOfLastWrite: TimeStamp;
|
|
71
|
+
private totalWrites: number = 0;
|
|
72
|
+
private readonly now: () => TimeStamp;
|
|
73
|
+
|
|
74
|
+
constructor(props: DynamicProps) {
|
|
75
|
+
const {
|
|
76
|
+
dynamicBufferSize,
|
|
77
|
+
transform = IDENTITY_TRANSFORM,
|
|
78
|
+
instrumentation = alamos.NOOP,
|
|
79
|
+
now = () => TimeStamp.now(),
|
|
80
|
+
} = props;
|
|
81
|
+
this.props = { dynamicBufferSize, transform, instrumentation };
|
|
82
|
+
this.now = now;
|
|
83
|
+
this.timeOfLastWrite = this.now();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** @returns the number of samples currently held in the cache. */
|
|
87
|
+
get length(): number {
|
|
88
|
+
return this.curr?.length ?? 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @returns the current buffer being written to by the cache. Under no circumstances
|
|
93
|
+
* should this be modified by the caller.
|
|
94
|
+
*/
|
|
95
|
+
get leadingBuffer(): Series | null {
|
|
96
|
+
return this.curr;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @returns a list of buffers that were filled by the cache during the write. If the
|
|
101
|
+
* current buffer is able to fit all writes, no buffers will be returned.
|
|
102
|
+
*/
|
|
103
|
+
write(series: MultiSeries): WriteResponse {
|
|
104
|
+
const res: WriteResponse = {
|
|
105
|
+
flushed: new MultiSeries([]),
|
|
106
|
+
allocated: new MultiSeries([]),
|
|
107
|
+
};
|
|
108
|
+
const list = series.series;
|
|
109
|
+
for (let i = 0; i < list.length; i++) this._write(list[i], res);
|
|
110
|
+
return res;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private allocate(
|
|
114
|
+
capacity: number,
|
|
115
|
+
alignment: bigint,
|
|
116
|
+
start: TimeStamp,
|
|
117
|
+
source: Series,
|
|
118
|
+
sampleIndex: number,
|
|
119
|
+
): Series {
|
|
120
|
+
this.counter++;
|
|
121
|
+
const dt = this.props.transform.resolveDataType(source.dataType);
|
|
122
|
+
// Bigint series narrowed to a non-bigint buffer store each value as a small delta
|
|
123
|
+
// off a per-buffer anchor to avoid losing precision. For timestamps, now() is
|
|
124
|
+
// close enough to the values being written. For int64 and uint64 the values can
|
|
125
|
+
// be anything, so the first sample we see is used as the anchor.
|
|
126
|
+
const narrowing = source.dataType.usesBigInt && !dt.usesBigInt;
|
|
127
|
+
let sampleOffset: math.Numeric = 0;
|
|
128
|
+
if (narrowing)
|
|
129
|
+
if (source.dataType.equals(DataType.TIMESTAMP)) sampleOffset = start.valueOf();
|
|
130
|
+
else if (sampleIndex < source.length)
|
|
131
|
+
sampleOffset = BigInt(source.data[sampleIndex].valueOf());
|
|
132
|
+
return Series.alloc({
|
|
133
|
+
capacity: dt.isVariable ? capacity * VARIABLE_DT_MULTIPLIER : capacity,
|
|
134
|
+
dataType: dt,
|
|
135
|
+
timeRange: start.range(TimeStamp.MAX),
|
|
136
|
+
sampleOffset,
|
|
137
|
+
glBufferUsage: "dynamic",
|
|
138
|
+
alignment,
|
|
139
|
+
key: `dynamic-${this.counter}`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Unstamped series (virtual channels, writes without an in-frame index) fall back
|
|
144
|
+
// to the wall clock.
|
|
145
|
+
private allocStart(series: Series): TimeStamp {
|
|
146
|
+
return series.timeRange.isZero ? this.now() : series.timeRange.start;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private allocCurr(
|
|
150
|
+
res: WriteResponse,
|
|
151
|
+
alignment: bigint,
|
|
152
|
+
start: TimeStamp,
|
|
153
|
+
source: Series,
|
|
154
|
+
sampleIndex: number,
|
|
155
|
+
): Series {
|
|
156
|
+
this.curr = this.allocate(
|
|
157
|
+
this.nextBufferSize(),
|
|
158
|
+
alignment,
|
|
159
|
+
start,
|
|
160
|
+
source,
|
|
161
|
+
sampleIndex,
|
|
162
|
+
);
|
|
163
|
+
res.allocated.push(this.curr);
|
|
164
|
+
return this.curr;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private flushCurr(res: WriteResponse): void {
|
|
168
|
+
if (this.curr == null) return;
|
|
169
|
+
this.curr.timeRange.end = this.currDataEnd ?? this.now();
|
|
170
|
+
this.currDataEnd = null;
|
|
171
|
+
res.flushed.push(this.curr);
|
|
172
|
+
this.curr = null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private _write(series: Series, res: WriteResponse): void {
|
|
176
|
+
const { transform, instrumentation: ins } = this.props;
|
|
177
|
+
if (this.curr != null) {
|
|
178
|
+
const resolved = transform.resolveDataType(series.dataType);
|
|
179
|
+
if (!this.curr.dataType.equals(resolved)) {
|
|
180
|
+
// The channel's data type changed (e.g. a calculated channel was reconfigured).
|
|
181
|
+
ins.L.warn("buffer data type changed, resetting", {
|
|
182
|
+
prev: this.curr.dataType.toString(),
|
|
183
|
+
next: resolved.toString(),
|
|
184
|
+
});
|
|
185
|
+
this.flushCurr(res);
|
|
186
|
+
} else if (series.alignment < this.curr.alignment) {
|
|
187
|
+
// The alignment counter rewound (e.g. the Core restarted and reset its
|
|
188
|
+
// in-memory counter).
|
|
189
|
+
ins.L.warn("alignment regressed, resetting buffer", {
|
|
190
|
+
buffer: this.curr.alignment.toString(),
|
|
191
|
+
incoming: series.alignment.toString(),
|
|
192
|
+
});
|
|
193
|
+
this.flushCurr(res);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
let curr = this.curr;
|
|
197
|
+
if (curr == null)
|
|
198
|
+
curr = this.allocCurr(res, series.alignment, this.allocStart(series), series, 0);
|
|
199
|
+
else {
|
|
200
|
+
// overlap > 0: the incoming series steps back into samples the current buffer
|
|
201
|
+
// already holds. overlap < 0: there is a gap between the buffer and the series.
|
|
202
|
+
const overlap = Number(curr.alignment + BigInt(curr.length) - series.alignment);
|
|
203
|
+
if (overlap > 0) {
|
|
204
|
+
// Drop the re-sent leading samples; a fresh allocation here would fragment
|
|
205
|
+
// the cache with overlapping series. sub() is zero-copy.
|
|
206
|
+
if (overlap >= series.length) return;
|
|
207
|
+
series = series.sub(overlap);
|
|
208
|
+
} else if (overlap < 0) {
|
|
209
|
+
this.flushCurr(res);
|
|
210
|
+
curr = this.allocCurr(
|
|
211
|
+
res,
|
|
212
|
+
series.alignment,
|
|
213
|
+
this.allocStart(series),
|
|
214
|
+
series,
|
|
215
|
+
0,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
while (true) {
|
|
220
|
+
const converted = transform.convert(series, curr.sampleOffset);
|
|
221
|
+
const amountWritten = curr.write(converted);
|
|
222
|
+
if (amountWritten === series.length) {
|
|
223
|
+
this.currDataEnd = series.timeRange.isZero ? null : series.timeRange.end;
|
|
224
|
+
this.updateAvgRate(series);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// The timestamp at the split point is unknowable from the data series, so
|
|
228
|
+
// both sides fall back to the wall clock.
|
|
229
|
+
this.currDataEnd = null;
|
|
230
|
+
this.flushCurr(res);
|
|
231
|
+
curr = this.allocCurr(
|
|
232
|
+
res,
|
|
233
|
+
series.alignment + BigInt(amountWritten),
|
|
234
|
+
this.now(),
|
|
235
|
+
series,
|
|
236
|
+
amountWritten,
|
|
237
|
+
);
|
|
238
|
+
series = series.slice(amountWritten);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private updateAvgRate(series: Series): void {
|
|
243
|
+
if (typeof this.props.dynamicBufferSize === "number") return;
|
|
244
|
+
const now = this.now();
|
|
245
|
+
const newRate = series.length / now.span(this.timeOfLastWrite).seconds;
|
|
246
|
+
if (this.totalWrites > 0 && isFinite(newRate) && newRate > 0)
|
|
247
|
+
this.avgRate =
|
|
248
|
+
(this.avgRate * (this.totalWrites - 1) + newRate) / this.totalWrites;
|
|
249
|
+
this.totalWrites++;
|
|
250
|
+
this.timeOfLastWrite = now;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private nextBufferSize(): number {
|
|
254
|
+
const { dynamicBufferSize } = this.props;
|
|
255
|
+
if (typeof dynamicBufferSize === "number") return dynamicBufferSize;
|
|
256
|
+
if (this.totalWrites < MAX_DEF_WRITES) return DEF_SIZE;
|
|
257
|
+
const size = math.roundToNearestMagnitude(this.avgRate * dynamicBufferSize.seconds);
|
|
258
|
+
return Math.round(Math.max(Math.min(size, MAX_SIZE), MIN_SIZE));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Flushes the leading buffer, stamping its end with the last stamped write or
|
|
263
|
+
* the wall clock.
|
|
264
|
+
* @returns the flushed buffer, or null when there is none.
|
|
265
|
+
*/
|
|
266
|
+
flush(): Series | null {
|
|
267
|
+
const res: WriteResponse = {
|
|
268
|
+
flushed: new MultiSeries([]),
|
|
269
|
+
allocated: new MultiSeries([]),
|
|
270
|
+
};
|
|
271
|
+
this.flushCurr(res);
|
|
272
|
+
return res.flushed.series[0] ?? null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** Closes the cache. It must not be used afterwards. */
|
|
276
|
+
close(): void {
|
|
277
|
+
this.curr = null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
debounce,
|
|
12
|
+
MultiSeries,
|
|
13
|
+
type Series,
|
|
14
|
+
sync,
|
|
15
|
+
TimeRange,
|
|
16
|
+
TimeSpan,
|
|
17
|
+
} from "@synnaxlabs/x";
|
|
18
|
+
|
|
19
|
+
import { type channel } from "@/channel";
|
|
20
|
+
import { UnexpectedError } from "@/errors";
|
|
21
|
+
import { type Cache } from "@/framer/cache/cache";
|
|
22
|
+
import { type Frame } from "@/framer/frame";
|
|
23
|
+
|
|
24
|
+
/** A function that reads a telemetry frame from the Synnax cluster. */
|
|
25
|
+
export interface RemoteReader {
|
|
26
|
+
(tr: TimeRange, keys: channel.Key[]): Promise<Frame>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface ReadRequest {
|
|
30
|
+
channel: channel.Key;
|
|
31
|
+
gaps: TimeRange[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface BatchFetch {
|
|
35
|
+
gap: TimeRange;
|
|
36
|
+
channels: Set<channel.Key>;
|
|
37
|
+
entries: Set<debounce.Entry<ReadRequest>>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ReaderProps {
|
|
41
|
+
/** Function used to read remote data from the server. */
|
|
42
|
+
readRemote: RemoteReader;
|
|
43
|
+
/** Will read from and populate the given cache with fetched data. */
|
|
44
|
+
cache: Cache;
|
|
45
|
+
/**
|
|
46
|
+
* Used to batch read requests to the server to minimize traffic. The window is not
|
|
47
|
+
* extended by later reads, so it is also the maximum wait before a batch fires.
|
|
48
|
+
* @default TimeSpan.milliseconds(50)
|
|
49
|
+
*/
|
|
50
|
+
batchDebounce?: TimeSpan;
|
|
51
|
+
/**
|
|
52
|
+
* Reads whose gap time ranges are within this threshold merge into one request.
|
|
53
|
+
* @default TimeSpan.milliseconds(5)
|
|
54
|
+
*/
|
|
55
|
+
overlapThreshold?: TimeSpan;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Reads historical telemetry, serving from the cache and batch-filling gaps from the
|
|
60
|
+
* server. A batch failure rejects only the reads whose gaps were in the failed fetch.
|
|
61
|
+
*/
|
|
62
|
+
export class Reader {
|
|
63
|
+
private readonly props: Required<Omit<ReaderProps, "batchDebounce">>;
|
|
64
|
+
private readonly batcher: debounce.Batcher<ReadRequest>;
|
|
65
|
+
// Serializes batch execution against close, so close waits for the batch in flight.
|
|
66
|
+
private readonly mu = sync.newMutex({ closed: false });
|
|
67
|
+
|
|
68
|
+
constructor(props: ReaderProps) {
|
|
69
|
+
const {
|
|
70
|
+
readRemote,
|
|
71
|
+
cache,
|
|
72
|
+
batchDebounce = TimeSpan.milliseconds(50),
|
|
73
|
+
overlapThreshold = TimeSpan.milliseconds(5),
|
|
74
|
+
} = props;
|
|
75
|
+
this.props = { readRemote, cache, overlapThreshold };
|
|
76
|
+
this.batcher = new debounce.Batcher({
|
|
77
|
+
interval: batchDebounce,
|
|
78
|
+
exec: async (entries) =>
|
|
79
|
+
await this.mu.runExclusive(async () => {
|
|
80
|
+
if (this.mu.closed) throw new UnexpectedError("telemetry reader is closed");
|
|
81
|
+
await this.batchRead(entries);
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Reads the given time range for the given channel.
|
|
88
|
+
* @throws {UnexpectedError} if the reader is closed while the read is pending.
|
|
89
|
+
*/
|
|
90
|
+
async read(tr: TimeRange, channel: channel.Key): Promise<MultiSeries> {
|
|
91
|
+
const { cache } = this.props;
|
|
92
|
+
const unary = cache.get(channel);
|
|
93
|
+
const { series, gaps } = unary.read(tr);
|
|
94
|
+
if (gaps.length === 0) return series;
|
|
95
|
+
if (this.mu.closed) throw new UnexpectedError("telemetry reader is closed");
|
|
96
|
+
await this.batcher.enqueue({ channel, gaps });
|
|
97
|
+
return unary.read(tr).series;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private async batchRead(entries: Array<debounce.Entry<ReadRequest>>): Promise<void> {
|
|
101
|
+
const { readRemote, cache, overlapThreshold } = this.props;
|
|
102
|
+
const batched: BatchFetch[] = [];
|
|
103
|
+
entries.forEach((entry) => {
|
|
104
|
+
const unary = cache.get(entry.req.channel);
|
|
105
|
+
entry.req.gaps.forEach((rawGap) => {
|
|
106
|
+
// A concurrent batch or a streaming write may have filled part of the gap
|
|
107
|
+
// while this entry sat in the debounce window.
|
|
108
|
+
unary.read(rawGap).gaps.forEach((gap) => {
|
|
109
|
+
const g = batched.find((r) => r.gap.equals(gap, overlapThreshold));
|
|
110
|
+
if (g == null)
|
|
111
|
+
batched.push({
|
|
112
|
+
gap,
|
|
113
|
+
channels: new Set([entry.req.channel]),
|
|
114
|
+
entries: new Set([entry]),
|
|
115
|
+
});
|
|
116
|
+
else {
|
|
117
|
+
g.channels.add(entry.req.channel);
|
|
118
|
+
g.gap = TimeRange.max(g.gap, gap);
|
|
119
|
+
g.entries.add(entry);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
const failures = new Map<debounce.Entry<ReadRequest>, unknown>();
|
|
125
|
+
await Promise.all(
|
|
126
|
+
batched.map(async ({ gap, channels, entries: served }) => {
|
|
127
|
+
try {
|
|
128
|
+
const frame = await readRemote(gap, Array.from(channels));
|
|
129
|
+
// Group series by key in one pass; per-key get() scans the whole frame.
|
|
130
|
+
const grouped = new Map<channel.Key, Series[]>();
|
|
131
|
+
frame.forEach((k, s) => {
|
|
132
|
+
const key = k as channel.Key;
|
|
133
|
+
const existing = grouped.get(key);
|
|
134
|
+
if (existing == null) grouped.set(key, [s]);
|
|
135
|
+
else existing.push(s);
|
|
136
|
+
});
|
|
137
|
+
channels.forEach((key) =>
|
|
138
|
+
cache.get(key).writeStatic(new MultiSeries(grouped.get(key) ?? [])),
|
|
139
|
+
);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
served.forEach((entry) => {
|
|
142
|
+
if (!failures.has(entry)) failures.set(entry, err);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
entries.forEach((entry) => {
|
|
148
|
+
const err = failures.get(entry);
|
|
149
|
+
if (err == null) entry.resolve();
|
|
150
|
+
else entry.reject(err);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async close(): Promise<void> {
|
|
155
|
+
this.batcher.close(new UnexpectedError("telemetry reader is closed"));
|
|
156
|
+
await this.mu.runExclusive(async () => {
|
|
157
|
+
this.mu.closed = true;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { alamos } from "@synnaxlabs/alamos";
|
|
11
|
+
import {
|
|
12
|
+
bounds,
|
|
13
|
+
MultiSeries,
|
|
14
|
+
type Series,
|
|
15
|
+
Size,
|
|
16
|
+
TimeRange,
|
|
17
|
+
TimeSpan,
|
|
18
|
+
TimeStamp,
|
|
19
|
+
} from "@synnaxlabs/x";
|
|
20
|
+
|
|
21
|
+
import { IDENTITY_TRANSFORM, type Transform } from "@/framer/cache/transform";
|
|
22
|
+
|
|
23
|
+
export interface DirtyReadResult {
|
|
24
|
+
series: MultiSeries;
|
|
25
|
+
gaps: TimeRange[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface GCMetrics {
|
|
29
|
+
purgedSeries: number;
|
|
30
|
+
purgedBytes: Size;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const zeroGCMetrics = (): GCMetrics => ({
|
|
34
|
+
purgedSeries: 0,
|
|
35
|
+
purgedBytes: Size.bytes(0),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
/** Props for the {@link Static} cache. */
|
|
39
|
+
export interface StaticProps {
|
|
40
|
+
/** Used for logging */
|
|
41
|
+
instrumentation?: alamos.Instrumentation;
|
|
42
|
+
/** Applied to every series before it enters the cache. Defaults to identity. */
|
|
43
|
+
transform?: Transform;
|
|
44
|
+
/**
|
|
45
|
+
* Sets the amount of time that a cache entry must be in the cache before it can
|
|
46
|
+
* be marked as stale and subject to garbage collection.
|
|
47
|
+
* @default TimeSpan.seconds(20) */
|
|
48
|
+
staleEntryThreshold?: TimeSpan;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const DEFAULT_STATIC_PROPS: Required<StaticProps> = {
|
|
52
|
+
instrumentation: alamos.NOOP,
|
|
53
|
+
transform: IDENTITY_TRANSFORM,
|
|
54
|
+
staleEntryThreshold: TimeSpan.seconds(20),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
interface CacheEntry {
|
|
58
|
+
/** The cached samples, after the transform and any insertion trimming. */
|
|
59
|
+
data: Series;
|
|
60
|
+
/** When the entry entered the cache, for garbage collection staleness. */
|
|
61
|
+
addedAt: TimeStamp;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A cache for historical channel data that will not be modified after it is written.
|
|
66
|
+
* Fetched and streamed entries are held apart because they measure position in
|
|
67
|
+
* different spaces: a fetched sample carries its committed alignment, the same sample
|
|
68
|
+
* streamed carries a provisional leading one. Insertion and gap computation both assume
|
|
69
|
+
* a single space, so each kind gets its own list.
|
|
70
|
+
*/
|
|
71
|
+
export class Static {
|
|
72
|
+
private fetched: CacheEntry[] = [];
|
|
73
|
+
private streamed: CacheEntry[] = [];
|
|
74
|
+
private readonly props: Required<StaticProps>;
|
|
75
|
+
|
|
76
|
+
constructor(props: StaticProps) {
|
|
77
|
+
const {
|
|
78
|
+
instrumentation = DEFAULT_STATIC_PROPS.instrumentation,
|
|
79
|
+
transform = DEFAULT_STATIC_PROPS.transform,
|
|
80
|
+
staleEntryThreshold = DEFAULT_STATIC_PROPS.staleEntryThreshold,
|
|
81
|
+
} = props;
|
|
82
|
+
this.props = { instrumentation, transform, staleEntryThreshold };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Writes the given series to the cache, merging written series with any existing
|
|
87
|
+
* series in the cache.
|
|
88
|
+
* @param streamed - Marks the series as live-streamed data. A fetched write evicts
|
|
89
|
+
* every streamed entry whose time range it fully covers.
|
|
90
|
+
*/
|
|
91
|
+
write(series: MultiSeries, streamed: boolean = false): void {
|
|
92
|
+
if (series.length === 0) return;
|
|
93
|
+
if (!streamed) this.evictStreamed(series);
|
|
94
|
+
const entries = streamed ? this.streamed : this.fetched;
|
|
95
|
+
series.series.forEach((s) =>
|
|
96
|
+
this.writeOne(this.props.transform.convert(s), entries),
|
|
97
|
+
);
|
|
98
|
+
this.repairIntegrity(series, entries);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Containment, not overlap: a fetch stamped wider than the data it returned
|
|
102
|
+
// (an uncommitted tail) must not evict streamed samples it did not replace.
|
|
103
|
+
private evictStreamed(written: MultiSeries): void {
|
|
104
|
+
this.streamed = this.streamed.filter(
|
|
105
|
+
(e) =>
|
|
106
|
+
!written.series.some(
|
|
107
|
+
(s) =>
|
|
108
|
+
s.timeRange.start.beforeEq(e.data.timeRange.start) &&
|
|
109
|
+
s.timeRange.end.afterEq(e.data.timeRange.end),
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Executes a 'dirty' read of the cache, retrieving any series in the cache that
|
|
116
|
+
* overlap with the given time range. The series may extend before or after the range.
|
|
117
|
+
* Gaps are computed against fetched entries only. Streamed entries carry provisional
|
|
118
|
+
* leading alignments that cannot pair with fetched data on another channel, so they
|
|
119
|
+
* never claim coverage; the fetch they provoke evicts them.
|
|
120
|
+
* @returns A list of series that overlap with the given time range and a list of
|
|
121
|
+
* gaps, representing the regions of time the fetched series do not cover.
|
|
122
|
+
*/
|
|
123
|
+
dirtyRead(tr: TimeRange): DirtyReadResult {
|
|
124
|
+
const overlapping = (entries: CacheEntry[]): Series[] =>
|
|
125
|
+
entries.filter((e) => e.data.timeRange.overlapsWith(tr)).map((e) => e.data);
|
|
126
|
+
const fetched = overlapping(this.fetched);
|
|
127
|
+
const series = [...fetched, ...overlapping(this.streamed)];
|
|
128
|
+
if (fetched.length === 0) return { series: new MultiSeries(series), gaps: [tr] };
|
|
129
|
+
const gaps: TimeRange[] = [];
|
|
130
|
+
const pushGap = (start: TimeStamp, end: TimeStamp): void => {
|
|
131
|
+
const gap = new TimeRange(start, end);
|
|
132
|
+
if (gap.isValid && !gap.span.isZero) gaps.push(gap);
|
|
133
|
+
};
|
|
134
|
+
pushGap(tr.start, fetched[0].timeRange.start);
|
|
135
|
+
for (let i = 1; i < fetched.length; i++)
|
|
136
|
+
pushGap(fetched[i - 1].timeRange.end, fetched[i].timeRange.start);
|
|
137
|
+
pushGap(fetched[fetched.length - 1].timeRange.end, tr.end);
|
|
138
|
+
return { series: new MultiSeries(series), gaps };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Garbage collects the cache, removing any stale entries.
|
|
143
|
+
* @returns metrics about the garbage collection.
|
|
144
|
+
*/
|
|
145
|
+
gc(): GCMetrics {
|
|
146
|
+
const { staleEntryThreshold } = this.props;
|
|
147
|
+
const res = zeroGCMetrics();
|
|
148
|
+
const collect = (entries: CacheEntry[]): CacheEntry[] =>
|
|
149
|
+
entries.filter((s) => {
|
|
150
|
+
const shouldKeep =
|
|
151
|
+
s.data.refCount > 0 ||
|
|
152
|
+
TimeStamp.since(s.addedAt).lessThan(staleEntryThreshold);
|
|
153
|
+
if (!shouldKeep) {
|
|
154
|
+
res.purgedBytes = res.purgedBytes.add(s.data.byteCapacity);
|
|
155
|
+
res.purgedSeries++;
|
|
156
|
+
}
|
|
157
|
+
return shouldKeep;
|
|
158
|
+
});
|
|
159
|
+
this.fetched = collect(this.fetched);
|
|
160
|
+
this.streamed = collect(this.streamed);
|
|
161
|
+
return res;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Closes the cache, freeing all of its resources. */
|
|
165
|
+
close(): void {
|
|
166
|
+
this.fetched = [];
|
|
167
|
+
this.streamed = [];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private writeOne(series: Series, entries: CacheEntry[]): void {
|
|
171
|
+
const {
|
|
172
|
+
instrumentation: { L },
|
|
173
|
+
} = this.props;
|
|
174
|
+
if (series.length === 0) return;
|
|
175
|
+
const insertionPlan = bounds.buildInsertionPlan(
|
|
176
|
+
entries.map((s) => s.data.alignmentBounds),
|
|
177
|
+
series.alignmentBounds,
|
|
178
|
+
);
|
|
179
|
+
if (insertionPlan === null)
|
|
180
|
+
return L.debug("Found no viable insertion plan", () => ({
|
|
181
|
+
inserting: series.digest,
|
|
182
|
+
cacheContents: entries.map((s) => s.data.digest),
|
|
183
|
+
}));
|
|
184
|
+
const { removeBefore, removeAfter, insertInto, deleteInBetween } = insertionPlan;
|
|
185
|
+
series = series.slice(removeBefore, series.length - removeAfter);
|
|
186
|
+
if (series.length === 0) return;
|
|
187
|
+
entries.splice(insertInto, deleteInBetween, {
|
|
188
|
+
data: series,
|
|
189
|
+
addedAt: TimeStamp.now(),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private repairIntegrity(write: MultiSeries, entries: CacheEntry[]): void {
|
|
194
|
+
const {
|
|
195
|
+
instrumentation: { L },
|
|
196
|
+
} = this.props;
|
|
197
|
+
// Entries are ordered and non-overlapping, so neighbor comparison suffices. An
|
|
198
|
+
// overlap is an insertion bug: evict both entries and let a refetch heal the gap.
|
|
199
|
+
for (let i = 1; i < entries.length; i++) {
|
|
200
|
+
if (
|
|
201
|
+
!bounds.overlapsWith(
|
|
202
|
+
entries[i - 1].data.alignmentBounds,
|
|
203
|
+
entries[i].data.alignmentBounds,
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
continue;
|
|
207
|
+
const [prev, curr] = entries.splice(i - 1, 2);
|
|
208
|
+
L.error("cache integrity violation - evicting overlapping entries", () => ({
|
|
209
|
+
write: write.series.map((s) => s.digest),
|
|
210
|
+
evicted: [prev.data.digest, curr.data.digest],
|
|
211
|
+
}));
|
|
212
|
+
i = 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|