@things-factory/headless-twin 10.0.14 → 10.0.17
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-server/engine/attention-digest.d.ts +4 -4
- package/dist-server/engine/attention-digest.js +7 -7
- package/dist-server/engine/attention-digest.js.map +1 -1
- package/dist-server/engine/canonical-ingest.d.ts +11 -2
- package/dist-server/engine/canonical-ingest.js +137 -8
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/command-routing.js +1 -1
- package/dist-server/engine/command-routing.js.map +1 -1
- package/dist-server/engine/declared-stimulus.js +1 -1
- package/dist-server/engine/declared-stimulus.js.map +1 -1
- package/dist-server/engine/energy-topology.js +1 -1
- package/dist-server/engine/energy-topology.js.map +1 -1
- package/dist-server/engine/ingest-dedupe.d.ts +38 -0
- package/dist-server/engine/ingest-dedupe.js +145 -0
- package/dist-server/engine/ingest-dedupe.js.map +1 -0
- package/dist-server/engine/ingest-health.d.ts +124 -9
- package/dist-server/engine/ingest-health.js +169 -15
- package/dist-server/engine/ingest-health.js.map +1 -1
- package/dist-server/engine/integration-probes.d.ts +3 -3
- package/dist-server/engine/integration-probes.js +6 -6
- package/dist-server/engine/integration-probes.js.map +1 -1
- package/dist-server/engine/kpi-baseline.js +4 -4
- package/dist-server/engine/kpi-baseline.js.map +1 -1
- package/dist-server/engine/kpi-fold.d.ts +122 -12
- package/dist-server/engine/kpi-fold.js +247 -18
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.d.ts +11 -11
- package/dist-server/engine/kpi-query.js +185 -28
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/live-feed-registry.d.ts +1 -1
- package/dist-server/engine/live-feed-registry.js +1 -1
- package/dist-server/engine/live-feed-registry.js.map +1 -1
- package/dist-server/engine/load-meter.d.ts +1 -1
- package/dist-server/engine/load-meter.js.map +1 -1
- package/dist-server/engine/local-declarations.d.ts +7 -7
- package/dist-server/engine/local-declarations.js +9 -9
- package/dist-server/engine/local-declarations.js.map +1 -1
- package/dist-server/engine/log.d.ts +1 -1
- package/dist-server/engine/log.js +1 -1
- package/dist-server/engine/log.js.map +1 -1
- package/dist-server/engine/measured-estimator.js +1 -1
- package/dist-server/engine/measured-estimator.js.map +1 -1
- package/dist-server/engine/measured-yield.js +1 -1
- package/dist-server/engine/measured-yield.js.map +1 -1
- package/dist-server/engine/model-basis.d.ts +1 -1
- package/dist-server/engine/model-basis.js +1 -1
- package/dist-server/engine/model-basis.js.map +1 -1
- package/dist-server/engine/model-gap.d.ts +3 -3
- package/dist-server/engine/model-gap.js +1 -1
- package/dist-server/engine/model-gap.js.map +1 -1
- package/dist-server/engine/model-vocabulary.js +1 -1
- package/dist-server/engine/model-vocabulary.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +4 -4
- package/dist-server/engine/oee-accumulator.js +3 -3
- package/dist-server/engine/oee-accumulator.js.map +1 -1
- package/dist-server/engine/property-effects.js +2 -2
- package/dist-server/engine/property-effects.js.map +1 -1
- package/dist-server/engine/read-time.d.ts +22 -0
- package/dist-server/engine/read-time.js +81 -0
- package/dist-server/engine/read-time.js.map +1 -0
- package/dist-server/engine/restart-policy.js +1 -1
- package/dist-server/engine/restart-policy.js.map +1 -1
- package/dist-server/engine/runtime-key.js +1 -1
- package/dist-server/engine/runtime-key.js.map +1 -1
- package/dist-server/engine/spec-coverage.d.ts +2 -2
- package/dist-server/engine/spec-coverage.js +1 -1
- package/dist-server/engine/spec-coverage.js.map +1 -1
- package/dist-server/engine/stage-path.d.ts +4 -4
- package/dist-server/engine/stage-path.js +1 -1
- package/dist-server/engine/stage-path.js.map +1 -1
- package/dist-server/engine/state-axes.d.ts +1 -1
- package/dist-server/engine/state-axes.js +2 -2
- package/dist-server/engine/state-axes.js.map +1 -1
- package/dist-server/engine/travel-estimator.d.ts +2 -2
- package/dist-server/engine/travel-estimator.js +1 -1
- package/dist-server/engine/travel-estimator.js.map +1 -1
- package/dist-server/engine/twin-engine.d.ts +243 -53
- package/dist-server/engine/twin-engine.js +690 -191
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/engine/warm-start.d.ts +2 -2
- package/dist-server/engine/warm-start.js +5 -5
- package/dist-server/engine/warm-start.js.map +1 -1
- package/dist-server/index.js +1 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js +1 -1
- package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +1 -1
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js +3 -3
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +1 -1
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js +2 -2
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +1 -1
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.d.ts +5 -0
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js +54 -0
- package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +1 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.d.ts +5 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js +44 -0
- package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +1 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.d.ts +6 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js +84 -0
- package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +1 -0
- package/dist-server/migrations/index.js +7 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/routes.d.ts +1 -0
- package/dist-server/routes.js +69 -5
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/index.d.ts +2 -2
- package/dist-server/service/index.js +27 -24
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/control-routing.d.ts +1 -1
- package/dist-server/service/reference/control-routing.js +1 -1
- package/dist-server/service/reference/control-routing.js.map +1 -1
- package/dist-server/service/reference/discovery-result.d.ts +2 -2
- package/dist-server/service/reference/discovery-result.js +3 -3
- package/dist-server/service/reference/discovery-result.js.map +1 -1
- package/dist-server/service/reference/hook-contract.d.ts +43 -0
- package/dist-server/service/reference/hook-contract.js +59 -0
- package/dist-server/service/reference/hook-contract.js.map +1 -0
- package/dist-server/service/reference/ingest-space.d.ts +1 -1
- package/dist-server/service/reference/ingest-space.js +4 -4
- package/dist-server/service/reference/ingest-space.js.map +1 -1
- package/dist-server/service/reference/knob-defaults.d.ts +1 -1
- package/dist-server/service/reference/knob-defaults.js +4 -4
- package/dist-server/service/reference/knob-defaults.js.map +1 -1
- package/dist-server/service/reference/reference-adapter.d.ts +140 -8
- package/dist-server/service/reference/reference-adapter.js +27 -0
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-hook.d.ts +20 -0
- package/dist-server/service/reference/reference-hook.js +133 -0
- package/dist-server/service/reference/reference-hook.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +2 -2
- package/dist-server/service/reference/reference-live.js +88 -13
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +14 -14
- package/dist-server/service/reference/reference-master.js +34 -12
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.d.ts +1 -1
- package/dist-server/service/reference/reference-resolver.js +10 -10
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/reference/twin-reference.d.ts +3 -3
- package/dist-server/service/reference/twin-reference.js.map +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.d.ts +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.js +1 -1
- package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
- package/dist-server/service/twin-audit/command-audit.d.ts +1 -1
- package/dist-server/service/twin-audit/command-audit.js.map +1 -1
- package/dist-server/service/twin-audit/twin-audit-event.d.ts +1 -1
- package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
- package/dist-server/service/twin-audit/twin-audit-query.js +1 -1
- package/dist-server/service/twin-audit/twin-audit-query.js.map +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.js +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +22 -2
- package/dist-server/service/twin-event/twin-event-keys.js +37 -5
- package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-type.d.ts +1 -0
- package/dist-server/service/twin-event/twin-event-type.js +8 -1
- package/dist-server/service/twin-event/twin-event-type.js.map +1 -1
- package/dist-server/service/twin-event/twin-event.d.ts +2 -2
- package/dist-server/service/twin-event/twin-event.js +32 -4
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js +1 -1
- package/dist-server/service/twin-forecast/forecast-metrics.js.map +1 -1
- package/dist-server/service/twin-forecast/gap-analytics.d.ts +1 -1
- package/dist-server/service/twin-forecast/gap-analytics.js.map +1 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js +29 -11
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.d.ts +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js +1 -1
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +1 -1
- package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
- package/dist-server/service/twin-journal/event-type-split-shape.d.ts +50 -0
- package/dist-server/service/twin-journal/event-type-split-shape.js +111 -0
- package/dist-server/service/twin-journal/event-type-split-shape.js.map +1 -0
- package/dist-server/service/twin-journal/event-type-split.d.ts +15 -0
- package/dist-server/service/twin-journal/event-type-split.js +102 -0
- package/dist-server/service/twin-journal/event-type-split.js.map +1 -0
- package/dist-server/service/twin-journal/journal-order.d.ts +15 -0
- package/dist-server/service/twin-journal/journal-order.js +17 -0
- package/dist-server/service/twin-journal/journal-order.js.map +1 -0
- package/dist-server/service/twin-journal/twin-journal-query.d.ts +5 -5
- package/dist-server/service/twin-journal/twin-journal-query.js +232 -21
- package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +27 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +59 -3
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js +14 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js +1 -1
- package/dist-server/service/twin-model/axis-journal-evidence.js.map +1 -1
- package/dist-server/service/twin-model/epcis-coverage.js +36 -1
- package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.js +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -1
- package/dist-server/service/twin-model/isa95-coverage.d.ts +15 -2
- package/dist-server/service/twin-model/isa95-coverage.js +32 -8
- package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
- package/dist-server/service/twin-model/item-ref.js +2 -2
- package/dist-server/service/twin-model/item-ref.js.map +1 -1
- package/dist-server/service/twin-model/name-index.d.ts +1 -1
- package/dist-server/service/twin-model/name-index.js +1 -1
- package/dist-server/service/twin-model/name-index.js.map +1 -1
- package/dist-server/service/twin-model/project-structure.d.ts +1 -1
- package/dist-server/service/twin-model/project-structure.js +3 -3
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +1 -1
- package/dist-server/service/twin-model/twin-equipment.js +1 -1
- package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
- package/dist-server/service/twin-model/twin-lineage-query.js +16 -5
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-location.d.ts +1 -1
- package/dist-server/service/twin-model/twin-location.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.d.ts +3 -3
- package/dist-server/service/twin-model/twin-model-item-query.js +14 -14
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-mutation.d.ts +2 -2
- package/dist-server/service/twin-model/twin-model-mutation.js +4 -4
- package/dist-server/service/twin-model/twin-model-mutation.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-query.js +117 -28
- package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js +22 -0
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-operation.d.ts +1 -1
- package/dist-server/service/twin-model/twin-operation.js +1 -1
- package/dist-server/service/twin-model/twin-operation.js.map +1 -1
- package/dist-server/service/twin-space/move-space.js +2 -2
- package/dist-server/service/twin-space/move-space.js.map +1 -1
- package/dist-server/service/twin-space/representation-role.d.ts +2 -0
- package/dist-server/service/twin-space/representation-role.js +18 -0
- package/dist-server/service/twin-space/representation-role.js.map +1 -0
- package/dist-server/service/twin-space/space-integrity.d.ts +1 -1
- package/dist-server/service/twin-space/space-integrity.js.map +1 -1
- package/dist-server/service/twin-space/twin-space-representation.d.ts +2 -0
- package/dist-server/service/twin-space/twin-space-representation.js +16 -0
- package/dist-server/service/twin-space/twin-space-representation.js.map +1 -1
- package/dist-server/service/twin-space/twin-space-resolver.d.ts +2 -2
- package/dist-server/service/twin-space/twin-space-resolver.js +36 -7
- package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
- package/dist-server/service/twin-structure/twin-structure.js +3 -3
- package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
- package/dist-server/service/twin-subject/event-subjects.d.ts +43 -0
- package/dist-server/service/twin-subject/event-subjects.js +137 -0
- package/dist-server/service/twin-subject/event-subjects.js.map +1 -0
- package/dist-server/service/twin-subject/index.d.ts +9 -0
- package/dist-server/service/twin-subject/index.js +16 -0
- package/dist-server/service/twin-subject/index.js.map +1 -0
- package/dist-server/service/twin-subject/item-resolver.d.ts +10 -0
- package/dist-server/service/twin-subject/item-resolver.js +93 -0
- package/dist-server/service/twin-subject/item-resolver.js.map +1 -0
- package/dist-server/service/twin-subject/subject-query-shape.d.ts +22 -0
- package/dist-server/service/twin-subject/subject-query-shape.js +88 -0
- package/dist-server/service/twin-subject/subject-query-shape.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.d.ts +23 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.js +159 -0
- package/dist-server/service/twin-subject/twin-subject-backfill.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-event.d.ts +14 -0
- package/dist-server/service/twin-subject/twin-subject-event.js +111 -0
- package/dist-server/service/twin-subject/twin-subject-event.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.d.ts +39 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.js +295 -0
- package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-query.d.ts +27 -0
- package/dist-server/service/twin-subject/twin-subject-query.js +232 -0
- package/dist-server/service/twin-subject/twin-subject-query.js.map +1 -0
- package/dist-server/service/twin-subject/twin-subject-writer.d.ts +27 -0
- package/dist-server/service/twin-subject/twin-subject-writer.js +166 -0
- package/dist-server/service/twin-subject/twin-subject-writer.js.map +1 -0
- package/dist-server/service/twin-target/twin-target-resolver.js +1 -1
- package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
- package/dist-shared/entity-delta.d.ts +1 -1
- package/dist-shared/entity-delta.js +3 -3
- package/dist-shared/entity-delta.js.map +1 -1
- package/dist-shared/touched-items.js +2 -2
- package/dist-shared/touched-items.js.map +1 -1
- package/dist-shared/twin-level.js +1 -1
- package/dist-shared/twin-level.js.map +1 -1
- package/package.json +3 -3
- package/server/engine/attention-digest.ts +9 -9
- package/server/engine/canonical-ingest.ts +170 -13
- package/server/engine/command-routing.ts +1 -1
- package/server/engine/declared-stimulus.ts +1 -1
- package/server/engine/energy-topology.ts +1 -1
- package/server/engine/ingest-dedupe.ts +149 -0
- package/server/engine/ingest-health.ts +234 -20
- package/server/engine/integration-probes.ts +7 -7
- package/server/engine/kpi-baseline.ts +4 -4
- package/server/engine/kpi-fold.ts +395 -27
- package/server/engine/kpi-query.ts +212 -46
- package/server/engine/live-feed-registry.ts +1 -1
- package/server/engine/load-meter.ts +1 -1
- package/server/engine/local-declarations.ts +13 -13
- package/server/engine/log.ts +1 -1
- package/server/engine/measured-estimator.ts +1 -1
- package/server/engine/measured-yield.ts +1 -1
- package/server/engine/model-basis.ts +2 -2
- package/server/engine/model-gap.ts +3 -3
- package/server/engine/model-vocabulary.ts +1 -1
- package/server/engine/oee-accumulator.ts +4 -4
- package/server/engine/property-effects.ts +2 -2
- package/server/engine/read-time.ts +77 -0
- package/server/engine/restart-policy.ts +1 -1
- package/server/engine/runtime-key.ts +1 -1
- package/server/engine/spec-coverage.ts +3 -3
- package/server/engine/stage-path.ts +5 -5
- package/server/engine/state-axes.ts +2 -2
- package/server/engine/travel-estimator.ts +2 -2
- package/server/engine/twin-engine.ts +764 -201
- package/server/engine/warm-start.ts +6 -6
- package/server/index.ts +1 -1
- package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +1 -1
- package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +3 -3
- package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +2 -2
- package/server/migrations/1786300000000-IndexEventTypeByTime.ts +48 -0
- package/server/migrations/1786400000000-IndexEventCreatedAt.ts +38 -0
- package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +93 -0
- package/server/migrations/index.ts +7 -1
- package/server/routes.ts +68 -5
- package/server/service/index.ts +4 -1
- package/server/service/reference/control-routing.ts +1 -1
- package/server/service/reference/discovery-result.ts +3 -3
- package/server/service/reference/hook-contract.ts +103 -0
- package/server/service/reference/ingest-space.ts +4 -4
- package/server/service/reference/knob-defaults.ts +4 -4
- package/server/service/reference/reference-adapter.ts +166 -9
- package/server/service/reference/reference-hook.ts +145 -0
- package/server/service/reference/reference-live.ts +92 -14
- package/server/service/reference/reference-master.ts +39 -17
- package/server/service/reference/reference-resolver.ts +10 -10
- package/server/service/reference/twin-reference.ts +3 -3
- package/server/service/twin-attention/twin-attention-query.ts +1 -1
- package/server/service/twin-audit/command-audit.ts +1 -1
- package/server/service/twin-audit/twin-audit-event.ts +2 -2
- package/server/service/twin-audit/twin-audit-query.ts +1 -1
- package/server/service/twin-control/twin-control-mutation.ts +1 -1
- package/server/service/twin-event/twin-event-keys.ts +37 -5
- package/server/service/twin-event/twin-event-type.ts +18 -1
- package/server/service/twin-event/twin-event.ts +32 -6
- package/server/service/twin-forecast/forecast-metrics.ts +1 -1
- package/server/service/twin-forecast/gap-analytics.ts +1 -1
- package/server/service/twin-forecast/twin-forecast-query.ts +30 -11
- package/server/service/twin-ingest-window/twin-ingest-window-query.ts +1 -1
- package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +1 -1
- package/server/service/twin-instance/twin-instance.ts +4 -4
- package/server/service/twin-journal/event-type-split-shape.ts +112 -0
- package/server/service/twin-journal/event-type-split.ts +144 -0
- package/server/service/twin-journal/journal-order.ts +20 -0
- package/server/service/twin-journal/twin-journal-query.ts +224 -20
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +57 -3
- package/server/service/twin-metrics/twin-metrics-query.ts +14 -1
- package/server/service/twin-model/axis-journal-evidence.ts +1 -1
- package/server/service/twin-model/epcis-coverage.ts +36 -1
- package/server/service/twin-model/iec61850-coverage.ts +1 -1
- package/server/service/twin-model/isa95-coverage.ts +45 -8
- package/server/service/twin-model/item-ref.ts +2 -2
- package/server/service/twin-model/name-index.ts +1 -1
- package/server/service/twin-model/project-structure.ts +4 -4
- package/server/service/twin-model/twin-equipment.ts +2 -2
- package/server/service/twin-model/twin-lineage-query.ts +16 -5
- package/server/service/twin-model/twin-location.ts +1 -1
- package/server/service/twin-model/twin-model-item-query.ts +14 -14
- package/server/service/twin-model/twin-model-mutation.ts +4 -4
- package/server/service/twin-model/twin-model-query.ts +117 -28
- package/server/service/twin-model/twin-model-tree-query.ts +25 -1
- package/server/service/twin-model/twin-operation.ts +2 -2
- package/server/service/twin-space/move-space.ts +3 -3
- package/server/service/twin-space/representation-role.ts +15 -0
- package/server/service/twin-space/space-integrity.ts +1 -1
- package/server/service/twin-space/twin-space-representation.ts +37 -0
- package/server/service/twin-space/twin-space-resolver.ts +39 -7
- package/server/service/twin-structure/twin-structure.ts +3 -3
- package/server/service/twin-subject/event-subjects.ts +155 -0
- package/server/service/twin-subject/index.ts +10 -0
- package/server/service/twin-subject/item-resolver.ts +92 -0
- package/server/service/twin-subject/subject-query-shape.ts +84 -0
- package/server/service/twin-subject/twin-subject-backfill.ts +196 -0
- package/server/service/twin-subject/twin-subject-event.ts +101 -0
- package/server/service/twin-subject/twin-subject-fast-path.ts +346 -0
- package/server/service/twin-subject/twin-subject-query.ts +210 -0
- package/server/service/twin-subject/twin-subject-writer.ts +189 -0
- package/server/service/twin-target/twin-target-resolver.ts +1 -1
- package/shared/entity-delta.ts +3 -3
- package/shared/touched-items.ts +2 -2
- package/shared/twin-level.ts +1 -1
- package/test/adopt-structure-live.test.ts +3 -3
- package/test/aggregate-not-findone.test.ts +112 -0
- package/test/attention-digest.test.ts +6 -6
- package/test/axis-read.test.ts +2 -2
- package/test/boot-resume.test.ts +20 -7
- package/test/broadcast-period.test.ts +2 -2
- package/test/broadcast-queue-overflow.test.ts +244 -0
- package/test/canonical-ingest-vocabularies.test.ts +179 -7
- package/test/canonical-quantity-door.test.ts +2 -2
- package/test/checkpoint-refuses-empty.test.ts +2 -2
- package/test/connector-capability-declaration.test.ts +88 -0
- package/test/control-capability.test.ts +1 -1
- package/test/cursor-stall-not-read-failure.test.ts +2 -2
- package/test/declaration-reaches-model.test.ts +5 -5
- package/test/declared-stimulus.test.ts +4 -4
- package/test/discovery-result.test.ts +2 -2
- package/test/entity-delta.test.ts +4 -4
- package/test/event-subjects.test.ts +147 -0
- package/test/event-time-column.test.ts +3 -3
- package/test/event-type-split.test.ts +155 -0
- package/test/fold-gap-speaks.test.ts +53 -0
- package/test/forecast-metrics.test.ts +1 -1
- package/test/forecast-tuning.test.ts +1 -1
- package/test/ingest-health-engine.test.ts +2 -2
- package/test/ingest-health-wiring.test.ts +7 -5
- package/test/ingest-health.test.ts +6 -6
- package/test/ingest-history.test.ts +2 -2
- package/test/ingest-idempotent.test.ts +132 -0
- package/test/ingest-space.test.ts +3 -3
- package/test/integration-probes.test.ts +3 -3
- package/test/integration-runner.test.ts +1 -1
- package/test/item-ref.test.ts +1 -1
- package/test/journal-order-axis.test.ts +80 -0
- package/test/journal-read-discipline.test.ts +16 -6
- package/test/journal-retention.test.ts +171 -29
- package/test/journal-sort-axis.test.ts +1 -1
- package/test/journal-write-door.test.ts +3 -3
- package/test/journal-write-trend.test.ts +1 -1
- package/test/kernel-kind-guard.test.ts +3 -3
- package/test/knob-defaults.test.ts +1 -1
- package/test/kpi-baseline-db.test.ts +2 -2
- package/test/kpi-fold.test.ts +185 -14
- package/test/kpi-query-bench.test.ts +3 -3
- package/test/live-cursor-wiring.test.ts +6 -6
- package/test/live-kernel-facts.test.ts +11 -11
- package/test/live-mirror-parity.test.ts +3 -3
- package/test/load-meter.test.ts +1 -1
- package/test/local-declarations.test.ts +10 -10
- package/test/log-stamp.test.ts +1 -1
- package/test/measured-yield.test.ts +2 -2
- package/test/merge-streams.test.ts +70 -0
- package/test/mirror-resumes-from-checkpoint.test.ts +13 -13
- package/test/model-basis.test.ts +2 -2
- package/test/model-gap.test.ts +4 -4
- package/test/model-vocabulary.test.ts +2 -2
- package/test/move-space.test.ts +1 -1
- package/test/oee-accumulator.test.ts +2 -2
- package/test/operational-vocabulary.test.ts +2 -2
- package/test/project-structure-db.test.ts +2 -2
- package/test/projection-reaches-screen.test.ts +2 -2
- package/test/property-effects.test.ts +3 -3
- package/test/read-failure-ledger.test.ts +106 -0
- package/test/read-failure-visible.test.ts +7 -7
- package/test/read-time.test.ts +118 -0
- package/test/reference-grounding.test.ts +1 -1
- package/test/reference-hook.test.ts +86 -0
- package/test/registry-key-guard.test.ts +1 -1
- package/test/rename-twin.test.ts +81 -0
- package/test/restart-policy.test.ts +3 -3
- package/test/resync-origin-site.test.ts +3 -3
- package/test/revision-axis.test.ts +14 -8
- package/test/runtime-key.test.ts +3 -3
- package/test/snapshot-freshness.test.ts +4 -4
- package/test/source-outcome-audit.test.ts +1 -1
- package/test/space-integrity.test.ts +1 -1
- package/test/space-representation.test.ts +66 -0
- package/test/space-scope-includes-stopped.test.ts +55 -0
- package/test/spec-coverage.test.ts +1 -1
- package/test/standard-coverage.test.ts +43 -1
- package/test/status-tally.test.ts +1 -1
- package/test/structure-revision-db.test.ts +7 -7
- package/test/subject-fast-path.test.ts +148 -0
- package/test/subject-read-model.test.ts +175 -0
- package/test/touched-items.test.ts +2 -2
- package/test/twin-audit.test.ts +1 -1
- package/test/twin-event-keys.test.ts +49 -3
- package/test/twin-model-item-db.test.ts +5 -5
- package/test/twin-model-tree-db.test.ts +35 -2
- package/test/twin-origin-resync.test.ts +1 -1
- package/test/warm-start-seam.test.ts +1 -1
- package/test/warm-start.test.ts +6 -6
- package/test/withheld-door.test.ts +95 -0
- package/test/yield-loop.test.ts +4 -4
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* ★ 저널 보존 —
|
|
2
|
+
* ★ 저널 보존 — **선언이 있을 때만 지운다. 그리고 도는 트윈에서만 체크포인트를 상한으로 본다.**
|
|
3
3
|
*
|
|
4
4
|
* ── 왜 필요한가 (2026-08-22 실측) ───────────────────────────────────────────
|
|
5
5
|
* 개발 저널이 시간당 **581,794행 · 0.85GB**(하루 20GB)로 자랐다. 데모 MES 트윈 셋이 전체의 **97%** 를
|
|
6
|
-
* 만들고 지우는 것이 없었다.
|
|
7
|
-
* 것은 없었다** — 그러면 며칠마다 같은 자리로 돌아온다.
|
|
6
|
+
* 만들고 지우는 것이 없었다.
|
|
8
7
|
*
|
|
9
|
-
* ──
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* ── 체크포인트를 전제 조건으로 두었던 것이 결함이었다 (2026-08-27) ──────────
|
|
9
|
+
* 예전 규율은 「체크포인트가 없는 인스턴스는 건드리지 않는다」였다. 근거는 「그때 저널이 유일한 복구
|
|
10
|
+
* 수단이다」였고, 그 근거가 틀렸다. 트윈이 자기 저널과 어떤 관계인지는 `restartPolicy` 가 선언한다.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* ③ **체크포인트 리비전보다 뒤는 지우지 않는다.** 그 뒤는 스냅샷이 대신하지 못한다.
|
|
12
|
+
* resync 연결된 시스템에서 다시 읽는다 저널은 복구 수단이 아니다
|
|
13
|
+
* reset 씨앗부터 다시 돌린다 저널은 복구 수단이 아니다
|
|
14
|
+
* resume 저널을 이어 세운다 보관된 구간에서 세운다
|
|
17
15
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* 셋 다 보관 기간 밖의 사건을 요구하지 않는다. 보존 기간을 7일로 선언한 것이 곧 「7일 전 상태로는
|
|
17
|
+
* 세우지 않는다」는 뜻이다. 그 전제 때문에 멈춘 트윈 셋에 2,900만 행이 영구히 남았다.
|
|
20
18
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
19
|
+
* 체크포인트가 남는 일은 하나다. **도는 트윈**은 메모리에서 이어 집계하므로, 체크포인트가 아직 반영하지
|
|
20
|
+
* 못한 사건을 지우면 그 구간이 어디에도 없어진다. 그래서 도는 트윈에서만 그 리비전을 상한으로 쓴다.
|
|
21
|
+
*
|
|
22
|
+
* ── 이 테스트가 무엇을 재는가 ───────────────────────────────────────────────
|
|
23
|
+
* DB 를 띄우지 않는다. 이 규율은 **조건을 어떻게 세우나**에 있고 그것은 순수하게 확인할 수 있다.
|
|
25
24
|
*/
|
|
26
25
|
import { test } from 'node:test'
|
|
27
26
|
import assert from 'node:assert/strict'
|
|
@@ -45,18 +44,27 @@ test('선언이 없으면 아무것도 지우지 않는다 — 기본값은 없
|
|
|
45
44
|
assert.match(
|
|
46
45
|
src,
|
|
47
46
|
/static JOURNAL_RETENTION_DAYS\?: number = undefined/,
|
|
48
|
-
'보존 기간의 기본값은 undefined 여야 한다(
|
|
47
|
+
'보존 기간의 기본값은 undefined 여야 한다(알리지 않고 지우는 것보다 알리지 않고 쌓는 편이 낫다)'
|
|
49
48
|
)
|
|
50
49
|
/* 그리고 그 값이 없으면 즉시 돌아간다. */
|
|
51
50
|
assert.match(pruneBody(), /if \(!days \|\| days <= 0\) return/, '선언이 없으면 지우지 않고 돌아간다')
|
|
52
51
|
})
|
|
53
52
|
|
|
54
|
-
test('
|
|
53
|
+
test('★ 체크포인트는 상한이지 전제 조건이 아니다 — 없다는 이유로 건너뛰지 않는다', () => {
|
|
55
54
|
const body = pruneBody()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
/*
|
|
56
|
+
* 한 줄이 이 규율의 전부다. 있으면 그 리비전이 상한이고, 없으면 상한이 없다.
|
|
57
|
+
*
|
|
58
|
+
* 예전에는 없으면 그 트윈을 건너뛰었다. 그래서 멈춘 트윈 셋에 2,900만 행이 영구히 남았다 —
|
|
59
|
+
* 멈춘 트윈은 체크포인트를 다시 쓸 주체가 없어서 만료된 뒤 영원히 조건을 못 넘긴다.
|
|
60
|
+
*/
|
|
61
|
+
assert.match(
|
|
62
|
+
body,
|
|
63
|
+
/const upTo = at > 0 \? at : Number\.MAX_SAFE_INTEGER/,
|
|
64
|
+
'체크포인트가 없으면 상한 없이 지운다'
|
|
65
|
+
)
|
|
66
|
+
assert.doesNotMatch(body, /if \(!upTo\)[\s\S]{0,200}?continue/, '없다는 이유로 건너뛰지 않는다')
|
|
67
|
+
assert.doesNotMatch(body, /skipped/, '건너뛰는 갈래가 아예 없다')
|
|
60
68
|
})
|
|
61
69
|
|
|
62
70
|
test('지우는 조건이 넷 다 있다 — 하나라도 빠지면 지나친 삭제가 된다', () => {
|
|
@@ -64,7 +72,7 @@ test('지우는 조건이 넷 다 있다 — 하나라도 빠지면 지나친
|
|
|
64
72
|
for (const [what, re] of [
|
|
65
73
|
['도메인', /domain_id = :domainId/],
|
|
66
74
|
['인스턴스', /instance_id = :instanceId/],
|
|
67
|
-
['체크포인트 리비전 이하', /revision <= :upTo/],
|
|
75
|
+
['체크포인트 리비전 이하(도는 트윈에서는 상한, 멈춘 트윈에서는 무한)', /revision <= :upTo/],
|
|
68
76
|
['보존 기간 이전(실제 시계)', /created_at < :cutoff/]
|
|
69
77
|
] as [string, RegExp][]) {
|
|
70
78
|
assert.match(body, re, `${what} 조건이 있어야 한다`)
|
|
@@ -93,14 +101,35 @@ test('도메인의 정책이 프로세스 기본값보다 먼저다 — 그리
|
|
|
93
101
|
assert.doesNotMatch(src, /from '@things-factory\/setting-base'/, '엔진은 Setting 을 알지 않는다')
|
|
94
102
|
})
|
|
95
103
|
|
|
96
|
-
test('보존
|
|
104
|
+
test('★ 보존 기간을 스냅샷 TTL 로 올리지 않는다 — 두 값은 다른 것을 정한다', () => {
|
|
105
|
+
/*
|
|
106
|
+
* 예전에는 `max(보존 기간, 스냅샷 TTL)` 이었다. 둘 다 7일이라 상향은 없었지만, 그 식은 두 값을 묶어
|
|
107
|
+
* 놓아서 보존 기간을 줄이면 스냅샷 TTL 이 따라오게 만든다.
|
|
108
|
+
*
|
|
109
|
+
* 보존 기간 이력을 며칠 두나
|
|
110
|
+
* 스냅샷 TTL 빠르게 세우기 위한 저장본이 며칠 사나
|
|
111
|
+
*
|
|
112
|
+
* 저장본이 만료되어도 트윈은 보관된 구간에서 세워진다. 그래서 보존 기간이 더 짧아도 성립한다.
|
|
113
|
+
*/
|
|
97
114
|
const body = pruneBody()
|
|
98
|
-
assert.
|
|
99
|
-
assert.match(body, /
|
|
100
|
-
assert.match(body, /twinWarn\(/, '올렸다는 사실을 말한다(조용히 바꾸지 않는다)')
|
|
115
|
+
assert.doesNotMatch(body, /Math\.max\(days, minDays\)/, '두 값을 묶지 않는다')
|
|
116
|
+
assert.match(body, /const effectiveDays = days/, '선언한 보존 기간을 그대로 쓴다')
|
|
101
117
|
})
|
|
102
118
|
|
|
103
|
-
test('
|
|
119
|
+
test('★ 멈출 때는 만료 없이 적는다 — 그러지 않으면 7일 뒤 그 상태를 아는 것이 없다', () => {
|
|
120
|
+
/*
|
|
121
|
+
* 멈춘 트윈은 아무도 스냅샷을 다시 쓰지 않아서 7일 뒤 만료된다. 멈추는 순간이 그 상태가 메모리에
|
|
122
|
+
* 있는 마지막 순간이므로 그때 만료 없이 적는다. 그러면 다시 뜰 때 보관된 구간을 계산하지 않아도 된다.
|
|
123
|
+
*/
|
|
124
|
+
assert.match(src, /static SNAPSHOT_KEEP_S = /, '만료 없이 두는 기간에 이름이 있어야 한다')
|
|
125
|
+
const at = src.indexOf('static async stop(')
|
|
126
|
+
assert.ok(at > 0, 'stop 이 있어야 한다')
|
|
127
|
+
const stopBody = src.slice(at, at + 1600)
|
|
128
|
+
assert.match(stopBody, /persistSnapshot\(domainId, id, true\)/, '멈출 때는 만료 없이 적는다')
|
|
129
|
+
assert.match(src, /keepForever \? this\.SNAPSHOT_KEEP_S : this\.SNAPSHOT_TTL_S/, '그 값이 실제로 쓰인다')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('지운 것을 말한다 — 알리지 않고 줄어든 저널은 없었던 일과 구별되지 않는다', () => {
|
|
104
133
|
const body = pruneBody()
|
|
105
134
|
assert.match(body, /journal pruned/, '지운 건수를 로그에 남긴다')
|
|
106
135
|
assert.match(body, /revision ≤/, '어디까지 지웠는지 함께 남긴다')
|
|
@@ -121,7 +150,7 @@ test('선언도 없고 물을 길도 없으면 주기 정리를 걸지 않는다
|
|
|
121
150
|
* 앱이 답하는 시임(`retentionDaysOf`)이 있고, 그것이 심겨 있으면 기본값이 없어도 걸어야 한다
|
|
122
151
|
* (그 도메인이 자기 값을 가질 수 있다). 반대로 **둘 다 없으면 물을 곳이 없으므로** 걸지 않는다.
|
|
123
152
|
*
|
|
124
|
-
* 기본값만 보게 두면 시임만 심은 배포에서 정리가
|
|
153
|
+
* 기본값만 보게 두면 시임만 심은 배포에서 정리가 알리지 않고 돌지 않는다 — 「보존을 켰는데 왜 안 줄어드나」.
|
|
125
154
|
*/
|
|
126
155
|
assert.match(
|
|
127
156
|
body,
|
|
@@ -131,3 +160,116 @@ test('선언도 없고 물을 길도 없으면 주기 정리를 걸지 않는다
|
|
|
131
160
|
/* 타이머가 프로세스를 붙잡지 않게 — 지우는 일이 종료를 막을 이유가 없다. */
|
|
132
161
|
assert.match(body, /unref/, '타이머는 unref 한다')
|
|
133
162
|
})
|
|
163
|
+
|
|
164
|
+
/*
|
|
165
|
+
* ★ 나눠서 지운다 — 한 문장으로 통째 지우면 그동안 호스트가 멈춘다.
|
|
166
|
+
*
|
|
167
|
+
* 실측(2026-08-25 · 개발 환경 44GB): 보관 기간 7일에 13일치가 쌓여 있었고, 그 밀린 몫이 한 번에
|
|
168
|
+
* 나왔다. 한 번의 지우기가 74초·79초였고 그 뒤에 한 줄짜리 `domains` 조회가 67초로 찍혔다 — 그
|
|
169
|
+
* 질의의 문제가 아니라 줄을 선 값이다. sqlite 는 쓰기가 하나다.
|
|
170
|
+
*
|
|
171
|
+
* 이 테스트는 소스를 전수 조회해 규율을 지킨다: 배치 경계를 먼저 찾는가 · 한 창의 시간 상한이 있는가 ·
|
|
172
|
+
* 배치 사이에 루프를 비워 주는가. 실제 지우기는 큰 기록이 있어야 재현되므로 여기서 재지 않는다.
|
|
173
|
+
*/
|
|
174
|
+
test('★ 지우기를 배치로 나눈다 — 쓰기 잠금을 한 번에 오래 잡지 않는다', () => {
|
|
175
|
+
const src = readFileSync(ENGINE, 'utf8')
|
|
176
|
+
assert.ok(/JOURNAL_PRUNE_BATCH\s*=\s*[0-9_]+/.test(src), '한 배치의 행 수가 이름을 갖고 있어야 한다')
|
|
177
|
+
assert.ok(/JOURNAL_PRUNE_BUDGET_MS\s*=\s*[0-9_]+/.test(src), '한 창의 시간 상한이 이름을 갖고 있어야 한다')
|
|
178
|
+
const prune = src.slice(src.indexOf('static async pruneJournal'))
|
|
179
|
+
const body = prune.slice(0, prune.indexOf('static startRetentionLoop'))
|
|
180
|
+
assert.ok(body.includes('JOURNAL_PRUNE_BATCH'), '배치 경계를 찾는 데 그 수를 쓴다')
|
|
181
|
+
assert.ok(body.includes('JOURNAL_PRUNE_BUDGET_MS'), '한 창의 시간 상한을 본다')
|
|
182
|
+
assert.ok(/setImmediate/.test(body), '배치 사이에 루프를 비워 준다 — 없으면 나눈 뜻이 없다')
|
|
183
|
+
/* `DELETE … LIMIT` 은 드라이버마다 다르다 — 경계 `revision` 을 찾아 그 아래만 지운다. */
|
|
184
|
+
assert.ok(!/delete[\s\S]{0,200}limit\(/i.test(body), 'DELETE 에 LIMIT 을 붙이지 않는다')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
* ★ 앞부분이 지워진 것을 목록이 말한다.
|
|
189
|
+
*
|
|
190
|
+
* 정리가 오래된 사건을 지우면 목록을 아무리 내려가도 어느 지점에서 기록이 끝난다. 화면이 그것을 말하지
|
|
191
|
+
* 않으면 사람은 「이 트윈은 그때 시작했다」로 읽는다. 없었던 것과 지워진 것은 다른 사실이다.
|
|
192
|
+
*/
|
|
193
|
+
test('★ 남아 있는 가장 오래된 리비전을 목록이 함께 낸다 — 지워진 것을 없었던 것으로 보이지 않게', () => {
|
|
194
|
+
const type = readFileSync(
|
|
195
|
+
join(import.meta.dirname, '..', 'server', 'service', 'twin-event', 'twin-event-type.ts'),
|
|
196
|
+
'utf8'
|
|
197
|
+
)
|
|
198
|
+
assert.match(type, /oldestRevision\?: number/, '목록 응답에 그 칸이 있어야 한다')
|
|
199
|
+
assert.match(type, /retention policy/, '무슨 뜻인지 설명이 있어야 한다(화면이 문구를 만든다)')
|
|
200
|
+
|
|
201
|
+
const query = readFileSync(
|
|
202
|
+
join(import.meta.dirname, '..', 'server', 'service', 'twin-journal', 'twin-journal-query.ts'),
|
|
203
|
+
'utf8'
|
|
204
|
+
)
|
|
205
|
+
/* 저장하지 않고 조회할 때 구한다 — 저장한 값은 실제 데이터와 어긋날 수 있다. */
|
|
206
|
+
assert.match(query, /orderBy\('e\.revision', 'ASC'\)[\s\S]{0,120}?limit\(1\)/, '가장 작은 리비전 한 행만 읽는다')
|
|
207
|
+
/* 트윈 하나를 물었을 때만 — 여러 트윈을 합치면 리비전은 트윈마다 따로 세는 번호다. */
|
|
208
|
+
assert.match(query, /if \(instanceIds\.length === 1\)/, '트윈 하나일 때만 낸다')
|
|
209
|
+
assert.match(query, /nextCursor, oldestRevision \}/, '응답에 실어 보낸다')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
/*
|
|
213
|
+
* ★ 경계를 시각순으로 찾는다 — 그러지 않으면 색인이 쓰이지 않는다.
|
|
214
|
+
*
|
|
215
|
+
* ── 무엇이 났나 (2026-08-27 실측 · 개발 파일 54GB · 3,128만 행) ───────────────
|
|
216
|
+
* 배치 경계를 `ORDER BY revision` 으로 찾았다. 그러면 계획기가 리비전 색인을 고르고, 지울 대상인지는
|
|
217
|
+
* 행마다 `created_at` 을 열어 확인한다. 지울 것이 적으면 그 트윈의 저널을 끝까지 걸어야 「한 배치를
|
|
218
|
+
* 못 채웠다」를 알 수 있다 — 1,029만 행에서 그것이 2초 예산을 다 썼고 44건만 지우고 멈췄다.
|
|
219
|
+
*
|
|
220
|
+
* 실측한 질의 계획.
|
|
221
|
+
*
|
|
222
|
+
* ORDER BY revision SEARCH USING INDEX ix_twin_event_0 ← 행마다 테이블을 연다
|
|
223
|
+
* ORDER BY createdAt SEARCH USING COVERING INDEX ix_twin_event_8 ← 테이블을 열지 않는다
|
|
224
|
+
* DELETE (정렬 없음) SEARCH USING INDEX ix_twin_event_8 ← 색인만으로 이미 고쳐졌다
|
|
225
|
+
*
|
|
226
|
+
* 그리고 `created_at` 축 색인을 얹었다(`ix_twin_event_8`). 7일 밖 건수 조회가 208초에서 1.68초가 됐다.
|
|
227
|
+
*/
|
|
228
|
+
test('★ 배치 경계를 createdAt 순으로 찾는다 — revision 순으로 찾으면 색인을 못 쓴다', () => {
|
|
229
|
+
const body = pruneBody()
|
|
230
|
+
assert.match(body, /\.orderBy\('e\.createdAt', 'ASC'\)/, '시각순으로 물어야 색인을 쓴다')
|
|
231
|
+
assert.doesNotMatch(body, /\.orderBy\('e\.revision', 'ASC'\)/, '리비전 순으로 되돌아가지 않는다')
|
|
232
|
+
/* 같은 시각의 행이 여럿일 수 있으므로 경계는 `<=` 다 — `<` 로 두면 제자리걸음이 된다. */
|
|
233
|
+
assert.match(body, /created_at <= :batchCutoff/, '경계 시각 이하까지 지운다')
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
test('★ createdAt 축 색인이 선언돼 있다 — 없으면 정리가 전량 주사한다', () => {
|
|
237
|
+
const entity = readFileSync(
|
|
238
|
+
join(import.meta.dirname, '..', 'server', 'service', 'twin-event', 'twin-event.ts'),
|
|
239
|
+
'utf8'
|
|
240
|
+
)
|
|
241
|
+
assert.match(
|
|
242
|
+
entity,
|
|
243
|
+
/@Index\('ix_twin_event_8', \(e: TwinEvent\) => \[e\.domain, e\.instanceId, e\.createdAt\]/,
|
|
244
|
+
'(domain, instanceId, createdAt) 색인이 있어야 한다'
|
|
245
|
+
)
|
|
246
|
+
/* 그리고 그것을 만드는 마이그레이션이 배선돼 있어야 한다 — 선언만 있으면 배포에 생기지 않는다. */
|
|
247
|
+
const list = readFileSync(join(import.meta.dirname, '..', 'server', 'migrations', 'index.ts'), 'utf8')
|
|
248
|
+
assert.match(list, /IndexEventCreatedAt1786400000000/, '마이그레이션 목록에 있어야 한다')
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
test('★ 한 문장이 짧아야 화면이 오래 멈추지 않는다 — 실측이 그 수를 정한다', () => {
|
|
252
|
+
/*
|
|
253
|
+
* ── 무엇이 났나 (2026-08-28 실측) ──────────────────────────────────────────
|
|
254
|
+
* 배치가 20,000 이었고, 한 문장이 그만큼 지우는 데 4~5.6초였다(서버 기록: hatio-mx2 20,130줄
|
|
255
|
+
* 5.2초). sqlite 는 연결이 하나라 그동안 **화면의 모든 질의가 줄을 선다** — 첫 화면 조회가
|
|
256
|
+
* 12.2초였다(정상 상태 40밀리초).
|
|
257
|
+
*
|
|
258
|
+
* 그리고 예산이 **문장이 끝난 뒤에** 검사되므로 한 문장이 2초 예산을 2~3배 넘겼다. 배치를 나눈 뜻이
|
|
259
|
+
* 그만큼 없어진다.
|
|
260
|
+
*
|
|
261
|
+
* 고칠 축은 총 시간이 아니라 **한 번에 멈추는 길이**다. 그래서 배치를 줄이고 예산을 늘렸다 —
|
|
262
|
+
* 지우는 양은 같고 잠금만 잘게 나뉜다.
|
|
263
|
+
*/
|
|
264
|
+
const src = readFileSync(ENGINE, 'utf8')
|
|
265
|
+
const batch = /JOURNAL_PRUNE_BATCH\s*=\s*([0-9_]+)/.exec(src)?.[1]?.replace(/_/g, '')
|
|
266
|
+
const budget = /JOURNAL_PRUNE_BUDGET_MS\s*=\s*([0-9_]+)/.exec(src)?.[1]?.replace(/_/g, '')
|
|
267
|
+
assert.ok(batch && budget)
|
|
268
|
+
/* 줄당 약 0.26밀리초로 재었다 — 한 문장이 1초를 넘지 않아야 한다. */
|
|
269
|
+
const perStatementMs = Number(batch) * 0.26
|
|
270
|
+
assert.ok(perStatementMs <= 1000, `한 문장이 ${Math.round(perStatementMs)}밀리초로 추정된다 — 1초를 넘으면 화면이 그만큼 멈춘다`)
|
|
271
|
+
/* 예산이 문장 여럿을 담아야 나눈 뜻이 있다 — 하나만 담으면 예산 검사가 아무 일도 하지 않는다. */
|
|
272
|
+
assert.ok(Number(budget) / perStatementMs >= 3, '예산이 한 문장에 삼켜지면 배치를 나눈 뜻이 없다')
|
|
273
|
+
/* 실측 근거가 코드에 적혀 있어야 한다 — 다음 사람이 다시 재지 않고 바꾸지 않게. */
|
|
274
|
+
assert.match(src, /20,130줄/, '무엇을 재서 이 수가 나왔는지 적혀 있어야 한다')
|
|
275
|
+
})
|
|
@@ -73,7 +73,7 @@ test('저널을 시간으로 거르는 질의는 시간으로 정렬한다 —
|
|
|
73
73
|
|
|
74
74
|
/*
|
|
75
75
|
* **상한이 있는 질의만 본다.** 이 결함은 「상한이 정렬 뒤에 걸려 무력해지는 것」이다. 상한이 없는
|
|
76
|
-
* 질의(재개 시 체크포인트 뒤를 전부
|
|
76
|
+
* 질의(재개 시 체크포인트 뒤를 전부 계산하는 경로)는 어차피 전부 읽어야 하므로 정렬 축을 바꿔도
|
|
77
77
|
* 얻는 것이 없다 — 그 자리를 붉히면 **거짓 빨강**이고, 그런 가드는 없는 것보다 나쁘다.
|
|
78
78
|
*/
|
|
79
79
|
if (!/\b(take|limit)\s*[:(]/.test(q)) continue
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* 배치로 옮기면 주기 사이에 멈출 때 그 구간이 사라진다 — **라이브도 이미 그랬다**(최대 200ms). 그래서
|
|
18
18
|
* 정지 때 남은 것을 흘리는 자리를 함께 만들었다. 상태만 남기고 저널을 잃으면 「왜 그렇게 됐나」가 빈다.
|
|
19
19
|
*
|
|
20
|
-
* 이 시험은 소스로 규율을 지킨다(DB 없이 도는 스위트다). 정량화는
|
|
20
|
+
* 이 시험은 소스로 규율을 지킨다(DB 없이 도는 스위트다). 정량화는 들어온 것이 없는 서버의 `journalRate` 가 답한다.
|
|
21
21
|
*/
|
|
22
22
|
import { test } from 'node:test'
|
|
23
23
|
import assert from 'node:assert/strict'
|
|
@@ -30,7 +30,7 @@ const engine = readFileSync(fileURLToPath(new URL('../server/engine/twin-engine.
|
|
|
30
30
|
* 메서드 본문만 — 다른 자리의 같은 낱말에 걸리지 않게.
|
|
31
31
|
*
|
|
32
32
|
* **다음 메서드 선언에서 끊는다.** 길이로 자르면 옆 메서드가 딸려 와, 「이 메서드가 몇 번 부르나」를
|
|
33
|
-
* 세는 단정이
|
|
33
|
+
* 세는 단정이 오류 없이 틀린 값을 낸다(실제로 그렇게 2를 세었다).
|
|
34
34
|
*/
|
|
35
35
|
function methodOf(src: string, name: string): string {
|
|
36
36
|
const at = src.indexOf(`${name}(`)
|
|
@@ -82,7 +82,7 @@ test('멈출 때 남은 것을 흘린다 — 성능을 사려고 사실을 팔
|
|
|
82
82
|
test('두 구동이 같은 계기를 든다 — 세지 않는 개선은 되돌려도 아무도 모른다', () => {
|
|
83
83
|
/*
|
|
84
84
|
* 계기(`inst.metrics`)가 `startLive` 에만 있었다. 그래서 도는 트윈 22개가 시뮬인 서버에서 「초당 몇 행을
|
|
85
|
-
* 쓰나」·「밀린 게 있나」를 물을 자리가 없었고, 모니터 목록에서도 시뮬이
|
|
85
|
+
* 쓰나」·「밀린 게 있나」를 물을 자리가 없었고, 모니터 목록에서도 시뮬이 알리지 않고 빠졌다(계기가 null 이라
|
|
86
86
|
* 걸러졌다) — 부하가 거의 없는 것처럼 보였다.
|
|
87
87
|
*/
|
|
88
88
|
assert.match(engine, /private static newMetrics\(\): TwinMetrics/, '계기 한 벌을 한 곳에서 만든다')
|
|
@@ -33,7 +33,7 @@ const T0 = 1_700_000_000_000
|
|
|
33
33
|
|
|
34
34
|
/* ── ① 유입 없이도 추이가 생긴다 ──────────────────────────────────────────── */
|
|
35
35
|
|
|
36
|
-
test('받는 것 없이 적기만 하는 트윈도 추이에 남는다 — 시뮬이
|
|
36
|
+
test('받는 것 없이 적기만 하는 트윈도 추이에 남는다 — 시뮬이 오류 없이 빠지지 않게', () => {
|
|
37
37
|
const l = newIngestLedger()
|
|
38
38
|
const closed: any[] = []
|
|
39
39
|
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
*
|
|
9
9
|
* 폴백이 둘 겹쳐 있었다. ①은 컬럼이 비었을 때, ②는 표에 없는 값일 때. 그리고 `kind` 는
|
|
10
10
|
* 검증 없는 자유 문자열이다(`@Arg('kind') kind: string` — enum 도 화이트리스트도 없다).
|
|
11
|
-
* 그래서 오타 하나·대소문자 하나로 **야드/생산 트윈이
|
|
11
|
+
* 그래서 오타 하나·대소문자 하나로 **야드/생산 트윈이 오류 없이 창고 커널로 돌았다.**
|
|
12
12
|
* 오류가 없으니 화면에는 트윈이 정상으로 보이고, 안에서 도는 규칙만 다른 도메인의 것이다.
|
|
13
13
|
* 예측 경로가 가장 나빴다 — 야드의 미래를 창고 규칙으로 굴려 놓고 숫자만 뜬다.
|
|
14
14
|
*
|
|
15
15
|
* ── 왜 검사로 남기나 ────────────────────────────────────────────────────────
|
|
16
16
|
* 자리를 고치는 것만으로는 부족하다. 커널 종류가 늘 때(다음은 TMS 든 무엇이든) 새 자리가
|
|
17
17
|
* 생기고, `?? WmsKernel` 은 "안전한 기본값" 처럼 보여서 다시 자란다. 실제로 세 자리에
|
|
18
|
-
* 똑같이 자라 있었다. 틀린 공장을
|
|
18
|
+
* 똑같이 자라 있었다. 틀린 공장을 알리지 않고 띄우는 것보다 뜨지 않는 편이 낫다.
|
|
19
19
|
*
|
|
20
20
|
* 이 검사가 막는 것은 **표를 밖에서 직접 색인하는 것**이다. 종류→커널 해소는 `kernelFor`
|
|
21
21
|
* 하나만 한다. 새 자리를 쓸 때 이 검사가 걸리면, 폴백을 붙이지 말고 `kernelFor` 를 부를 것.
|
|
@@ -59,7 +59,7 @@ test('종류→커널 해소는 kernelFor 한 곳만 한다', () => {
|
|
|
59
59
|
assert.deepEqual(indexing, [], 'KERNELS 를 밖에서 색인하고 있다 — kernelFor(kind) 를 쓸 것')
|
|
60
60
|
})
|
|
61
61
|
|
|
62
|
-
test('kernelFor 는 모르는 종류에 오류를 낸다 —
|
|
62
|
+
test('kernelFor 는 모르는 종류에 오류를 낸다 — 알리지 않고 고르지 않는다', () => {
|
|
63
63
|
const src = readFileSync(ENGINE, 'utf-8')
|
|
64
64
|
const fn = src.slice(src.indexOf('function kernelFor'))
|
|
65
65
|
assert.match(fn.slice(0, 300), /throw new Error/, 'kernelFor 가 오류를 내지 않으면 이 계약이 무너진다')
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ★ 여러 구간 동시 비교 — **실 DB로 배관을 넘어 본다.**
|
|
3
3
|
*
|
|
4
4
|
* 분포 산수는 `kpi-baseline.test.ts`(순수)가 지킨다. 여기서 지키는 것은 **호스트 배관**이다:
|
|
5
|
-
* 창을 하루씩 뒤로 옮겨 **각 창을 따로 읽는가** · 그 창을 같은 규칙으로
|
|
5
|
+
* 창을 하루씩 뒤로 옮겨 **각 창을 따로 읽는가** · 그 창을 같은 규칙으로 계산하는가 · 지표 값을 정본 표
|
|
6
6
|
* (`TWIN_METRIC`)로 꺼내는가 · 기록 없는 날을 결측으로 남기는가.
|
|
7
7
|
*
|
|
8
8
|
* 이 배관은 **경계를 넘어야만** 틀리는 것이 드러난다. 실제로 앱의 시뮬 트윈은 저널이 두 시간 남짓이라
|
|
@@ -99,7 +99,7 @@ before(async () => {
|
|
|
99
99
|
/*
|
|
100
100
|
* 지금 창 20건 · 어제 40건 · 그제 60건 · **3일 전은 기록 없음** · 4일 전 80건.
|
|
101
101
|
* 3일 전을 비워 두는 것이 이 스펙의 요점이다 — 그 날이 결측으로 남고 분포에서 빠지는지 본다
|
|
102
|
-
* (
|
|
102
|
+
* (알리지 않고 빼면 "지난 4일" 이 실제로는 3일이었다는 것을 아무도 모른다).
|
|
103
103
|
*/
|
|
104
104
|
const rows = [
|
|
105
105
|
...taskRows(0, 20, 30_000, 1000),
|