@things-factory/headless-twin 10.0.15 โ 10.0.18
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 +18 -82
- package/dist-server/engine/canonical-ingest.js +183 -18
- 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 +4 -4
- 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 +90 -10
- package/dist-server/engine/ingest-health.js +125 -16
- 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 +212 -14
- package/dist-server/engine/kpi-fold.js +374 -21
- 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 +281 -36
- 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 +15 -14
- 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 +3 -3
- package/dist-server/engine/model-vocabulary.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +6 -5
- package/dist-server/engine/oee-accumulator.js +6 -5
- 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 +307 -54
- package/dist-server/engine/twin-engine.js +822 -196
- 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 +30 -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 +116 -9
- 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 +76 -13
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +25 -16
- package/dist-server/service/reference/reference-master.js +35 -13
- 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 +12 -12
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/reference/template-registry.d.ts +1 -1
- package/dist-server/service/reference/template-registry.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-backfill/backfill-period-facts.d.ts +24 -0
- package/dist-server/service/twin-backfill/backfill-period-facts.js +96 -0
- package/dist-server/service/twin-backfill/backfill-period-facts.js.map +1 -0
- package/dist-server/service/twin-backfill/backfill-shape.d.ts +34 -0
- package/dist-server/service/twin-backfill/backfill-shape.js +75 -0
- package/dist-server/service/twin-backfill/backfill-shape.js.map +1 -0
- package/dist-server/service/twin-backfill/index.d.ts +2 -0
- package/dist-server/service/twin-backfill/index.js +6 -0
- package/dist-server/service/twin-backfill/index.js.map +1 -0
- package/dist-server/service/twin-backfill/twin-backfill-resolver.d.ts +10 -0
- package/dist-server/service/twin-backfill/twin-backfill-resolver.js +44 -0
- package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +1 -0
- package/dist-server/service/twin-control/twin-control-mutation.js +3 -3
- package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +1 -1
- package/dist-server/service/twin-event/twin-event-keys.js +2 -2
- 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/domain-catalog.js +2 -1
- package/dist-server/service/twin-lifecycle/domain-catalog.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 +34 -3
- 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 +12 -9
- package/dist-server/service/twin-model/isa95-coverage.js +33 -9
- 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 +2 -2
- 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 +7 -6
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +2 -2
- package/dist-server/service/twin-model/twin-equipment.js +3 -3
- 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 +15 -15
- 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 +51 -30
- package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js +23 -1
- 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 +37 -8
- 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 +4 -4
- 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 +7 -6
- package/server/engine/attention-digest.ts +9 -9
- package/server/engine/canonical-ingest.ts +202 -87
- package/server/engine/command-routing.ts +1 -1
- package/server/engine/declared-stimulus.ts +1 -1
- package/server/engine/energy-topology.ts +2 -2
- package/server/engine/ingest-dedupe.ts +149 -0
- package/server/engine/ingest-health.ts +171 -22
- package/server/engine/integration-probes.ts +7 -7
- package/server/engine/kpi-baseline.ts +4 -4
- package/server/engine/kpi-fold.ts +592 -41
- package/server/engine/kpi-query.ts +307 -48
- package/server/engine/live-feed-registry.ts +1 -1
- package/server/engine/load-meter.ts +1 -1
- package/server/engine/local-declarations.ts +15 -14
- 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 +2 -2
- package/server/engine/oee-accumulator.ts +8 -6
- 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 +906 -205
- 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 +73 -5
- package/server/service/index.ts +7 -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 +145 -10
- package/server/service/reference/reference-hook.ts +145 -0
- package/server/service/reference/reference-live.ts +87 -15
- package/server/service/reference/reference-master.ts +51 -20
- package/server/service/reference/reference-resolver.ts +11 -11
- package/server/service/reference/template-registry.ts +1 -1
- 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-backfill/backfill-period-facts.ts +168 -0
- package/server/service/twin-backfill/backfill-shape.ts +86 -0
- package/server/service/twin-backfill/index.ts +3 -0
- package/server/service/twin-backfill/twin-backfill-resolver.ts +35 -0
- package/server/service/twin-control/twin-control-mutation.ts +2 -2
- package/server/service/twin-event/twin-event-keys.ts +2 -2
- 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/domain-catalog.ts +2 -1
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +58 -4
- 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 +34 -3
- package/server/service/twin-model/iec61850-coverage.ts +1 -1
- package/server/service/twin-model/isa95-coverage.ts +43 -16
- package/server/service/twin-model/item-ref.ts +2 -2
- package/server/service/twin-model/name-index.ts +2 -2
- package/server/service/twin-model/project-structure.ts +7 -6
- package/server/service/twin-model/twin-equipment.ts +16 -4
- 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 +15 -15
- package/server/service/twin-model/twin-model-mutation.ts +4 -4
- package/server/service/twin-model/twin-model-query.ts +49 -28
- package/server/service/twin-model/twin-model-tree-query.ts +26 -2
- 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 +40 -8
- 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 +4 -4
- 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 +6 -5
- package/test/backfill-shape.test.ts +89 -0
- package/test/boot-resume.test.ts +20 -7
- package/test/broadcast-cost-baseline.test.ts +2 -1
- package/test/broadcast-period.test.ts +2 -2
- package/test/broadcast-queue-overflow.test.ts +244 -0
- package/test/canonical-ingest-vocabularies.test.ts +259 -8
- package/test/canonical-quantity-door.test.ts +2 -2
- package/test/capability-mapping.test.ts +1 -1
- package/test/checkpoint-refuses-empty.test.ts +2 -2
- package/test/connector-capability-declaration.test.ts +88 -0
- package/test/contract-layer-guard.test.ts +48 -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 +7 -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/equipment-identity-reaches.test.ts +57 -0
- 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/fact-scope-wiring.test.ts +96 -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/generated-not-counted.test.ts +99 -0
- package/test/ingest-bench.test.ts +2 -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/ingest-wiring-guard.test.ts +197 -0
- 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 +266 -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 +9 -6
- package/test/load-meter.test.ts +1 -1
- package/test/local-declarations.test.ts +13 -12
- package/test/log-stamp.test.ts +1 -1
- package/test/master-to-twin.test.ts +2 -2
- 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 +20 -5
- package/test/operational-vocabulary.test.ts +2 -2
- package/test/project-structure-db.test.ts +2 -2
- package/test/projection-reaches-screen.test.ts +7 -2
- package/test/projection-reads-declared.test.ts +109 -0
- package/test/property-effects.test.ts +10 -6
- 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/scale-twin-bench.test.ts +2 -1
- 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 +19 -21
- 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 +1 -1
- 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/vocabulary-guard.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 +2 -2
- package/test/yield-loop.test.ts +4 -4
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.TwinEngine = void 0;
|
|
12
12
|
const log_js_1 = require("./log.js");
|
|
13
|
+
const read_time_js_1 = require("./read-time.js");
|
|
13
14
|
const shell_1 = require("@things-factory/shell");
|
|
14
15
|
/* ์ ๋์ ์๋ฅผ ์กฐ๊ฑด์ SQL ์ด ์๋ค โ ๊ด์ฉ๊ตฌ๋ง ์ด๋ค(์์ SQL ์ 5๊ฐ ๋๋ผ์ด๋ฒ์์ ๊ฐ๋ผ์ง๋ค). */
|
|
15
16
|
const typeorm_1 = require("typeorm");
|
|
16
17
|
const cache_service_1 = require("@things-factory/cache-service");
|
|
17
18
|
const twin_event_js_1 = require("../service/twin-event/twin-event.js");
|
|
18
19
|
const twin_event_keys_js_1 = require("../service/twin-event/twin-event-keys.js");
|
|
20
|
+
const twin_subject_writer_js_1 = require("../service/twin-subject/twin-subject-writer.js");
|
|
21
|
+
const item_resolver_js_1 = require("../service/twin-subject/item-resolver.js");
|
|
19
22
|
const warm_start_js_1 = require("./warm-start.js");
|
|
20
23
|
const local_declarations_js_1 = require("./local-declarations.js");
|
|
21
24
|
const runtime_key_js_1 = require("./runtime-key.js");
|
|
@@ -50,9 +53,11 @@ const live_attentions_js_1 = require("./live-attentions.js");
|
|
|
50
53
|
const attention_digest_js_1 = require("./attention-digest.js");
|
|
51
54
|
const live_feed_registry_js_1 = require("./live-feed-registry.js");
|
|
52
55
|
const ingest_health_js_1 = require("./ingest-health.js");
|
|
53
|
-
const
|
|
56
|
+
const ingest_dedupe_js_1 = require("./ingest-dedupe.js");
|
|
57
|
+
const ops_contract_1 = require("@operato/ops-contract");
|
|
54
58
|
/* ์ปค๋ ๋ฐํ์ ๋ก๋ โ CJS ๋ฒ๋ค(dist-cjs). ํ์
์ ์ import type ๋ก. replay = ์ด๋ฒคํธ์ดโ์ํ ์ฌ๊ตฌ์ฑ(๋ณต๊ตฌยท์๊ฐ์ฌํ). */
|
|
55
|
-
const { WmsKernel, YmsKernel, MesKernel, EmsKernel, TwinRuntime, StateProjector, replay, replayFrom, replayWithCheckpoint, replaySegments
|
|
59
|
+
const { WmsKernel, YmsKernel, MesKernel, EmsKernel, TwinRuntime, StateProjector, replay, replayFrom, replayWithCheckpoint, replaySegments } = require('@operato/twin-kernel');
|
|
60
|
+
const { readBoardLocations, readBoardEquipment, DOMAIN_CATALOG, OP_EVENT, validateScenario } = require('@operato/ops-contract');
|
|
56
61
|
const KERNELS = { wms: WmsKernel, yms: YmsKernel, mes: MesKernel, ems: EmsKernel };
|
|
57
62
|
/**
|
|
58
63
|
* ์๊ฐ์ถ์ ๊ตฌํ ๋ ํ ๋ฒ์ ๋์ฐ๋ ํธ์ ์.
|
|
@@ -95,11 +100,11 @@ function parseTime(v) {
|
|
|
95
100
|
* ์ข
๋ฅ ๋ฌธ์์ด โ ์ปค๋. **๋ชจ๋ฅด๋ ๊ฐ์ด๋ฉด ์ค๋ฅ๋ฅผ ๋ธ๋ค.**
|
|
96
101
|
*
|
|
97
102
|
* ์์ ์๋ ํ๋ฅผ ์ฐพ๊ณ ์์ผ๋ฉด WmsKernel ๋ก ๋จ์ด์ก๋ค. `kind` ๋ ๊ฒ์ฆ ์๋ ์์ ๋ฌธ์์ด(`@Arg('kind') kind: string`)
|
|
98
|
-
* ์ด๋ผ ์คํ ํ๋ยท๋์๋ฌธ์ ํ๋๋ก ์ผ๋/์์ฐ ํธ์์ด
|
|
103
|
+
* ์ด๋ผ ์คํ ํ๋ยท๋์๋ฌธ์ ํ๋๋ก ์ผ๋/์์ฐ ํธ์์ด **์ค๋ฅ ์์ด ์ฐฝ๊ณ ์ปค๋๋ก ๋์๋ค.** ์ค๋ฅ๊ฐ ์์ผ๋ ํ๋ฉด์๋
|
|
99
104
|
* ํธ์์ด ์ ์์ผ๋ก ๋ณด์ด๊ณ , ์์์ ๋๋ ๊ท์น๋ง ๋ค๋ฅธ ๋๋ฉ์ธ์ ๊ฒ์ด๋ค. ์์ธก ๊ฒฝ๋ก๊ฐ ๊ฐ์ฅ ๋์๋ค โ
|
|
100
105
|
* ์ผ๋์ ๋ฏธ๋๋ฅผ ์ฐฝ๊ณ ๊ท์น์ผ๋ก ์คํํด ๋๊ณ ์ซ์๋ง ๋ฌ๋ค.
|
|
101
106
|
*
|
|
102
|
-
* ํ๋ฆฐ ๊ณต์ฅ์
|
|
107
|
+
* ํ๋ฆฐ ๊ณต์ฅ์ ์๋ฆฌ์ง ์๊ณ ๋์ฐ๋ ๊ฒ๋ณด๋ค ๋จ์ง ์๋ ํธ์ด ๋ซ๋ค.
|
|
103
108
|
*/
|
|
104
109
|
function kernelFor(kind) {
|
|
105
110
|
const K = KERNELS[kind];
|
|
@@ -113,16 +118,34 @@ let observeUnavailableWarned = false;
|
|
|
113
118
|
* **์ด ์ปค๋์ ์ง์ค์ด ์๋ณธ์์ ์จ๋ค๊ณ ์ ์ธํ๋ค** โ ๊ทธ๋ฆฌ๊ณ ์ ์ธ์ด ๋ฟ์ง ์์์ผ๋ฉด ๋งํ๋ค.
|
|
114
119
|
*
|
|
115
120
|
* โโ ๋ฌด์์ด ํ๋ ธ๋ (2026-08-21) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
116
|
-
* ์์ ์๋ `kernel.observe?.()` ์๋ค. ์ต์
๋ ํธ์ถ์ด๋ผ **๋ฉ์๋๊ฐ ์์ผ๋ฉด
|
|
121
|
+
* ์์ ์๋ `kernel.observe?.()` ์๋ค. ์ต์
๋ ํธ์ถ์ด๋ผ **๋ฉ์๋๊ฐ ์์ผ๋ฉด ์๋ฆฌ์ง ์๊ณ ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค.**
|
|
117
122
|
* ์ค์น๋ ์ปค๋ 0.7.39 ์๋ ๊ทธ ๋ฉ์๋๊ฐ ์์ผ๋ฏ๋ก, ์ง๊ธ ๋ฐฐํฌ๋ณธ์์๋ ๋ฏธ๋ฌ๊ฐ ๊ด์ธก ๊ตฌ๋์ผ๋ก ์ ์ธ๋์ง
|
|
118
123
|
* ์๋๋ค โ ๊ทธ๋ฐ๋ฐ ์ฝ๋๋ฅผ ์ฝ์ผ๋ฉด ์ ์ธํ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค.
|
|
119
124
|
*
|
|
120
125
|
* ๊ทธ ์ฐจ์ด๊ฐ ์ค์ ๊ฑฐ๋์ ๊ฐ๋ฅธ๋ค: ๊ด์ธก ๊ตฌ๋์ ์๋ณธ์ ๋นํ์ ๋ฐ์๋ค์ด๊ณ ์ธ์ง๋ง, ์๋ฎฌ๋ก ์ค์ธ๋ ๋ฏธ๋ฌ๋
|
|
121
|
-
* **๋ฉ์ถ๋ค.** ์ฆ ใ๊ด์ฉ์ด ์ผ์ง ์ค ์์๋๋ฐ ์ ์ผ์ ธ ์๋คใ๊ฐ
|
|
126
|
+
* **๋ฉ์ถ๋ค.** ์ฆ ใ๊ด์ฉ์ด ์ผ์ง ์ค ์์๋๋ฐ ์ ์ผ์ ธ ์๋คใ๊ฐ ์๋ฆฌ์ง ์๊ณ ์ง๋๊ฐ๊ณ , ์ฅ์ ๊ฐ ๋ฌ์ ๋ ์์ธ์ด
|
|
122
127
|
* ์ปค๋์ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค โ ์์ธ์ ๋ฒ์ ์ด๋ค.
|
|
123
128
|
*
|
|
124
129
|
* ๊ทธ๋์ ์ต์
๋ ํธ์ถ์ ์์ ๊ณ , ์์ผ๋ฉด **ํ ๋ฒ ๊ฒฝ๊ณ ํ๋ค.** ์ปค๋์ด ๋ฐฐํฌ๋๋ฉด ์ด ๊ฒฝ๊ณ ๋ ์ฌ๋ผ์ง๋ค.
|
|
125
130
|
*/
|
|
131
|
+
/**
|
|
132
|
+
* ์ ์ฅ๋ ๊ธฐ๋ก์ **๋๋ ๋์๊ณผ ๊ฐ์ ์ฝ๋๋ก** ์ฒ๋ฆฌํ๊ฒ ํ๋ค (2026-08-27).
|
|
133
|
+
*
|
|
134
|
+
* โโ ๋ฌด์์ด ํ๋ ธ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
135
|
+
* ๋๋ ๋์ ์ฌ๊ฑด์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋๋ฉ์ธ ์ปค๋์ด๋ค(`startLive` ๊ฐ `new Kernel(...)` ์ ์ธ์ด๋ค). ๊ทธ๋ฐ๋ฐ
|
|
136
|
+
* ์ ์ฅ๋ ๊ธฐ๋ก์ผ๋ก ๊ณผ๊ฑฐ ์์ ์ํ๋ฅผ ๋ง๋๋ ๊ฒฝ๋ก๋ ์ปค๋ ์ข
๋ฅ๋ฅผ ๋๊ธฐ์ง ์์์ ๋๋ฉ์ธ ๊ท์น ์์ด
|
|
137
|
+
* ์ฒ๋ฆฌํ๋ค. ๊ทธ ๊ฒฐ๊ณผ ใ์ด์ ์คํ 3์์ ์ด ๋ฐ์ ์๊ฐ ์ด๋ ๋ใ๋ฅผ ๋ฌผ์ผ๋ฉด ๋ฐ์ ๋๊ณผ ๊ณ๋์ด ๋ ๋น์ด ์์๋ค โ
|
|
138
|
+
* ๋ฐ์์ ์ ์ฅ๊น์ง ํด ๋ ๊ฐ์ธ๋ฐ ์ฝ๋ ์ชฝ์ด ๊ฑด๋๋ด ๊ฒ์ด๋ค.
|
|
139
|
+
*
|
|
140
|
+
* ์ข
๋ฅ๋ ๋ชจ๋ธ์ ์๋ค(๋ฑ๋ก๋ถ๊ฐ ๋ ๋ค). ๊ทธ๋์ ํธ์คํธ๊ฐ ๋งํด ์ค๋ค.
|
|
141
|
+
*/
|
|
142
|
+
function replayOptions(reg, domainId) {
|
|
143
|
+
return {
|
|
144
|
+
kind: reg?.kind,
|
|
145
|
+
productionSpec: reg?.model?.productionSpec,
|
|
146
|
+
tenantId: domainId
|
|
147
|
+
};
|
|
148
|
+
}
|
|
126
149
|
function declareObserved(kernel, what) {
|
|
127
150
|
if (typeof kernel?.observe === 'function') {
|
|
128
151
|
kernel.observe();
|
|
@@ -158,7 +181,7 @@ class TwinEngine {
|
|
|
158
181
|
*
|
|
159
182
|
* ํ์ ์ ์์ฐ(500ms)์ด ์๋๋ผ **๊ตถ๊น ๋ฌธํฑ**์ผ๋ก ๋ฐ๋ก ๋๋ค: ์กฐ๊ธ ๋๋ฆฐ ํธ์์ ๊ณ๊ธฐํ์ด ๋งํ๊ฒ ๋๊ณ
|
|
160
183
|
* (๊ฒฝ๊ณ ), ํธ์คํธ๋ฅผ ๊ตถ๊ธฐ๋ ํธ์๋ง ๋ฉ์ถ๋ค. ํ ๋ฒ์ผ๋ก ๋ฉ์ถ์ง ์๋๋ค โ ์์คํํธ ์งํ์ ์ฒซ ํฑ์ ์๋
|
|
161
|
-
* ๋ฌด๊ฒ๋ค(๋ณต๊ตฌํ ์ํ๋ฅผ ์ฒ์
|
|
184
|
+
* ๋ฌด๊ฒ๋ค(๋ณต๊ตฌํ ์ํ๋ฅผ ์ฒ์ ๊ณ์ฐํ๋ค). **์ฐ์**์ผ๋ก ์ด์ด์ง ๋๊ฐ ๊ตฌ์กฐ์ ์ผ๋ก ๋๋ฆฐ ๊ฒ์ด๋ค.
|
|
162
185
|
*/
|
|
163
186
|
/*
|
|
164
187
|
* โโ ํฑ์ **ํ ์๊ฐ์ ๋ชฐ์ง ์๋๋ค** (2026-08-21 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโ
|
|
@@ -176,7 +199,7 @@ class TwinEngine {
|
|
|
176
199
|
/**
|
|
177
200
|
* ํฉ์ด์ง ์ฒซ ๋ฐํ ๋ค ์ฃผ๊ธฐ ํฑ. **ํธ๋ค์ ํญ์ ์ง์ง ํ์ด๋จธ**๋ค โ ์ ์งํ๋ ์ชฝ์ด `clearInterval(inst.timer)`
|
|
178
201
|
* ํ๋๋ก ๋๋ด์ผ ํ๋ฏ๋ก, ์ฒซ ๋ฐํ ์ ์๋ ๊ทธ `setTimeout` ์, ์ดํ์๋ `setInterval` ์ ๊ฐ์ ์๋ฆฌ์ ๋๋ค
|
|
179
|
-
* (๊ฐ์ผ ๊ฐ์ฒด๋ฅผ ์ฃผ๋ฉด `clearInterval` ์ด ์๋ฌด ์ผ๋ ํ์ง ์๊ณ ํธ์์ด ๋ฉ์ถ์ง ์๋๋ค โ
|
|
202
|
+
* (๊ฐ์ผ ๊ฐ์ฒด๋ฅผ ์ฃผ๋ฉด `clearInterval` ์ด ์๋ฌด ์ผ๋ ํ์ง ์๊ณ ํธ์์ด ๋ฉ์ถ์ง ์๋๋ค โ ๋ค์ด์จ ๊ฒ์ด ์๋ ๊ฒฐํจ์ด ๋๋ค).
|
|
180
203
|
*/
|
|
181
204
|
static startTickTimer(fn, hold) {
|
|
182
205
|
const spread = Math.max(1, Math.round(this.TICK_MS / 20));
|
|
@@ -207,7 +230,7 @@ class TwinEngine {
|
|
|
207
230
|
* ์ ๋์ ๊ทธ๋๋ก ์ง์ค(์๊ฐ์ฌํ/history replay ๋ฌด๋ณ๊ฒฝ) โ ์บ์๋ display-only ์์คํํธ ์ต์ ํ. */
|
|
208
231
|
static { this.SNAPSHOT_CACHE_ID = 'twin-snapshot'; }
|
|
209
232
|
/*
|
|
210
|
-
* โโ ์ฌ๊ฐ์ **์ฌ์ฌ** โ ๊ณผ๊ฑฐ๋ฅผ ๋ฌผ์์ ๋ ๋ชฉํ ์ง์ ์์
|
|
233
|
+
* โโ ์ฌ๊ฐ์ **์ฌ์ฌ** โ ๊ณผ๊ฑฐ๋ฅผ ๋ฌผ์์ ๋ ๋ชฉํ ์ง์ ์์ ๊ณ์ฐ ์ํด (2026-08-18) โโ
|
|
211
234
|
*
|
|
212
235
|
* ์ต์ ์ฌ๊ฐ์ ํ๋๋ก๋ ์๊ฐ์ฌํ์ ๋์ธ ์ ์๋ค: ๊ทธ๊ฒ์ ์ธ์ ๋ ๋ชฉํ๋ณด๋ค **๋ค**์ ์๋ค. ๊ทธ๋์ ์ง์ ์
|
|
213
236
|
* ์ฌ๋ฌ ๊ฐ ๋จ๊ธด๋ค. ๋ค๋ง ๊ทธ๊ฒ๋ค์ ๊ฐ๊ฐ ์ํ ์ ์ฒด๋ฅผ ๋ค๊ณ ์์ด ๋ฌด๊ฒ๋ค โ ํ ํ์ ๋ชฐ์ ๋ฃ์ผ๋ฉด ๊ฑฐ๋ํ
|
|
@@ -215,13 +238,20 @@ class TwinEngine {
|
|
|
215
238
|
*
|
|
216
239
|
* ๊ฐ๊ฒฉ์ ๋ฆฌ๋น์ ๋๊ธ์ผ๋ก ์ก๋๋ค(`CHAIN_STRIDE`): ๋๊ธ์ ๋์ ๋๋ง ํ ์ง์ ์ ๋จ๊ธฐ๋ฏ๋ก, ์ ๋์ด ๋น ๋ฅด๊ฒ
|
|
217
240
|
* ์๋ผ๋ ํธ์์์๋ ์ง์ ์๊ฐ ํญ๋ฐํ์ง ์๋๋ค. ์ค๋๋ ๊ฒ๋ถํฐ ๋ฒ๋ฆฌ๊ณ ์ต๊ทผ `CHAIN_KEEP` ๊ฐ๋ง ๋ ๋ค โ
|
|
218
|
-
* ๊ณผ๊ฑฐ๋ก ๊น์ด ๊ฐ์๋ก ์ง์ ์ด ์์ด 0๋ถํฐ
|
|
241
|
+
* ๊ณผ๊ฑฐ๋ก ๊น์ด ๊ฐ์๋ก ์ง์ ์ด ์์ด 0๋ถํฐ ๊ณ์ฐํ๋ ๊ฒ์ **์๋ ค์ง ํ๊ณ**๋ค(๋ฌดํ ๋ณด๊ด๋ณด๋ค ์ ์งํ๋ค).
|
|
219
242
|
*/
|
|
220
243
|
static { this.CHAIN_CACHE_ID = 'twin-fold-chain'; }
|
|
221
244
|
static { this.CHAIN_INDEX_CACHE_ID = 'twin-fold-chain-index'; }
|
|
222
245
|
static { this.CHAIN_STRIDE = 5000; } // ๋ฆฌ๋น์ ๋๊ธ โ ์ด ๊ฐ๊ฒฉ์ ๋์ ๋๋ง ํ ์ง์ ์ ๋จ๊ธด๋ค
|
|
223
|
-
static { this.CHAIN_KEEP = 5; } // ์ต๊ทผ ๋ช ์ง์ ์ ๋ค๊ณ ์๋(๊ทธ๋ณด๋ค ๊ณผ๊ฑฐ๋ 0๋ถํฐ
|
|
246
|
+
static { this.CHAIN_KEEP = 5; } // ์ต๊ทผ ๋ช ์ง์ ์ ๋ค๊ณ ์๋(๊ทธ๋ณด๋ค ๊ณผ๊ฑฐ๋ 0๋ถํฐ ๊ณ์ฐํ๋ค)
|
|
224
247
|
static { this.SNAPSHOT_TTL_S = 7 * 24 * 3600; } // 7์ผ โ ์ ์ ๋ค์ดํ์ ์์กด, ๋ง๋ฃ ์ ์ ๋ replay ํด๋ฐฑ
|
|
248
|
+
/**
|
|
249
|
+
* ๋ฉ์ถ ํธ์์ ๋ง์ง๋ง ์ํ๋ฅผ ๋๋ ๊ธฐ๊ฐ โ ์ฌ์ค์ ๋ง๋ฃ ์์ (2026-08-27).
|
|
250
|
+
*
|
|
251
|
+
* ์บ์ ๊ณ์ธต์ ใ๋ง๋ฃ ์์ใ์ ๋ปํ๋ ๊ฐ์ด ์์ด์ ํฐ ์๋ฅผ ์ด๋ค(`ICacheService` ๋ ์ด ๋จ์ TTL ํ๋๋ง
|
|
252
|
+
* ๋ฐ๋๋ค). 100๋
์ด๋ฉด ์ด ์์คํ
์ ์๋ช
๋ณด๋ค ๊ธธ๋ค.
|
|
253
|
+
*/
|
|
254
|
+
static { this.SNAPSHOT_KEEP_S = 100 * 365 * 24 * 3600; }
|
|
225
255
|
static { this.CHECKPOINT_MS = 20000; } // ์ฒดํฌํฌ์ธํธ ์ฃผ๊ธฐ(ํซ ๋ธ๋ก๋์บ์คํธ ๊ฒฝ๋ก์ ๋ถ๋ฆฌ, O(state) ์ค๋กํ)
|
|
226
256
|
/**
|
|
227
257
|
* **์ ๋ ๋ณด์กด โ ์ง์ฐ๋ ๊ฒ์ ์ ์ธ์ด ์์ ๋๋ง ํ๋ค.**
|
|
@@ -234,28 +264,39 @@ class TwinEngine {
|
|
|
234
264
|
* โโ ๊ทธ๋ฐ๋ฐ ์ ๋์ ์ง์ฐ๋ ๊ฒ์ ์ฌ์ค์ ์๋ ์ผ์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
235
265
|
* ๊ทธ๋์ ์ธ ๊ท์จ์ ์งํจ๋ค.
|
|
236
266
|
*
|
|
237
|
-
* โ **์ ์ธ์ด ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ์ง์ฐ์ง ์๋๋ค.** ๊ธฐ๋ณธ๊ฐ์ ์์์ด๋ค โ
|
|
267
|
+
* โ **์ ์ธ์ด ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ์ง์ฐ์ง ์๋๋ค.** ๊ธฐ๋ณธ๊ฐ์ ์์์ด๋ค โ ์๋ฆฌ์ง ์๊ณ ์ง์ฐ๋ ํธ์ด ์๋ฆฌ์ง ์๊ณ ์๋
|
|
238
268
|
* ๊ฒ๋ณด๋ค ๋์๋ค. ์ง์ฐ๋ ๊ฒ์ ์ฌ๋์ด ์ ํ๋ค.
|
|
239
269
|
* โก **์ฒดํฌํฌ์ธํธ๊ฐ ๋์ ํ ์ ์๋ ๋งํผ๋ง.** ์ค๋
์ท์ด ์๊ฑฐ๋ ๊ทธ ๋ฆฌ๋น์ ์ ๋๋ ์๋ฆฌ๋ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
|
|
240
270
|
* ์ฃผ์์ด ใ๋ง๋ฃ ์ ์ ๋ replay ํด๋ฐฑใ์ด๋ผ๊ณ ์ ์ด ๋ ๊ทธ๋๋ก โ ์ค๋
์ท์ด ์ฌ๋ผ์ง๋ฉด ์ ๋์ด **์ ์ผํ**
|
|
241
271
|
* ๋ณต๊ตฌ ์๋จ์ด๋ฏ๋ก, ๋์ ํจ๊ป ์์ผ๋ฉด ๊ทธ ํธ์์ ์ํ๋ ๋๋๋ฆด ์ ์๋ค.
|
|
242
|
-
* โข **์ง์ด ๊ฒ์ ๋งํ๋ค.** ๋ช ๊ฑด์ ์ด๋ ์๊ฐ๊น์ง ์ง์ ๋์ง ๋ก๊ทธ์ ๋จ๊ธด๋ค.
|
|
272
|
+
* โข **์ง์ด ๊ฒ์ ๋งํ๋ค.** ๋ช ๊ฑด์ ์ด๋ ์๊ฐ๊น์ง ์ง์ ๋์ง ๋ก๊ทธ์ ๋จ๊ธด๋ค. ์๋ฆฌ์ง ์๊ณ ์ค์ด๋ ์ ๋์
|
|
243
273
|
* ใ์์๋ ์ผใ๊ณผ ๊ตฌ๋ณ๋์ง ์๋๋ค.
|
|
244
274
|
*
|
|
245
275
|
* ๊ทธ๋ฆฌ๊ณ ๋ณด์กด ๊ธฐ๊ฐ์ **์ค๋
์ท TTL(7์ผ)๋ณด๋ค ์งง์ ์ ์๋ค.** ๋ ์งง์ผ๋ฉด ์ค๋
์ท์ด ์ด์ ์๋๋ฐ ๊ทธ๊ฒ์ด
|
|
246
|
-
* ๊ฐ๋ฆฌํค๋ ์์ชฝ ์ ๋์ด ์๋ ๊ตฌ๊ฐ์ด ์๊ธฐ๊ณ , ์๊ฐ์ฌํยท๊ณ๋ณด ์ถ์ ์ด ๊ทธ ๊ตฌ๊ฐ์์
|
|
276
|
+
* ๊ฐ๋ฆฌํค๋ ์์ชฝ ์ ๋์ด ์๋ ๊ตฌ๊ฐ์ด ์๊ธฐ๊ณ , ์๊ฐ์ฌํยท๊ณ๋ณด ์ถ์ ์ด ๊ทธ ๊ตฌ๊ฐ์์ ์๋ฆฌ์ง ์๊ณ ๋น๋ค.
|
|
247
277
|
*/
|
|
248
278
|
static { this.JOURNAL_RETENTION_DAYS = undefined; }
|
|
249
279
|
static { this.RETENTION_SWEEP_MS = 10 * 60 * 1000; } // 10๋ถ๋ง๋ค ํ ๋ฒ โ ์ง์ฐ๋ ์ผ์ ๊ธํ์ง ์๋ค
|
|
250
280
|
/** ์ต์ ์ค๋
์ท์ cache-service ์ ์ฒดํฌํฌ์ธํธ(๋๋ฉ์ธ+instanceId ํค). display-onlyยท๋น์ฐจ๋จยท์ค๋ฅํก์. */
|
|
251
|
-
static async persistSnapshot(domainId, instanceId
|
|
281
|
+
static async persistSnapshot(domainId, instanceId,
|
|
282
|
+
/**
|
|
283
|
+
* ๋ง๋ฃ๋ฅผ ๋์ง ์๋๋ค โ **ํธ์์ ๋ฉ์ถ ๋๋ง** ์ฐธ์ด๋ค (2026-08-27).
|
|
284
|
+
*
|
|
285
|
+
* ๋๋ ํธ์์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ค์ ์ฐ๋ฏ๋ก 7์ผ ๋ง๋ฃ๊ฐ ๊ฑธ๋ฆฌ์ง ์๋๋ค. ๋ฉ์ถ ํธ์์ ์๋ฌด๋ ์ฐ์ง ์์์
|
|
286
|
+
* 7์ผ ๋ค ๋ง๋ฃ๋๊ณ , ๊ทธ๋ฌ๋ฉด ๊ทธ ํธ์์ ๋ง์ง๋ง ์ํ๋ฅผ ์๋ ๊ฒ์ด ์๋ฌด๊ฒ๋ ์๋ค. ๋ฉ์ถ๋ ์๊ฐ์ด ๊ทธ
|
|
287
|
+
* ์ํ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ง์ง๋ง ์๊ฐ์ด๋ฏ๋ก ๊ทธ๋ ๋ง๋ฃ ์์ด ์ ๋๋ค.
|
|
288
|
+
*
|
|
289
|
+
* ๋ง๋ฃ๋ ๋ค์๋ ๊ทธ ํธ์์ ๋ณด๊ด๋ ๊ตฌ๊ฐ์์ ๋ค์ ์ธ์์ง๋ค(๋ณด๊ด ๊ธฐ๊ฐ๋งํผ์ด๋ฏ๋ก ์ ํํ๋ค). ๋ค๋ง ๊ทธ
|
|
290
|
+
* ๊ตฌ๊ฐ ์์ ์ํ๋ ์ ์ ์๋ค. ๋ฉ์ถ๋ ์๊ฐ์ ์ ์ด ๋๋ฉด ๊ทธ ์์ค์ด ์๋ค.
|
|
291
|
+
*/
|
|
292
|
+
keepForever = false) {
|
|
252
293
|
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
253
294
|
if (!inst)
|
|
254
295
|
return;
|
|
255
296
|
/*
|
|
256
297
|
* **๋ดํฌ๊ฐ ์๋๋ผ ์ํ๋ฅผ ์ ์ฅํ๋ค.** `snapshot()` ์ ์๋ฎฌ์์ `runtime.resync()` ๋ดํฌ๋ฅผ ์ฃผ๋๋ฐ,
|
|
257
298
|
* ๊ทธ๊ฒ์ ๋ค์ `{revision, state}` ๋ก ๊ฐ์ธ ๋ฃ์ด ์๋ค โ ๊บผ๋ธ ๊ฐ์ ์ถ์ด ํ๋๋ ์์ด ์์คํํธ๊ฐ
|
|
258
|
-
*
|
|
299
|
+
* ์๋ฆฌ์ง ์๊ณ ๋์ด๊ฐ๋ค(์ ๋์ ์์ฒ ๊ฑด์ด ์์ด๋ ํธ์์ด ๋น ์ฑ๋ก ๋ด๋ค).
|
|
259
300
|
*/
|
|
260
301
|
const state = (0, warm_start_js_1.unwrapState)(this.snapshot(domainId, instanceId));
|
|
261
302
|
if (!state)
|
|
@@ -278,7 +319,7 @@ class TwinEngine {
|
|
|
278
319
|
*
|
|
279
320
|
* ์๋ณธ์ด ์ค์ ๋ก ใ๋ค ๋น์๋คใ๊ณ ๋งํ ๊ฒฝ์ฐ๋ ๋ง์ง ์๋๋ค โ ๊ทธ๋๋ ์ ์
์ด ์์์ผ๋ฏ๋ก ์ด ๋ฌธ์ ์ง๋๋ค.
|
|
280
321
|
*
|
|
281
|
-
* ๊ทธ๋ฆฌ๊ณ **๊ฑฐ์ ์ ๋งํ๋ค**:
|
|
322
|
+
* ๊ทธ๋ฆฌ๊ณ **๊ฑฐ์ ์ ๋งํ๋ค**: ์๋ฆฌ์ง ์๊ณ ๊ฑฐ์ ํ๋ฉด ์ ์ฒดํฌํฌ์ธํธ๊ฐ ๋ก์ ๊ฐ๋์ง ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.
|
|
282
323
|
*/
|
|
283
324
|
if (!(inst.metrics?.ingestedTotal > 0)) {
|
|
284
325
|
const observed = (s) => (s?.items?.length ?? 0) + (s?.orders?.length ?? 0) + (s?.tasks?.length ?? 0);
|
|
@@ -297,52 +338,52 @@ class TwinEngine {
|
|
|
297
338
|
/* ๊ตฌ์กฐ ๋ฆฌ๋น์ ๋ ํจ๊ป โ ์ฝ๋ ์ชฝ์ด "์ด ์ํ๊ฐ ์ง๊ธ์ ๊ณต์ฅ์ธ๊ฐ" ๋ฅผ ๊ฐ๋ฆด ์ ์์ด์ผ ํ๋ค. */
|
|
298
339
|
const { structureRev } = await this.tipOf(domainId, instanceId).catch(() => ({ structureRev: null }));
|
|
299
340
|
/*
|
|
300
|
-
* โโ **์ด์ด
|
|
341
|
+
* โโ **์ด์ด ๊ณ์ฐํ ์จ์์ ํจ๊ป ์ ๋๋ค** (2026-08-24) โโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
301
342
|
*
|
|
302
343
|
* ์ด ํจ์๋ ์ค๋ซ๋์ `{revision, state, structureRev}` ๋ง ์ ์๋ค. ๊ทธ๋์ **์ฌ๊ฐ์ ์ ์ฝ๋ ์ชฝ์ ๋ค
|
|
303
|
-
* ์๋๋ฐ ์ฐ๋ ์ชฝ์ด ์์๋ค**: ์กฐํ ๊ฒฝ๋ก(`recover`)๋ `fold` ๊ฐ ์์ผ๋ฉด ๊ผฌ๋ฆฌ๋ง
|
|
304
|
-
* 0๋ถํฐ
|
|
305
|
-
* ๊ทธ๋์ ์ฌ๊ธฐ๋ยท์กฐํ๋ง๋ค ์ฒ์๋ถํฐ ๋ค์
|
|
344
|
+
* ์๋๋ฐ ์ฐ๋ ์ชฝ์ด ์์๋ค**: ์กฐํ ๊ฒฝ๋ก(`recover`)๋ `fold` ๊ฐ ์์ผ๋ฉด ๊ผฌ๋ฆฌ๋ง ๊ณ์ฐํ๊ณ , ์์ผ๋ฉด ์ ๋์
|
|
345
|
+
* 0๋ถํฐ ๊ณ์ฐํ๋ค. ์ค์ธก์ผ๋ก ์ ์ฅ๋ ์ค๋
์ท 34๊ฑด ์ ๋ถ `fold` ๊ฐ ๋น์ด ์์๊ณ , ์ ๋์ 2,960๋ง ์ค์ด์๋ค โ
|
|
346
|
+
* ๊ทธ๋์ ์ฌ๊ธฐ๋ยท์กฐํ๋ง๋ค ์ฒ์๋ถํฐ ๋ค์ ๊ณ์ฐํ๋ค. ๊ท๋ชจ ๊ธฐ์ค(์ํฐํฐ 10๋งยทํ๋ชฉ 100๋ง)์์ ์ด๊ฒ์
|
|
306
347
|
* ๋๋ฆฐ ๊ฒ์ด ์๋๋ผ **๋ชป ํ๋ ๊ฒ**์ด๋ค.
|
|
307
348
|
*
|
|
308
349
|
* ์จ์์ ์ํ๊ฐ ๋์ ํ ์ ์๋ค: ๋ฆฌ๋์๋ ์๋น์ฒ๊ฐ ๋ณด๋ ๊ฐ ๋ง๊ณ ๋ ๋ ๋ค(๋ถ๋ชจ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ด๊นยท์ง๊ณ
|
|
309
|
-
* ์ค์ธ ์๋ยท๋ด์ ์ค ๋ชฐ๋ผ ์ธ์ด ๋ ์ฌ๊ฑด). ์ํ๋ง ๋๋๋ฆฌ๊ณ ๋ค๋ฅผ
|
|
350
|
+
* ์ค์ธ ์๋ยท๋ด์ ์ค ๋ชฐ๋ผ ์ธ์ด ๋ ์ฌ๊ฑด). ์ํ๋ง ๋๋๋ฆฌ๊ณ ๋ค๋ฅผ ๊ณ์ฐํ๋ฉด 0๋ถํฐ ๊ณ์ฐํ ๊ฒฐ๊ณผ์ **์๋ฆฌ์ง ์๊ณ **
|
|
310
351
|
* ๋ฌ๋ผ์ง๋ค. ๊ทธ ๋์น๋ ์ปค๋ ์ํ์ด ์ฆ๋ช
ํ๋ค(`observed-checkpoint.test.ts`).
|
|
311
352
|
*
|
|
312
353
|
* ๊ด์ธก ๊ตฌ๋์ด ์๋๋ฉด ์จ์์ด ์๋ค โ ์๋ฎฌ์ ๋ฆฌ๋์๋ฅผ ๊ฐ์ง ์๊ณ , ๊ทธ ์ํ์ ๊ถ์๋ ์ปค๋ ์์ ์ด๋ค.
|
|
313
|
-
* ๊ทธ๋๋ `fold` ๋ฅผ **๋ฃ์ง ์๋๋ค**(๋น ์จ์์ ๋ฃ์ผ๋ฉด ์ฝ๋ ์ชฝ์ด ใ์ด์ด
|
|
354
|
+
* ๊ทธ๋๋ `fold` ๋ฅผ **๋ฃ์ง ์๋๋ค**(๋น ์จ์์ ๋ฃ์ผ๋ฉด ์ฝ๋ ์ชฝ์ด ใ์ด์ด ๊ณ์ฐํ ์ ์๋คใ๊ณ ์๋ชป ๋ณธ๋ค).
|
|
314
355
|
*/
|
|
315
356
|
const reducer = inst.kernel?.observedCheckpoint?.();
|
|
316
357
|
const fold = reducer && inst.oee ? { reducer, oee: inst.oee.serialize() } : undefined;
|
|
317
|
-
await cache_service_1.cacheService.setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, { revision, state, structureRev, ...(fold ? { fold } : {}) }, this.SNAPSHOT_TTL_S);
|
|
358
|
+
await cache_service_1.cacheService.setInCache(this.SNAPSHOT_CACHE_ID, { domainId, instanceId }, { revision, state, structureRev, ...(fold ? { fold } : {}) }, keepForever ? this.SNAPSHOT_KEEP_S : this.SNAPSHOT_TTL_S);
|
|
318
359
|
}
|
|
319
360
|
/**
|
|
320
|
-
*
|
|
361
|
+
* ๊ณ์ฐ์ **์ฌ๊ฐ์ ** โ ๋ฆฌ๋์ ๋ด๋ถ ์ํ ์ ๋ถ + ๊ฐ๋ ๋์ ๊ธฐ.
|
|
321
362
|
*
|
|
322
|
-
* ์ค๋
์ท(`state`)์ ์๋น์ฒ๊ฐ ๋ณด๋ ๊ฐ์ด๋ผ ์ด์ด
|
|
323
|
-
* ์ฌ๊ฑด ์ง๊ณ๊ฐ ์๋ค โ ๊ทธ ์ํ๋ก ๋ค๋ฅผ
|
|
363
|
+
* ์ค๋
์ท(`state`)์ ์๋น์ฒ๊ฐ ๋ณด๋ ๊ฐ์ด๋ผ ์ด์ด ๊ณ์ฐ์ ์จ์์ด ๋์ง ๋ชปํ๋ค(๋ณด๋ฅ๋ ๋ด๊นยท์งํฉยท๋ฐ์ ๋ชป ํ
|
|
364
|
+
* ์ฌ๊ฑด ์ง๊ณ๊ฐ ์๋ค โ ๊ทธ ์ํ๋ก ๋ค๋ฅผ ๊ณ์ฐํ๋ฉด 0๋ถํฐ ๊ณ์ฐํ ๊ฒฐ๊ณผ์ ์ค๋ฅ ์์ด ๋ฌ๋ผ์ง๋ค). ๊ทธ๋์ ์จ์์ ๋ฐ๋ก ๋ ๋ค.
|
|
324
365
|
*/
|
|
325
366
|
static { this.FOLD_NOTE = 'reducer + oee checkpoint โ the seed for folding only the tail'; }
|
|
326
367
|
/**
|
|
327
|
-
* ์ฌ๊ธฐ๋์ ์ธ **์์คํํธ ์จ์**์ ๋ง๋ ๋ค โ ์ํ + ์ด์ด
|
|
368
|
+
* ์ฌ๊ธฐ๋์ ์ธ **์์คํํธ ์จ์**์ ๋ง๋ ๋ค โ ์ํ + ์ด์ด ๊ณ์ฐํ ์ฌ๊ฐ์ .
|
|
328
369
|
*
|
|
329
370
|
* โโ ์ ์ด ์๋ฆฌ๊ฐ ์๊ฒผ๋ (2026-08-24) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
330
371
|
* ๋ ํธ์ถ๋ถ๊ฐ ๊ฐ์ ์ผ์ ์กฐ๊ธ์ฉ ๋ค๋ฅด๊ฒ ํ๊ณ ์์๊ณ (๊ฒนํฌ์ฅ์ ํ์ชฝ๋ง ๋ฒ๊ฒผ๋ค), ๋ ๋ค **์ฌ๊ฐ์ ์ ๋ฒ๋ฆฌ๊ณ **
|
|
331
372
|
* ์ํ๋ง ๋ค๊ณ ๊ฐ๋ค. ๊ทธ๋์ ์ ์ฅ๋ ์ฌ๊ฐ์ ์ ์ฝ๋ ์ชฝ์ด ๋ค ์๋๋ฐ๋ ์ฌ๊ธฐ๋์ ๋งค๋ฒ ์ ๋์ ์ฒ์๋ถํฐ
|
|
332
|
-
*
|
|
373
|
+
* ๊ณ์ฐํ๋ค(์ค์ธก: ์ ๋ 2,960๋ง ์ค).
|
|
333
374
|
*
|
|
334
375
|
* ์ฌ๊ธฐ์ ํ๋ ์ผ ์
:
|
|
335
376
|
* โ ๊ฒนํฌ์ฅ์ ๋ฒ๊ธด๋ค โ ์ ํ์์ผ๋ก ์ ์ฅ๋ ๊ฐ์ด ํ ๋ฒ์ ๋ฐ๋์ ๋์จ๋ค
|
|
336
377
|
* โก **๊ทธ ๊ณต์ฅ์ด ์์ง ๊ทธ ๊ณต์ฅ์ธ์ง** ์ฌํํ๋ค โ ์๋๋ฉด ์จ์์ ๋ฒ๋ฆฐ๋ค(์๋)
|
|
337
|
-
* โข ์จ์์ด ์ ๋ ๋๋ณด๋ค ์์ ์์ผ๋ฉด **๊ทธ ๊ผฌ๋ฆฌ๋ง
|
|
378
|
+
* โข ์จ์์ด ์ ๋ ๋๋ณด๋ค ์์ ์์ผ๋ฉด **๊ทธ ๊ผฌ๋ฆฌ๋ง ๊ณ์ฐํด** ๋๊น์ง ๋ฐ์ด ๋๋ค
|
|
338
379
|
*
|
|
339
380
|
* โก๊ฐ ํ์ํ ์ด์ : ์ฌ๊ฐ์ ์ ๊ทธ๋์ ๋ณด๋ ์์์ ๋ง๋ค์ด์ง ๊ฒ์ด๋ค. ๊ทธ ๋ค ๊ตฌ์กฐ๊ฐ ๋ฐ๋์๋ค๋ฉด(์๋ฆฌ๊ฐ
|
|
340
381
|
* ๋น ์ก๋คยท์ค๋น๊ฐ ์ฎ๊ฒจ์ก๋ค) ๋์ธ์ด ๋ฆฌ๋์๋ **์ง๊ธ ์๋ ์๋ฆฌ์ ์ค๋น๋ฅผ ๋ ๋ค** โ ์๋ ๋์ฅ์ค์ด ํ๋ฉด์
|
|
341
382
|
* ๋์ค๊ณ ๊ทธ ์๋ฆฌ์ ํ์ ์ด ๊ณ์ ๋์๊ฐ๋ค. ์ค๋ฅ ์์ด ํ๋ฆฌ๋ฏ๋ก ๋์ ๋์ง ์๋๋ค.
|
|
342
383
|
*
|
|
343
384
|
* โข์ด ํ์ํ ์ด์ : ์ค๋
์ท์ ์ฒดํฌํฌ์ธํธ ์ฃผ๊ธฐ๋ก ์ฐ์ด๋ฏ๋ก ๋ง์ง๋ง ์ฃผ๊ธฐ ์ดํ์ ์ฌ์ค์ ์ ๋์๋ง ์๋ค.
|
|
344
|
-
* ๊ทธ๊ฒ์ ๋นผ๊ณ ๋์ธ์ฐ๋ฉด ๊ทธ๋งํผ์ด
|
|
345
|
-
*
|
|
385
|
+
* ๊ทธ๊ฒ์ ๋นผ๊ณ ๋์ธ์ฐ๋ฉด ๊ทธ๋งํผ์ด ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋ค โ ใ๋ชจ๋ฆใ์ ใ์์ใ์ผ๋ก ์ ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ถ๋ฅ๋ค.
|
|
386
|
+
* ๊ณ์ฐํ๋ ๊ตฌ๊ฐ์ **๊ทธ ํ๋ฟ**์ด๊ณ (์ ๋ ์ ์ฒด๊ฐ ์๋๋ค), `recover` ๊ฐ ๊ทธ ์๋ฆฌ์์ ์ ์ฌ๊ฐ์ ์ ๋จ๊ฒจ ์ค๋ค.
|
|
346
387
|
*/
|
|
347
388
|
static async warmSeedFor(domainId, instanceId) {
|
|
348
389
|
let cached = await this.loadSnapshot(domainId, instanceId).catch(() => null);
|
|
@@ -357,18 +398,43 @@ class TwinEngine {
|
|
|
357
398
|
`at ${tip.structureRev} โ starting without it (the journal is folded from the beginning instead).`);
|
|
358
399
|
return { revision: cached.revision, state: (0, warm_start_js_1.unwrapState)(cached.state) };
|
|
359
400
|
}
|
|
360
|
-
|
|
401
|
+
/*
|
|
402
|
+
* โโ **๋ฌป์ง ๋ชปํ์ผ๋ฉด ๊ทธ ์ฌ์ค์ ๋งํ๋ค** (2026-08-28) โโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
403
|
+
*
|
|
404
|
+
* ์ฌ๊ธฐ๊ฐ `if (tip && โฆ)` ์ด์๋ค. ์์์ `tipOf` ๊ฐ ์คํจํ๋ฉด `null` ์ด ๋๊ณ , ๊ทธ๋ฌ๋ฉด ์ด ๊ฐ๋๊ฐ
|
|
405
|
+
* **์๋ฌด ๋ง ์์ด ๊ฑด๋๋ด๋ค** โ ์ ์ฅ๋ณธ ๋ค์ ์ฌ๊ฑด์ ๋ฐ์ํ์ง ๋ชปํ ์ฑ ๋จ๊ณ , ๋ก๊ทธ์ ์๋ฌด ํ์ ์ด ์๋ค.
|
|
406
|
+
* ์ค์ธก(2026-08-28 10:34): ์ ์ฅ๋ณธ 3,372,228 ยท ์ ๋ ๋จธ๋ฆฌ 3,374,894 ์ธ๋ฐ ๊ณ์ฐํ๋ค๋ ์ค๋, ๋ชป ํ๋ค๋
|
|
407
|
+
* ์ค๋ ์์๋ค.
|
|
408
|
+
*/
|
|
409
|
+
if (!tip) {
|
|
410
|
+
(0, log_js_1.twinWarn)(`[twin-engine] "${instanceId}": could not read the journal tip โ starting from the stored seed at revision ` +
|
|
411
|
+
`${cached.revision ?? 0} without folding what came after it. Some recent facts may be missing from state.`);
|
|
412
|
+
return { revision: cached.revision, ...seedOf(cached), state: (0, warm_start_js_1.unwrapState)(cached.state) };
|
|
413
|
+
}
|
|
414
|
+
if ((cached.revision ?? 0) < tip.revision) {
|
|
361
415
|
/*
|
|
362
|
-
* ํ์
|
|
416
|
+
* ํ์ ๊ณ์ฐํ๋ค โ `recover` ๊ฐ ์ด ์จ์์ผ๋ก **๊ผฌ๋ฆฌ๋ง** ๊ณ์ฐํ๊ณ , ๋ ์ง์ ์ ์ ์ฌ๊ฐ์ ์ ๋จ๊ธด๋ค.
|
|
363
417
|
* ์์ง ์ด ํธ์์ ๋ฐํ์์ด ์์ผ๋ฏ๋ก `recover` ๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ์ ๋ ๊ฒฝ๋ก๋ฅผ ํ๋ค(๊ทธ๊ฒ์ด ์ฌ๊ธฐ์ ์ ์ ๋ค).
|
|
364
418
|
*/
|
|
365
419
|
const gap = tip.revision - (cached.revision ?? 0);
|
|
366
|
-
|
|
420
|
+
let failed;
|
|
421
|
+
await this.recover(domainId, instanceId).catch(err => {
|
|
422
|
+
failed = err?.message ?? String(err);
|
|
423
|
+
(0, log_js_1.twinWarn)(`[twin-engine] "${instanceId}": could not fold the ${gap} event(s) after the checkpoint โ ${failed}`);
|
|
424
|
+
});
|
|
367
425
|
const advanced = await this.loadSnapshot(domainId, instanceId).catch(() => null);
|
|
368
426
|
if (advanced?.state && (advanced.revision ?? 0) > (cached.revision ?? 0)) {
|
|
369
427
|
(0, log_js_1.twinLog)(`[twin-engine] "${instanceId}": folded ${gap} event(s) after the checkpoint โ revision ${advanced.revision}.`);
|
|
370
428
|
cached = advanced;
|
|
371
429
|
}
|
|
430
|
+
else if (!failed) {
|
|
431
|
+
/*
|
|
432
|
+
* **์๋ฌด ์ผ๋ ํ์ง ์์ ๊ฒ์ ๋งํ๋ค.** ๊ณ์ฐ์ด ์ค๋ฅ ์์ด ๋๋ฌ๋๋ฐ ์ฌ๊ฐ์ ์ด ๋์๊ฐ์ง ์์๋ค๋ ๋ป์ด๊ณ ,
|
|
433
|
+
* ๊ทธ๋ฌ๋ฉด ๊ทธ ์ฌ๊ฑด๋ค์ ๊ฒฐ๊ณผ๊ฐ ์ํ์ ์๋ค. ์์ ์๋ ์ด ๊ฐ๋๊ฐ ์กฐ๊ฑด์ ๊ฑธ๋ฆฌ์ง ์์ ์นจ๋ฌตํ๋ค.
|
|
434
|
+
*/
|
|
435
|
+
(0, log_js_1.twinWarn)(`[twin-engine] "${instanceId}": folding the ${gap} event(s) after the checkpoint left the seed at revision ` +
|
|
436
|
+
`${cached.revision ?? 0} โ state starts without those facts. The screens may show them as absent.`);
|
|
437
|
+
}
|
|
372
438
|
}
|
|
373
439
|
return { revision: cached.revision, state: (0, warm_start_js_1.unwrapState)(cached.state), ...seedOf(cached) };
|
|
374
440
|
}
|
|
@@ -378,10 +444,10 @@ class TwinEngine {
|
|
|
378
444
|
return entry?.value ?? null;
|
|
379
445
|
}
|
|
380
446
|
/**
|
|
381
|
-
*
|
|
447
|
+
* ๊ณ์ฐํ ์ํ๋ฅผ ์ค๋
์ท์ผ๋ก ๋จ๊ธด๋ค โ **๋ผ์ด๋ธ๊ฐ ์๋์ด๋.**
|
|
382
448
|
*
|
|
383
449
|
* `persistSnapshot` ์ ๊ธฐ๋ ์ค์ธ ์ธ์คํด์ค์์๋ง ๋ฌ๋ค(๋ฉ๋ชจ๋ฆฌ๊ฐ ์ง์ค์ด๋ฏ๋ก ์ณ๋ค). ๊ทธ๋ฐ๋ฐ **๋ฉ์ถ**
|
|
384
|
-
* ํธ์์ ์กฐํํ ๋๋ง๋ค ์ ๋์ ์ ๋ ๋ค์
|
|
450
|
+
* ํธ์์ ์กฐํํ ๋๋ง๋ค ์ ๋์ ์ ๋ ๋ค์ ๊ณ์ฐํ๊ณ ์์๋ค(23,731๊ฑด์ง๋ฆฌ ํธ์์์ 4.6์ด). ๊ทธ ํด๋์ ๊ฒฐ๊ณผ๋ฅผ
|
|
385
451
|
* ๋จ๊ฒจ ๋๋ฉด **์ฒ์ ํ ๋ฒ๋ง ๋๋ฆฌ๋ค.**
|
|
386
452
|
*
|
|
387
453
|
* `structureRev` ๋ฅผ ํจ๊ป ์ ๋๋ค: ์ด๋ฒคํธ๊ฐ ํ๋๋ ์ ๋์ด๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์์น์ฐ๋ฉด(์ฌํ๋ก๋น์ ๋) ๊ทธ
|
|
@@ -401,11 +467,11 @@ class TwinEngine {
|
|
|
401
467
|
return Array.isArray(revs) ? revs.filter((r) => Number.isFinite(r)).sort((a, b) => a - b) : [];
|
|
402
468
|
}
|
|
403
469
|
/**
|
|
404
|
-
* ๋ชฉํ ์ด์ ์ **๊ฐ์ฅ ๊ฐ๊น์ด ์ง์ **์ ๊ณ ๋ฅธ๋ค โ ์์ผ๋ฉด `null`(0๋ถํฐ
|
|
470
|
+
* ๋ชฉํ ์ด์ ์ **๊ฐ์ฅ ๊ฐ๊น์ด ์ง์ **์ ๊ณ ๋ฅธ๋ค โ ์์ผ๋ฉด `null`(0๋ถํฐ ๊ณ์ฐํ๋ค).
|
|
405
471
|
*
|
|
406
472
|
* ์๊ฐ์ผ๋ก ๋ฌผ์์ผ๋ฉด ๊ทธ ์ง์ ์ ๋ง์ง๋ง ์ฌ์ค ์๊ฐ์ด ๋ชฉํ ์ด๋ด์ฌ์ผ ํ๋ค(๋ฆฌ๋น์ ๋ง ๋ณด๋ฉด ๋ชฉํ๋ณด๋ค ๋ค์
|
|
407
473
|
* ์ฌ์ค์ด ์จ์์ ์์ธ๋ค). ๊ตฌ์กฐ๊ฐ ๋ฐ๋ ํธ์์์๋ ์ฐ์ง ์๋๋ค โ ๋ง๋๋ฅผ ๊ฑด๋๋ด ์จ์์ ๊ทธ ๊ฒฝ๊ณ์
|
|
408
|
-
* ํ์ ์ ์๋๋ค(๊ทธ ๊ฒฝ์ฐ๋ 0๋ถํฐ
|
|
474
|
+
* ํ์ ์ ์๋๋ค(๊ทธ ๊ฒฝ์ฐ๋ 0๋ถํฐ ๊ณ์ฐํ๋ ๊ฒ์ด ์ณ๋ค).
|
|
409
475
|
*/
|
|
410
476
|
static async chainSeedFor(domainId, instanceId, target) {
|
|
411
477
|
const revs = await this.chainIndex(domainId, instanceId);
|
|
@@ -456,19 +522,49 @@ class TwinEngine {
|
|
|
456
522
|
}
|
|
457
523
|
/** ์ด ํธ์ ์ ๋์ ๋ ๋ฆฌ๋น์ ยท ์ต์ ๊ตฌ์กฐ ๋ฆฌ๋น์ โ ์ค๋
์ท์ด ์ง๊ธ์ ์ฌ์ค์ธ์ง ๊ฐ๋ฆฌ๋ ๋ ๊ฐ. */
|
|
458
524
|
static async tipOf(domainId, instanceId) {
|
|
525
|
+
/*
|
|
526
|
+
* โโ **๊ด๊ณ๋ก ๋ฌป์ง ์๋๋ค** (2026-08-28) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
527
|
+
*
|
|
528
|
+
* `findOne({ where: { domain: { id } } })` ๋ ๊ด๊ณ๋ฅผ ๊ฐ์ง ์ํฐํฐ์์ ๋ ๋จ๊ณ ์ง์๊ฐ ๋๊ณ **์์ชฝ์
|
|
529
|
+
* ์ํ์ด ์๋ค** โ ์กฐ๊ฑด์ ๋ง๋ ํ์ ์ ๋ถ ๋ง๋ค์ด ๋๊ณ ๋ฐ์์ ํ ์ค์ ๊ณ ๋ฅธ๋ค. ์ด ํ์ผ์ด ๊ฐ์ ๊ฒ์
|
|
530
|
+
* ์ค์ธกํด ์ ์ด ๋์๋ค(ยง`twinEvents`: 0.024์ด ๋ 12์ด, ์ ๋ 375๋ง ํ).
|
|
531
|
+
*
|
|
532
|
+
* ์ด ํจ์๋ **๋ถํ
๋ง๋ค ํธ์๋ง๋ค** ๋ถ๋ฆฐ๋ค. ์นํํธ๋ ์ ๋์ด 337๋ง ํ์ด๋ฏ๋ก ๊ทธ ํ ๋ฒ์ด ๋ถํ
์
|
|
533
|
+
* ๋ถ์ก๋๋ค. ๊ด๊ณ๋ฅผ ์ปฌ๋ผ์ผ๋ก ๋ฌผ์ผ๋ฉด ๊ฐ์ธ์ง ์๊ณ ์์ธ(`domain, instance, revision`)์ ์ฒซ ์ค๋ก ๋๋๋ค.
|
|
534
|
+
*/
|
|
459
535
|
const [tip, newest] = await Promise.all([
|
|
460
|
-
(0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
461
|
-
|
|
536
|
+
(0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
537
|
+
.createQueryBuilder('e')
|
|
538
|
+
.select('e.revision', 'revision')
|
|
539
|
+
.where('e.domain = :domainId', { domainId })
|
|
540
|
+
.andWhere('e.instanceId = :instanceId', { instanceId })
|
|
541
|
+
.orderBy('e.revision', 'DESC')
|
|
542
|
+
.limit(1)
|
|
543
|
+
.getRawOne(),
|
|
544
|
+
(0, shell_1.getRepository)(twin_structure_js_1.TwinStructure)
|
|
545
|
+
.createQueryBuilder('s')
|
|
546
|
+
.select('s.rev', 'rev')
|
|
547
|
+
.where('s.domain = :domainId', { domainId })
|
|
548
|
+
.andWhere('s.instanceId = :instanceId', { instanceId })
|
|
549
|
+
.orderBy('s.rev', 'DESC')
|
|
550
|
+
.limit(1)
|
|
551
|
+
.getRawOne()
|
|
462
552
|
]);
|
|
463
|
-
|
|
553
|
+
const revision = Number(tip?.revision);
|
|
554
|
+
const structureRev = Number(newest?.rev);
|
|
555
|
+
return {
|
|
556
|
+
revision: Number.isFinite(revision) ? revision : 0,
|
|
557
|
+
structureRev: Number.isFinite(structureRev) ? structureRev : null
|
|
558
|
+
};
|
|
464
559
|
}
|
|
465
560
|
/**
|
|
466
|
-
* **์ ๋์ ๋ณด์กด ๊ธฐ๊ฐ๊น์ง๋ง
|
|
561
|
+
* **์ ๋์ ๋ณด์กด ๊ธฐ๊ฐ๊น์ง๋ง ๋๋ค.**
|
|
467
562
|
*
|
|
468
|
-
*
|
|
563
|
+
* ์ง์ฐ๋ ์กฐ๊ฑด์ ํ๋๋ค โ `createdAt` ์ด ๋ณด์กด ๊ธฐ๊ฐ๋ณด๋ค ์ค๋๋๋ค(**ํ์ด ์ฐ์ธ ์ค์ ์๊ฐ**์ด ๊ธฐ์ค์ด๋ค).
|
|
469
564
|
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
565
|
+
* **๋๋ ํธ์**์์๋ง ์กฐ๊ฑด์ด ํ๋ ๋ ๋ถ๋๋ค: `revision` ์ด ์ฒดํฌํฌ์ธํธ ๋ฆฌ๋น์ ์ดํ์ฌ์ผ ํ๋ค. ๋๋
|
|
566
|
+
* ํธ์์ ๋ฉ๋ชจ๋ฆฌ์์ ์ด์ด ์ง๊ณํ๋ฏ๋ก, ์ฒดํฌํฌ์ธํธ๊ฐ ์์ง ๋ฐ์ํ์ง ๋ชปํ ์ฌ๊ฑด์ ์ง์ฐ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด
|
|
567
|
+
* ์ด๋์๋ ์์ด์ง๋ค. ๋ฉ์ถ ํธ์์๋ ์ด์ด ์ง๊ณํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์์ด์ ์ด ์กฐ๊ฑด์ด ์๋ค.
|
|
472
568
|
*
|
|
473
569
|
* โโ ์ `eventTime` ์ด ์๋๋ผ `createdAt` ์ธ๊ฐ (2026-08-22 ์ค์ธก์ผ๋ก ๊ณ ์นจ) โโโโ
|
|
474
570
|
* ์ฒ์์ `eventTime` ์ผ๋ก ์ ์๋ค. ๊ทธ๊ฒ์ **ํธ์์ ์๊ณ**๋ค โ ์๋ฎฌ๋ ์ด์
์ ์๊ธฐ ์๊ณ๋ก ์ฌ๊ฑด์ ์ฐ๊ณ ,
|
|
@@ -483,9 +579,17 @@ class TwinEngine {
|
|
|
483
579
|
* `createdAt` ์ ๊ทธ ํ์ด DB ์ ์ฐ์ธ ์๊ฐ์ด๊ณ 1,599๋ง ํ ์ ๋ถ ์ฑ์์ ธ ์๋ค(ํ์ธํจ). ๋๋ฉ์ธ ์๊ฐ์
|
|
484
580
|
* ์ ์ฑ
์ ์ฐ์ง ์๋๋ค โ ๊ทธ ๋์ ์์ผ๋ฉด ์๋ฎฌ๊ณผ ๋ฏธ๋ฌ์์ ๊ฐ์ ์ค์ ์ด ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
|
|
485
581
|
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
582
|
+
* โโ ์ ์ฒดํฌํฌ์ธํธ๋ฅผ ์ ์ ์กฐ๊ฑด์ผ๋ก ๋์ง ์๋ (2026-08-27) โโโโโโโโโโโโโโโโโโโ
|
|
583
|
+
* ์์ ์๋ ์ฒดํฌํฌ์ธํธ๊ฐ ์์ผ๋ฉด ๊ทธ ํธ์์ ๊ฑด๋๋ฆฌ์ง ์์๋ค. ใ์ ๋์ด ์ ์ผํ ๋ณต๊ตฌ ์๋จใ์ด๋ผ๋ ์ ์
|
|
584
|
+
* ๋๋ฌธ์ด์๊ณ , ๊ทธ ์ ์ ๊ฐ ํ๋ ธ๋ค. ํธ์์ด ์๊ธฐ ์ ๋๊ณผ ์ด๋ค ๊ด๊ณ์ธ์ง๋ `restartPolicy` ๊ฐ ์ ์ธํ๋ค โ
|
|
585
|
+
* `resync` ๋ ์ฐ๊ฒฐ๋ ์์คํ
์์ ๋ค์ ์ฝ๊ณ , `reset` ์ ์จ์๋ถํฐ ๋๋ฆฌ๊ณ , `resume` ์ ๋ณด๊ด๋ ๊ตฌ๊ฐ์์
|
|
586
|
+
* ์ธ์ด๋ค. ์
๋ค ๋ณด๊ด ๊ธฐ๊ฐ ๋ฐ์ ์ฌ๊ฑด์ ์๊ตฌํ์ง ์๋๋ค.
|
|
587
|
+
*
|
|
588
|
+
* ๋ณด์กด ๊ธฐ๊ฐ์ 7์ผ๋ก ์ ์ธํ ๊ฒ์ด ๊ณง ใ7์ผ ์ ์ํ๋ก๋ ์ธ์ฐ์ง ์๋๋คใ๋ ๋ป์ด๋ค. ๊ทธ ์ ์ ๋ฅผ ์งํค๋๋ผ
|
|
589
|
+
* ์ง์ฐ์ง ์์ผ๋ฉด, ๋ฉ์ถ ํธ์์ ์ ๋์ด ์๊ตฌํ ๋จ๋๋ค โ ์ค์ธก์ผ๋ก ์ธ ํธ์์ 2,900๋ง ํ์ด ๊ทธ๋ ๊ฒ ๋จ์๋ค.
|
|
590
|
+
*
|
|
591
|
+
* ใ์ง์ธ ์ ์์๋คใ๋ ์ฌ์ค์ ๊ทธ๋๋ก ์ผ๋ค(๋๋๋ฐ ์ฒดํฌํฌ์ธํธ๊ฐ ์์ง ์๋ ๊ฒฝ์ฐ) โ ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ๋ฉด
|
|
592
|
+
* ใ๋ณด์กด์ด ๋๋๋ฐ ์ ์ ์ค์ด๋๋ใ๊ฐ ๋๋ค.
|
|
489
593
|
*
|
|
490
594
|
* `createdAt` ์ด ๋น ์ ํ์ **์ง์ฐ์ง ์๋๋ค**(์๊ฐ์ ๋ชจ๋ฅด๋ ๊ฒ์ ใ์ค๋๋๋คใ๋ก ์ฝ์ง ์๋๋ค).
|
|
491
595
|
*
|
|
@@ -496,52 +600,193 @@ class TwinEngine {
|
|
|
496
600
|
const perDomain = this.retentionDaysOf ? await this.retentionDaysOf(domainId).catch(() => undefined) : undefined;
|
|
497
601
|
const days = perDomain ?? this.JOURNAL_RETENTION_DAYS;
|
|
498
602
|
if (!days || days <= 0)
|
|
499
|
-
return { deleted: 0, instances: 0
|
|
500
|
-
/*
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
603
|
+
return { deleted: 0, instances: 0 };
|
|
604
|
+
/*
|
|
605
|
+
* โโ ๋ณด์กด ๊ธฐ๊ฐ์ ์ค๋
์ท TTL ๋ก ์ฌ๋ฆฌ์ง ์๋๋ค (2026-08-27) โโโโโโโโโโโโโโโโโโโโ
|
|
606
|
+
*
|
|
607
|
+
* ์ฌ๊ธฐ๊ฐ `max(๋ณด์กด ๊ธฐ๊ฐ, ์ค๋
์ท TTL)` ์ด์๋ค. ๋ ๋ค 7์ผ์ด๋ผ ์ํฅ์ ์์์ง๋ง, ๊ทธ ์์ ๋ ๊ฐ์
|
|
608
|
+
* ๋ฌถ์ด ๋์์ ํ๋๋ฅผ ์ค์ด๋ฉด ๋ค๋ฅธ ํ๋๊ฐ ๋ฐ๋ผ์ค๊ฒ ๋ง๋ ๋ค. ๋ ๊ฐ์ ๋ค๋ฅธ ๊ฒ์ ์ ํ๋ค.
|
|
609
|
+
*
|
|
610
|
+
* ๋ณด์กด ๊ธฐ๊ฐ ์ด๋ ฅ์ ๋ฉฐ์น ๋๋
|
|
611
|
+
* ์ค๋
์ท TTL ๋น ๋ฅด๊ฒ ์ธ์ฐ๊ธฐ ์ํ ์ ์ฅ๋ณธ์ด ๋ฉฐ์น ์ฌ๋
|
|
612
|
+
*
|
|
613
|
+
* ์ ์ฅ๋ณธ์ด ๋ง๋ฃ๋์ด๋ ํธ์์ ๋ณด๊ด๋ ๊ตฌ๊ฐ์์ ์ธ์์ง๋ค. ๊ทธ๋์ ๋ณด์กด ๊ธฐ๊ฐ์ด ๋ ์งง์๋ ์ฑ๋ฆฝํ๋ค.
|
|
614
|
+
*/
|
|
615
|
+
const effectiveDays = days;
|
|
507
616
|
const cutoff = new Date(Date.now() - effectiveDays * 86400 * 1000);
|
|
508
617
|
const rows = await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } });
|
|
509
618
|
let deleted = 0;
|
|
510
619
|
let instances = 0;
|
|
511
|
-
const skipped = [];
|
|
512
620
|
for (const r of rows) {
|
|
621
|
+
/*
|
|
622
|
+
* โโ ์ฒดํฌํฌ์ธํธ๋ **์ํ**์ด์ง ์ ์ ์กฐ๊ฑด์ด ์๋๋ค (2026-08-27 ์ฌ์ฉ์ ์ง์๋ก ๊ณ ์นจ) โโ
|
|
623
|
+
*
|
|
624
|
+
* ์ฌ๊ธฐ๊ฐ ์ฒดํฌํฌ์ธํธ๊ฐ ์์ผ๋ฉด ๊ฑด๋๋ฐ์๋ค. ๊ทธ ๊ท์น์ ใ์ ๋์ด ์ ์ผํ ๋ณต๊ตฌ ์๋จใ์ด๋ผ๋ ์ ์ ์์
|
|
625
|
+
* ๋์๋๋ฐ, ๊ทธ ์ ์ ๊ฐ ํ๋ ธ๋ค. ํธ์์ด ์๊ธฐ ์ ๋๊ณผ ์ด๋ค ๊ด๊ณ์ธ์ง๋ `restartPolicy` ๊ฐ ์ ์ธํ๋ค.
|
|
626
|
+
*
|
|
627
|
+
* resync ์ฐ๊ฒฐ๋ ์์คํ
์์ ๋ค์ ์ฝ๋๋ค ์ ๋์ ๋ณต๊ตฌ ์๋จ์ด ์๋๋ค
|
|
628
|
+
* reset ์จ์๋ถํฐ ๋ค์ ๋๋ฆฐ๋ค ์ ๋์ ๋ณต๊ตฌ ์๋จ์ด ์๋๋ค
|
|
629
|
+
* resume ์ ๋์ ์ด์ด ์ธ์ด๋ค ๋ณด๊ด๋ ๊ตฌ๊ฐ์์ ์ธ์ด๋ค
|
|
630
|
+
*
|
|
631
|
+
* ์
๋ค ๋ณด๊ด ๊ธฐ๊ฐ ๋ฐ์ ์ฌ๊ฑด์ ์๊ตฌํ์ง ์๋๋ค. ๋ณด๊ด ๊ธฐ๊ฐ 7์ผ์ด๋ผ๋ ์ ์ธ์ด ๊ณง ใ7์ผ ์ ์ํ๋ก๋
|
|
632
|
+
* ์ธ์ฐ์ง ์๋๋คใ๋ ๋ป์ด๋ค. ๊ทธ๋์ ์ ๋ฆฌ๋ ์ฒดํฌํฌ์ธํธ ์์ด๋ ์ง์ด๋ค.
|
|
633
|
+
*
|
|
634
|
+
* ์ฒดํฌํฌ์ธํธ๊ฐ ํ๋ ์ผ์ ํ๋ ๋จ๋๋ค. ์ฒดํฌํฌ์ธํธ๊ฐ **์์ผ๋ฉด** ๊ทธ ๋ฆฌ๋น์ ์ ์ํ์ผ๋ก ์ด๋ค โ ๋ค์
|
|
635
|
+
* ๊ธฐ๋์ด ๊ทธ ์ง์ ์์ ์ด์ด ์ง๊ณํ๋ฏ๋ก, ๊ทธ ๋ค์ ์ฌ๊ฑด์ ์ง์ฐ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ์ด๋์๋ ์์ด์ง๋ค.
|
|
636
|
+
*
|
|
637
|
+
* **์์ผ๋ฉด ์ํ๋ ์๋ค.** ์ด์ด ์ง๊ณํ ์ง์ ์ด ์์ผ๋ ์งํฌ ๊ฒ๋ ์๊ณ , ๋ณด๊ด ๊ธฐ๊ฐ ์กฐ๊ฑด๋ง์ผ๋ก ์ง์ด๋ค.
|
|
638
|
+
* ์๋ค๋ ์ด์ ๋ก ๊ฑด๋๋ฐ๋ฉด ๋ฉ์ถ ํธ์์ ์๊ตฌํ ์ค์ง ์๋๋ค(์ค์ธก: ์ธ ํธ์์ 2,900๋ง ํ).
|
|
639
|
+
*/
|
|
513
640
|
const snap = await this.loadSnapshot(domainId, r.instanceId).catch(() => null);
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
641
|
+
const at = Number(snap?.revision ?? 0);
|
|
642
|
+
const upTo = at > 0 ? at : Number.MAX_SAFE_INTEGER;
|
|
643
|
+
/*
|
|
644
|
+
* โโ ๋๋ ์ ์ง์ด๋ค (2026-08-25 ์ค์ธก์ผ๋ก ๊ณ ์นจ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
645
|
+
*
|
|
646
|
+
* ์ฌ๊ธฐ๊ฐ **ํ ๋ฌธ์ฅ์ผ๋ก ํต์งธ** ์ง์ ๋ค. ์ง์ธ ๊ฒ์ด ๋ฉฐ์น ์น๋ฉด ๊ทธ ํ ๋ฌธ์ฅ์ด ์๋ฐฑ๋ง ํ์ด ๋๊ณ , sqlite ๋
|
|
647
|
+
* ์ฐ๊ธฐ๊ฐ ํ๋์ด๋ฏ๋ก ๊ทธ๋์ ํธ์คํธ๊ฐ ์๋ฌด ์ผ๋ ๋ชป ํ๋ค. ์ค์ธก: ํ ๋ฒ์ ์ง์ฐ๊ธฐ๊ฐ 74์ดยท79์ด์๊ณ ,
|
|
648
|
+
* ๊ทธ ๋ค์ ํ ์ค์ง๋ฆฌ `domains` ์กฐํ๊ฐ 67์ด๋ก ์ฐํ๋ค โ ๊ทธ ์ง์์ ๋ฌธ์ ๊ฐ ์๋๋ผ ์ค์ ์ ๊ฐ์ด๋ค.
|
|
649
|
+
* ๊ฐ๋ฐ ํ๊ฒฝ์์ ๋ณด๊ด ๊ธฐ๊ฐ 7์ผ์ 13์ผ์น๊ฐ ์์ฌ ์์๊ณ , ๊ทธ ๋ฐ๋ฆฐ ๋ชซ์ด ํ ๋ฒ์ ๋์๋ค.
|
|
650
|
+
*
|
|
651
|
+
* ๊ทธ๋์ **ํ ๋ฒ์ ์ง์ฐ๋ ์๋ฅผ ๋ฌถ๊ณ **, ๋ฐฐ์น ์ฌ์ด์ ๋ฃจํ๋ฅผ ๋น์ ์ค๋ค. ๊ทธ๋ฆฌ๊ณ ํ ์ฐฝ์์ ์ฐ๋
|
|
652
|
+
* ์๊ฐ์๋ ์ํ์ ๋๋ค โ ๋จ์ ๊ฒ์ ๋ค์ ์ฐฝ์ด ์ด์ด์ ์ง์ด๋ค. ์ง์ฐ๋ ์ด๋์ ๊ฐ๊ณ , ๊ทธ ์ฌ์ด์
|
|
653
|
+
* ์ฌ๋์ ์์ฒญ์ด ์ฒ๋ฆฌ๋๋ค.
|
|
654
|
+
*
|
|
655
|
+
* `DELETE โฆ LIMIT` ์ ๋๋ผ์ด๋ฒ๋ง๋ค ๋ค๋ฅด๋ฏ๋ก ์ฐ์ง ์๋๋ค(sqlite ๋ ๊ธฐ๋ณธ ๋น๋์์ ์ง์ํ์ง ์๋๋ค).
|
|
656
|
+
* ๋์ **๊ฒฝ๊ณ ๋ฆฌ๋น์ ์ ๋จผ์ ์ฐพ์** ๊ทธ ์๋๋ง ์ง์ด๋ค โ ๋ค์ฏ ๋๋ผ์ด๋ฒ์์ ๊ฐ์ ๋ป์ด ๋๋ ๋ฐฉ๋ฒ์ด๋ค.
|
|
657
|
+
*/
|
|
658
|
+
let n = 0;
|
|
659
|
+
const startedMs = Date.now();
|
|
660
|
+
for (;;) {
|
|
661
|
+
/*
|
|
662
|
+
* โโ ๊ฒฝ๊ณ๋ฅผ **์๊ฐ**์ผ๋ก ์ฐพ๋๋ค (2026-08-27 ์ค์ธก์ผ๋ก ๊ณ ์นจ) โโโโโโโโโโโโโโโโโโ
|
|
663
|
+
*
|
|
664
|
+
* ์ฌ๊ธฐ๊ฐ `ORDER BY revision` ์ด์๋ค. ๊ทธ๋ฌ๋ฉด ๊ณํ๊ธฐ๊ฐ ๋ฆฌ๋น์ ์์ธ์ ๊ณ ๋ฅด๊ณ , ์ง์ธ ๋์์ธ์ง๋
|
|
665
|
+
* ํ๋ง๋ค `created_at` ์ ์ด์ด ํ์ธํ๋ค. ์ง์ธ ๊ฒ์ด ์ ์ผ๋ฉด ๊ทธ ํธ์์ ์ ๋์ ๋๊น์ง ๊ฑธ์ด์ผ
|
|
666
|
+
* ใํ ๋ฐฐ์น๋ฅผ ๋ชป ์ฑ์ ๋คใ๋ฅผ ์ ์ ์๋ค โ 1,029๋ง ํ์์ ๊ทธ๊ฒ์ด 2์ด ์์ฐ์ ๋ค ์ผ๊ณ 44๊ฑด๋ง
|
|
667
|
+
* ์ง์ฐ๊ณ ๋ฉ์ท๋ค.
|
|
668
|
+
*
|
|
669
|
+
* ์๊ฐ์์ผ๋ก ๋ฌผ์ผ๋ฉด `(domain, instance, created_at)` ์์ธ์ ๊ทธ๋๋ก ์ด๋ค. ์ค์ธก ๊ณํ:
|
|
670
|
+
*
|
|
671
|
+
* ORDER BY revision SEARCH USING INDEX ix_twin_event_0 โ created_at ์ ํ๋ง๋ค ํ์ธ
|
|
672
|
+
* ORDER BY createdAt SEARCH USING COVERING INDEX ix_twin_event_8 โ ํ
์ด๋ธ์ ์ด์ง ์๋๋ค
|
|
673
|
+
*
|
|
674
|
+
* ์ง์ฐ๊ธฐ๋ ์ ๋ ฌ์ด ์์ด ์์ธ๋ง ์์ผ๋ฉด ๋ฐ๋ก ๊ทธ๊ฒ์ ์ด๋ค(์ค์ธก ํ์ธ).
|
|
675
|
+
*/
|
|
676
|
+
const edge = await (0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
677
|
+
.createQueryBuilder('e')
|
|
678
|
+
.select('e.createdAt', 'createdAt')
|
|
679
|
+
.where('e.domain = :domainId', { domainId })
|
|
680
|
+
.andWhere('e.instanceId = :instanceId', { instanceId: r.instanceId })
|
|
681
|
+
.andWhere('e.createdAt IS NOT NULL')
|
|
682
|
+
.andWhere('e.createdAt < :cutoff', { cutoff })
|
|
683
|
+
.orderBy('e.createdAt', 'ASC')
|
|
684
|
+
.offset(this.JOURNAL_PRUNE_BATCH - 1)
|
|
685
|
+
.limit(1)
|
|
686
|
+
.getRawOne();
|
|
687
|
+
/*
|
|
688
|
+
* ๊ฒฝ๊ณ๊ฐ ์์ผ๋ฉด ๋จ์ ๊ฒ์ด ํ ๋ฐฐ์น ์์ด๋ค โ ๊ทธ๋๋ ๋ณด๊ด ๊ธฐ๊ฐ ๊ฒฝ๊ณ๊น์ง ์ง์ฐ๊ณ ๋๋๋ค.
|
|
689
|
+
*
|
|
690
|
+
* ๊ฒฝ๊ณ๊ฐ ์์ผ๋ฉด ๊ทธ ์๊ฐ **์ดํ**๊น์ง ์ง์ด๋ค(`<=`). ๊ฐ์ ์๊ฐ์ ํ์ด ์ฌ๋ฟ์ด๋ฉด ํ ๋ฐฐ์น๊ฐ ์กฐ๊ธ
|
|
691
|
+
* ์ปค์ง์ง๋ง, `<` ๋ก ๋๋ฉด ๊ทธ ์๊ฐ์ ํ๋ค์ด ๋จ์ ๋ค์ ๋ฐฐ์น๊ฐ ๊ฐ์ ๊ฒฝ๊ณ๋ฅผ ๋ค์ ์ฐพ๋๋ค(์ ์๋ฆฌ๊ฑธ์).
|
|
692
|
+
*/
|
|
693
|
+
/*
|
|
694
|
+
* ์์ ๊ฒฐ๊ณผ์ ์ปฌ๋ผ ๊ฐ์ **๋๋ผ์ด๋ฒ์๊ฒ ํด์์ํจ๋ค**(ยง`hydratedDate`). sqlite ๊ฐ ์ฃผ๋ ๊ฐ์๋
|
|
695
|
+
* ์๊ฐ๋๊ฐ ์์ด์ ๊ทธ๋๋ก `new Date()` ๋ก ์ฝ์ผ๋ฉด ์ง์ญ ์๊ฐ์ผ๋ก ํด์๋๋ค โ ๊ฒฝ๊ณ๊ฐ ๊ทธ๋งํผ ์ด๋ฅด๊ฒ
|
|
696
|
+
* ๋ฐ๋ฆฌ๊ณ , ๊ทธ๋ฌ๋ฉด **ํ ๊ฑด๋ ์ง์ฐ์ง ๋ชปํด ์ ๋ฆฌ๊ฐ ๊ทธ๋๋ก ๋ฉ์ถ๋ค**(0๊ฑด์ด๋ฉด ๋ฐ๋ณต์ ๋๋ธ๋ค).
|
|
697
|
+
*/
|
|
698
|
+
const batchCutoff = (0, read_time_js_1.hydratedDate)((0, shell_1.getRepository)(twin_event_js_1.TwinEvent), 'createdAt', edge?.createdAt);
|
|
699
|
+
const del = (0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
700
|
+
.createQueryBuilder()
|
|
701
|
+
.delete()
|
|
702
|
+
.from(twin_event_js_1.TwinEvent)
|
|
703
|
+
.where('domain_id = :domainId', { domainId })
|
|
704
|
+
.andWhere('instance_id = :instanceId', { instanceId: r.instanceId })
|
|
705
|
+
/* ์ฒดํฌํฌ์ธํธ๊ฐ ์์ง ๋ฐ์ํ์ง ๋ชปํ ์ฌ๊ฑด์ ์ง์ฐ์ง ์๋๋ค(๋๋ ํธ์์์๋ง ์ํ์ด ๊ฑธ๋ฆฐ๋ค). */
|
|
706
|
+
.andWhere('revision <= :upTo', { upTo })
|
|
707
|
+
.andWhere('created_at IS NOT NULL');
|
|
708
|
+
const res = await (batchCutoff
|
|
709
|
+
? del.andWhere('created_at <= :batchCutoff', { batchCutoff })
|
|
710
|
+
: del.andWhere('created_at < :cutoff', { cutoff })).execute();
|
|
711
|
+
const batch = res.affected ?? 0;
|
|
712
|
+
n += batch;
|
|
713
|
+
if (!batch)
|
|
714
|
+
break;
|
|
715
|
+
if (Date.now() - startedMs >= this.JOURNAL_PRUNE_BUDGET_MS) {
|
|
716
|
+
(0, log_js_1.twinLog)(`[twin-engine] journal prune paused "${r.instanceId}" โ ์ด๋ฒ ์ฐฝ์์ ${n}๊ฑด๊น์ง ์ง์ ๋ค. ` +
|
|
717
|
+
'๋จ์ ๊ฒ์ ๋ค์ ์ฐฝ์ด ์ด์ด์ ์ง์ด๋ค(ํธ์คํธ๊ฐ ๊ทธ ์ฌ์ด์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ค).');
|
|
718
|
+
break;
|
|
719
|
+
}
|
|
720
|
+
/* ๋ฃจํ๋ฅผ ๋น์ ์ค๋ค โ ์ด ํ ์ค์ด ์์ผ๋ฉด ๋ฐฐ์น๋ก ๋๋ ๋ป์ด ์๋ค(๊ฐ์ ํฑ์์ ๊ณ์ ์ง์ด๋ค). */
|
|
721
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
519
722
|
}
|
|
520
|
-
const res = await (0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
521
|
-
.createQueryBuilder()
|
|
522
|
-
.delete()
|
|
523
|
-
.from(twin_event_js_1.TwinEvent)
|
|
524
|
-
.where('domain_id = :domainId', { domainId })
|
|
525
|
-
.andWhere('instance_id = :instanceId', { instanceId: r.instanceId })
|
|
526
|
-
.andWhere('revision <= :upTo', { upTo })
|
|
527
|
-
.andWhere('created_at IS NOT NULL')
|
|
528
|
-
.andWhere('created_at < :cutoff', { cutoff })
|
|
529
|
-
.execute();
|
|
530
|
-
const n = res.affected ?? 0;
|
|
531
723
|
if (n > 0) {
|
|
532
724
|
deleted += n;
|
|
533
725
|
instances++;
|
|
534
|
-
/* **์ง์ด ๊ฒ์ ๋งํ๋ค** โ
|
|
535
|
-
(0, log_js_1.twinLog)(`[twin-engine] journal pruned "${r.instanceId}" โ ${n}๊ฑด (
|
|
536
|
-
|
|
726
|
+
/* **์ง์ด ๊ฒ์ ๋งํ๋ค** โ ์๋ฆฌ์ง ์๊ณ ์ค์ด๋ ์ ๋์ ใ์์๋ ์ผใ๊ณผ ๊ตฌ๋ณ๋์ง ์๋๋ค. */
|
|
727
|
+
(0, log_js_1.twinLog)(`[twin-engine] journal pruned "${r.instanceId}" โ ${n}๊ฑด (${cutoff.toISOString()} ์ด์ ` +
|
|
728
|
+
`${upTo < Number.MAX_SAFE_INTEGER ? ` ยท revision โค ${upTo} ๊น์ง๋ง, ๊ทธ ๋ค๋ ์ฒดํฌํฌ์ธํธ๊ฐ ๋์ ํ์ง ๋ชปํ๋ค` : ''}).`);
|
|
729
|
+
}
|
|
730
|
+
/*
|
|
731
|
+
* โโ ์กฐํ์ฉ ํ์ ํ๋ ๊ฐ์ ์ฐฝ์์ ์ค์ธ๋ค (2026-08-27) โโโโโโโโโโโโโโโโโโโโโโโโ
|
|
732
|
+
*
|
|
733
|
+
* ์ด ํ๋ **๋ฒ๋ฆด ์ ์๋ ๊ฐ**์ด๋ค(์ฌ๊ฑด์์ ํ์๋ ๊ฒ์ด๋ฏ๋ก). ์ง์ฐ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ ์ด๋ ฅ ์กฐํ๊ฐ ์ ๋๋ก
|
|
734
|
+
* ๋์ด๊ฐ ๋๋ ค์ง๊ณ , ์ฌ์ค์ ์ฌ๋ผ์ง์ง ์๋๋ค.
|
|
735
|
+
*
|
|
736
|
+
* ๊ทธ๋์ ์ฒดํฌํฌ์ธํธ ์ํ์ ๋ณด์ง ์๋๋ค โ ๊ทธ ์ํ์ ใ์ฌ์ค์ ์์ง ์๊ธฐ ์ํ ๊ฒใ์ด๊ณ ์ฌ๊ธฐ์๋ ์์
|
|
737
|
+
* ์ฌ์ค์ด ์๋ค. ๋ณด๊ด ๊ธฐ๊ฐ๋ง ๋ณธ๋ค.
|
|
738
|
+
*/
|
|
739
|
+
const subjectPruned = await (0, twin_subject_writer_js_1.pruneSubjectRows)(domainId, r.instanceId, cutoff, this.JOURNAL_PRUNE_BUDGET_MS, this.JOURNAL_PRUNE_BATCH).catch(() => 0);
|
|
740
|
+
if (subjectPruned > 0) {
|
|
741
|
+
(0, log_js_1.twinLog)(`[twin-subject] pruned "${r.instanceId}" โ ${subjectPruned}์ค (${cutoff.toISOString()} ์ด์ ).`);
|
|
537
742
|
}
|
|
538
743
|
}
|
|
539
|
-
|
|
540
|
-
(0, log_js_1.twinLog)(`[twin-engine] journal prune skipped ${skipped.length} instance(s) with no checkpoint โ ` +
|
|
541
|
-
`์ ๋์ด ์ ์ผํ ๋ณต๊ตฌ ์๋จ์ด๋ผ ์๋์ง ์์๋ค: ${skipped.slice(0, 5).join(', ')}${skipped.length > 5 ? ' โฆ' : ''}`);
|
|
542
|
-
}
|
|
543
|
-
return { deleted, instances, skipped };
|
|
744
|
+
return { deleted, instances };
|
|
544
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* ํ ๋ฒ์ ์ง์ฐ๊ธฐ๊ฐ ๋ค๋ฃจ๋ ํ ์ โ ์ฐ๊ธฐ ์ ๊ธ์ ์ด ๋งํผ๋ง ์ก๋๋ค.
|
|
748
|
+
*
|
|
749
|
+
* โโ 20,000 ์ด ์ ์ปธ๋ (2026-08-28 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
750
|
+
* ์ ํ์ 20,000 ์ด์๊ณ ๊ทผ๊ฑฐ๋ ใํ ๋ฌธ์ฅ์ผ๋ก ์๋ฐฑ๋ง ํ์ ์ง์ฐ๋ฉด 74์ด์๋คใ์๋ค. ๊ทธ๊ฒ์ **๋ ๋์
|
|
751
|
+
* ์ชฝ๊ณผ ๊ฒฌ์ค ์**์ด๊ณ , 20,000 ์์ฒด๋ฅผ ์ฐ ๊ฒ์ด ์๋์๋ค. ์ค์ ๋ก ์ฌ ๋ณด๋ ์ด๋ ๋ค(์๋ฒ ๊ธฐ๋ก):
|
|
752
|
+
*
|
|
753
|
+
* hatio-mx1 20,123์ค 5.6์ด
|
|
754
|
+
* hatio-mx2 20,130์ค 5.2์ด
|
|
755
|
+
* hatio-us 20,139์ค 4.2์ด
|
|
756
|
+
* ํ ์ฐฝ์ ํฉ๊ณ ์ฝ 15์ด
|
|
757
|
+
*
|
|
758
|
+
* sqlite ๋ ์ฐ๊ฒฐ์ด ํ๋๋ค. ๊ทธ๋์ ๊ทธ 4~5์ด ๋์ **ํ๋ฉด์ ๋ชจ๋ ์ง์๊ฐ ์ค์ ์ ๋ค** โ ์ค์ธก์ผ๋ก ์ฒซ
|
|
759
|
+
* ํ๋ฉด ์กฐํ๊ฐ 12.2์ด์๋ค(์ ์ ์ํ์์๋ 40๋ฐ๋ฆฌ์ด๋ค).
|
|
760
|
+
*
|
|
761
|
+
* ๊ทธ๋ฆฌ๊ณ ์์ฐ(`JOURNAL_PRUNE_BUDGET_MS` = 2์ด)์ด **๋ฌธ์ฅ์ด ๋๋ ๋ค์** ๊ฒ์ฌ๋๋ฏ๋ก, ํ ๋ฌธ์ฅ์ด ์์ฐ์
|
|
762
|
+
* 2~3๋ฐฐ ๋๊ธด๋ค. ๋ฐฐ์น๋ฅผ ๋๋ ๋ป์ด ๊ทธ๋งํผ ์์ด์ง๋ค.
|
|
763
|
+
*
|
|
764
|
+
* โโ 2,000 ์ ๊ทผ๊ฑฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
765
|
+
* ์ ์ค์ธก์ด ์ค๋น ์ฝ 0.26๋ฐ๋ฆฌ์ด๋ค(5.2์ด / 20,130์ค). 2,000์ค์ด๋ฉด **ํ ๋ฌธ์ฅ์ด ์ฝ 0.5์ด**๋ค. ํ๋ฉด์ด
|
|
766
|
+
* ํ ๋ฒ ๋ฉ์ถ๋ ๊ธธ์ด๊ฐ 5์ด์์ 0.5์ด๋ก ์ค๊ณ , ์์ฐ ๊ฒ์ฌ๋ ๋ป์ ๊ฐ๋๋ค(ํ ์ฐฝ์ ๋ฌธ์ฅ ๋ท).
|
|
767
|
+
*
|
|
768
|
+
* ์ด๋์ ๊ฐ๊ณ ๋๋ ์ ์น๋ฅธ๋ค โ ์ฐฝ๋ง๋ค ์ง์ฐ๋ ์๊ฐ ์ค์ง๋ง ์ง์ฐ๋ ์ผ์ ๊ธํ์ง ์๋ค(์ฐฝ์ด 10๋ถ๋ง๋ค ์จ๋ค).
|
|
769
|
+
*
|
|
770
|
+
* ๊ฐ์ ๋ฐ๊พธ๋ ค๋ฉด ๋ค์ ์ฌ๊ณ ์ด ๋ฌธ์ฅ์ ๊ณ ์น ๊ฒ.
|
|
771
|
+
*/
|
|
772
|
+
static { this.JOURNAL_PRUNE_BATCH = 2_000; }
|
|
773
|
+
/**
|
|
774
|
+
* ํ ์ฐฝ์์ ์ง์ฐ๋ ๋ฐ ์ฐ๋ ์๊ฐ ์ํ(ms) โ ๋จ์ ๊ฒ์ ๋ค์ ์ฐฝ์ด ์ด์ด์ ์ง์ด๋ค.
|
|
775
|
+
*
|
|
776
|
+
* ๋ฐ๋ฆฐ ๋ชซ์ด ๋ฉฐ์น ์น๋ฉด ํ ์ฐฝ์์ ๋ค ์ง์ธ ์ ์๋ค. ๋ค ์ง์ฐ๋ ค ๋ค๋ฉด ๊ทธ๋์ ํธ์คํธ๊ฐ ๋ฉ์ถ๊ณ , ๊ทธ๊ฒ์ด ๋ฐ๋ก
|
|
777
|
+
* ๊ณ ์น๋ ค๋ ์ฆ์์ด๋ค. ์ด๋์ ๊ฐ๊ณ ๋๋ ์ ์น๋ฅธ๋ค.
|
|
778
|
+
*
|
|
779
|
+
* โโ 2์ด์์ 5์ด๋ก ์ฌ๋ฆฐ ์ด์ (2026-08-28) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
780
|
+
* ๋ฐฐ์น๋ฅผ 20,000 โ 2,000 ์ผ๋ก ์ค์๋ค(ยง`JOURNAL_PRUNE_BATCH`). ์์ฐ์ ๊ทธ๋๋ก ๋๋ฉด **์ฐฝ๋ง๋ค ์ง์ฐ๋
|
|
781
|
+
* ์์ด 2.5๋ฐฐ ์ค์ด** ๋ฐ๋ฆฐ ๋ชซ์ด ๋น ์ง์ง ์๋๋ค.
|
|
782
|
+
*
|
|
783
|
+
* ์์ฐ์ 5์ด๋ก ๋๋ฉด ํ ์ฐฝ์ ๋ฌธ์ฅ ์ด ๊ฐ(๊ฐ 0.5์ด)๊ฐ ๋์ **์ง์ฐ๋ ์์ ์ ๊ณผ ๊ฐ๊ณ **, ์ ๊ธ์ ์ด ๋ฒ
|
|
784
|
+
* ๋๋์ด ๊ทธ ์ฌ์ด์ ํ๋ฉด ์ง์๊ฐ ์ฒ๋ฆฌ๋๋ค. ๊ณ ์น๋ ค๋ ๊ฒ์ ์ด ์๊ฐ์ด ์๋๋ผ **ํ ๋ฒ์ ๋ฉ์ถ๋ ๊ธธ์ด**๋ค.
|
|
785
|
+
*
|
|
786
|
+
* ์ ํ ๋ฌธ์ฅ 5.2์ด ยท ๊ทธ๋์ ๋ชจ๋ ์กฐํ๊ฐ ์ค์ ์ ๋ค
|
|
787
|
+
* ํ ๋ฌธ์ฅ ์ด ๊ฐ ร 0.5์ด ยท ์ฌ์ด๋ง๋ค ๋ฃจํ๋ฅผ ๋น์ ์ค๋ค
|
|
788
|
+
*/
|
|
789
|
+
static { this.JOURNAL_PRUNE_BUDGET_MS = 5_000; }
|
|
545
790
|
/** ๋ณด์กด ์ ๋ฆฌ ์ฃผ๊ธฐ ๊ธฐ๋(1ํ) โ ์ ์ธ์ด ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค. */
|
|
546
791
|
static startRetentionLoop(domainId) {
|
|
547
792
|
if (this.retentionTimer)
|
|
@@ -641,7 +886,7 @@ class TwinEngine {
|
|
|
641
886
|
* `bootstrap()` ์ ์ํ๋ง ๋์ฐพ์ `recovered` ์ ๋ด์๊ณ , ์ปค๋์ ์ธ์ฐ๋ ๊ฒ์ **๋ช
์ mutation ๋ฟ**์ด์๋ค
|
|
642
887
|
* (์ด ํ์ผ ์์ชฝ ์ฃผ์์ด ใํฅํใ๋ผ๊ณ ์ ์ด ๋ ๊ทธ ์๋ฆฌ๋ค). ๊ทธ๋์ ์๋ฒ๋ฅผ ํ ๋ฒ ์ฌ๊ธฐ๋ํ๋ฉด ๋ฑ๋ก๋ถ๋
|
|
643
888
|
* `running` ์ด๋ผ ๋งํ๋๋ฐ **์๋ฌด ์ปค๋๋ ๋์ง ์์๋ค** โ ํ๋ฉด์ ๋๋ ํธ์์, ์ค์ ๋ก๋ ๋ฉ์ถ ํธ์์.
|
|
644
|
-
* ๋ฏธ๋ฌ ํธ์์์๋ ๋ ๋์๋ค: ๊ณ์ธก์ด
|
|
889
|
+
* ๋ฏธ๋ฌ ํธ์์์๋ ๋ ๋์๋ค: ๊ณ์ธก์ด ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ๊ณ , ์ฌ๋์ ใ๊ฐ์ด ์ ๋ณํ๋คใ๋ก ์๊ฒ ๋๋ค.
|
|
645
890
|
*
|
|
646
891
|
* โโ ๋ชจ๋๋ฅผ ์ง์ด๋ด์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
647
892
|
* ๋ฏธ๋ฌ์๋ ํธ์์ ์๋ฎฌ๋ก ๋์ด๋ฆฌ๋ฉด **์๋ ์์ง์์ ๋ง๋ค์ด ๋ธ๋ค**(๊ด์ธก ํธ์์ด ์ค์ค๋ก ๋ฌผ๊ฑด์ ์ฎ๊ธด๋ค).
|
|
@@ -752,7 +997,7 @@ class TwinEngine {
|
|
|
752
997
|
...(plan.attentionSinceCount ? [`${plan.attentionSinceCount} attention start time(s)`] : [])
|
|
753
998
|
].join(', ');
|
|
754
999
|
(0, log_js_1.twinLog)(`[twin-engine] warm-started "${id}" โ restored ${restored}.`);
|
|
755
|
-
/* ๋บ ๊ฒ์
|
|
1000
|
+
/* ๋บ ๊ฒ์ ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค โ ์ง์ด๋ด์ง ์์๋ค๋ ์ฌ์ค ์์ฒด๋ฅผ ๋งํด์ผ ํ๋ฉด์ ๋น์นธ์ด ์ฝํ๋ค. */
|
|
756
1001
|
if (plan.ordersWithoutDemand > 0) {
|
|
757
1002
|
(0, log_js_1.twinWarn)(`[twin-engine] "${id}": ${plan.ordersWithoutDemand} order(s) could not be restored โ they carry progress only, ` +
|
|
758
1003
|
'with no requested/fulfilled counts, so the remaining demand is unknown. They are left out rather than guessed.');
|
|
@@ -765,7 +1010,7 @@ class TwinEngine {
|
|
|
765
1010
|
* `model.operations`(๋ง์คํฐ ์ธ์ ์คํธ๊ฐ ํต๊ณผ์ํจ ISA-95 OperationsSegment ๋ช
์ธ)๋ฅผ ์ปค๋์ด ์๋นํ๋ค.
|
|
766
1011
|
* ์์ผ๋ฉด ์ปค๋ ๊ธฐ๋ณธ ์์๋ก ๊ตด๋ฌ๊ฐ๊ณ , ์ปค๋ `specCoverage()` ๊ฐ ๋ฌด์์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ผ๋์ง ๋ณด๊ณ ํ๋ค.
|
|
767
1012
|
*
|
|
768
|
-
* ์ปค๋์ด ์์ง ์ด API ๋ฅผ ๊ฐ์ง ์์ ๋ฒ์ ์ด๋ฉด(๋ฐํ ์ด์ )
|
|
1013
|
+
* ์ปค๋์ด ์์ง ์ด API ๋ฅผ ๊ฐ์ง ์์ ๋ฒ์ ์ด๋ฉด(๋ฐํ ์ด์ ) **์๋ฆฌ์ง ์๊ณ ๋์ด๊ฐ์ง ์๊ณ ๊ฒฝ๊ณ ํ๋ค** โ ๋ช
์ธ๋ฅผ
|
|
769
1014
|
* ์ ์ธํ๋๋ฐ ๋ฐ์๋์ง ์๋ ์ํ๋ฅผ ๋ชจ๋ฅด๊ณ ์ง๋๊ฐ๋ฉด, ์์ธก์ด ์์๋ก ๋์๊ฐ ๊ฒ์ ์๋ฌด๋ ์ ์ ์๋ค.
|
|
770
1015
|
*/
|
|
771
1016
|
static applyOperations(kernel, model, id) {
|
|
@@ -787,7 +1032,7 @@ class TwinEngine {
|
|
|
787
1032
|
kernel.declareDurations(declared);
|
|
788
1033
|
}
|
|
789
1034
|
catch (err) {
|
|
790
|
-
/* ์ปค๋์ด ๊ฑฐ์ ํ ๊ฐ์
|
|
1035
|
+
/* ์ปค๋์ด ๊ฑฐ์ ํ ๊ฐ์ ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค โ ํ๋ฉด์ ใ๋ฃ์์ต๋๋คใ๋ผ๊ณ ๋งํ ๊ฐ์ด๋ค. */
|
|
791
1036
|
(0, log_js_1.twinWarn)(`[twin-engine] "${id}": declared operation duration rejected by the kernel โ ${err?.message ?? err}`);
|
|
792
1037
|
}
|
|
793
1038
|
}
|
|
@@ -827,7 +1072,7 @@ class TwinEngine {
|
|
|
827
1072
|
* ๋ ๋ค ๋ชป ๋ง๋ค๋ฉด ์ฃผ์
ํ์ง ์๋๋ค โ ์ปค๋์ด ๋ช
์ธยท์์๋ก ๊ตด๋ฌ๊ฐ๊ณ `specCoverage()` ๊ฐ ๊ทธ ์ฌ์ค์ ๋จ๊ธด๋ค.
|
|
828
1073
|
*
|
|
829
1074
|
* ์ค์ธก์ DB ์กฐํ๋ผ ๋น๋๊ธฐ๋ค. ๊ทธ๋์ ์ด ํจ์๋ **await ํ์ง ์๋ ์ชฝ์์๋ ์์ **ํ๋๋ก ์คํจ๋ฅผ ์ผํค๋,
|
|
830
|
-
* ๋ฌด์์ ์ ๋ชป ๋ฃ์๋์ง๋ ๋ก๊ทธ๋ก ๋จ๊ธด๋ค(
|
|
1075
|
+
* ๋ฌด์์ ์ ๋ชป ๋ฃ์๋์ง๋ ๋ก๊ทธ๋ก ๋จ๊ธด๋ค(๋ค์ด์จ ๊ฒ์ด ์๋ ๋ฌดํจํ ๊ธ์ง).
|
|
831
1076
|
*/
|
|
832
1077
|
static async installEstimators(kernel, domainId, instanceId, model) {
|
|
833
1078
|
if (!kernel || typeof kernel !== 'object')
|
|
@@ -845,7 +1090,7 @@ class TwinEngine {
|
|
|
845
1090
|
/*
|
|
846
1091
|
* **์ํ๋ฅ ๋ ์ด๋ ฅ์์ ๋ฐฐ์ด๋ค** (2026-08-19) โ ์์์ ๊ฐ์ ์๋ฆฌ์์ ๋ถ์ธ๋ค.
|
|
847
1092
|
*
|
|
848
|
-
* ์ปค๋์ด ๊ทธ ์์์ ๊ฐ์ง ์์ ๋ฒ์ ์ด๋ฉด(๋ฐํ ์ด์ )
|
|
1093
|
+
* ์ปค๋์ด ๊ทธ ์์์ ๊ฐ์ง ์์ ๋ฒ์ ์ด๋ฉด(๋ฐํ ์ด์ ) ์๋ฆฌ์ง ์๊ณ ๋์ด๊ฐ์ง ์๊ณ ๋งํ๋ค: ์์จ์ด ์์๋ก ๋จ์
|
|
849
1094
|
* ์ด์ ๋ฅผ ๋ชจ๋ฅด๊ณ ์ง๋๊ฐ๋ฉด, ํ๋ฉด์ ๋ถ๋ ํ์ ์ด ๊ทธ ํ์ฅ์ ์ฌ์ค์ด ์๋๋ผ ์ฐ๋ฆฌ ์์์ ๊ฒฐ๊ณผ๋ค.
|
|
850
1095
|
*/
|
|
851
1096
|
const yields = await this.measuredYield(domainId, instanceId);
|
|
@@ -874,7 +1119,7 @@ class TwinEngine {
|
|
|
874
1119
|
`${travel.estimator ? `, travel from distance (speeds: ${Object.keys(travel.speedsByKind).join(',')})` : `, travel not derived (${travel.reasons.join('; ')})`}`);
|
|
875
1120
|
}
|
|
876
1121
|
/**
|
|
877
|
-
* ์ค์ธก ์ถ์ ๊ธฐ โ **์์ธก ์์ฒญ๋ง๋ค ์ ๋์ ๋ค์
|
|
1122
|
+
* ์ค์ธก ์ถ์ ๊ธฐ โ **์์ธก ์์ฒญ๋ง๋ค ์ ๋์ ๋ค์ ๊ณ์ฐํ์ง ์๋๋ค.**
|
|
878
1123
|
*
|
|
879
1124
|
* ์์ธก ์ปค๋์ ์์ฒญ๋ง๋ค ์๋ก ์ธ์์ง๊ณ (๋ฏธ๋ฌ ์์ธกยท๋ฐฑํ
์คํธ), ํ๋ฉด์ ์๊ฐ์ ๊ธ์ผ๋ฉด ๊ณ์ ์ฌ์์ธกํ๋ค.
|
|
880
1125
|
* ๊ฑฐ๊ธฐ์ KPI ์กฐํ๋ฅผ ๊ทธ๋๋ก ๋ฌ๋ฉด ์์ฒญ๋น ์ ๋ ์ค์บ์ด ํ๋์ฉ ๋ถ๋๋ค โ ์ค์ธก์ ๋ถ ๋จ์๋ก ๋ฐ๋์ง ์์ผ๋ฏ๋ก
|
|
@@ -893,10 +1138,10 @@ class TwinEngine {
|
|
|
893
1138
|
* ๋ค์ ๋ฃ์ผ๋ฏ๋ก). ๋ฒ๋ฆฌ๋ ๊ฒ์ด ์ํด๊ฐ ์๋ ์ด์ : ์ด ๊ฐ์ ์บ์์ด๊ณ , ์์ผ๋ฉด ๋ค์ ๊ณ์ฐํ๋ค.
|
|
894
1139
|
*
|
|
895
1140
|
* ์๋ฅผ ํฌ๊ฒ ์ก๋๋ค โ ํธ์ ๊ท๋ชจ๋ ๋ ํฌ๊ณ , ํญ๋ชฉ ํ๋๋ ์์
์ข
๋ฅ๋ณ ์์ ๋ช ์ค์ด๋ค. ์ํ์ด ์์ผ๋ฉด
|
|
896
|
-
* ์ ์ ๊ท๋ชจ์์ ์๋ก ๋ฐ์ด๋ด๋ฉฐ ์บ์๊ฐ ๋ฌด์๋ฏธํด์ง๋ค(๊ทธ๊ฒ ๋ ๋์๋ค:
|
|
1141
|
+
* ์ ์ ๊ท๋ชจ์์ ์๋ก ๋ฐ์ด๋ด๋ฉฐ ์บ์๊ฐ ๋ฌด์๋ฏธํด์ง๋ค(๊ทธ๊ฒ ๋ ๋์๋ค: ์๋ฆฌ์ง ์๊ณ ๋๋ ค์ง๋ค).
|
|
897
1142
|
*/
|
|
898
1143
|
static { this.MEASURED_MAX = 5_000; }
|
|
899
|
-
/** ์ด ํธ์์ด ์ด๋ ฅ์์ ๋ฐฐ์ด ์ํ๋ฅ โ ์์์ **๊ฐ์ ํด๋ยท๊ฐ์ ์บ์**์์ ์จ๋ค(์ ๋์ ๋ ๋ฒ
|
|
1144
|
+
/** ์ด ํธ์์ด ์ด๋ ฅ์์ ๋ฐฐ์ด ์ํ๋ฅ โ ์์์ **๊ฐ์ ํด๋ยท๊ฐ์ ์บ์**์์ ์จ๋ค(์ ๋์ ๋ ๋ฒ ๊ณ์ฐํ์ง ์๋๋ค). */
|
|
900
1145
|
static async measuredYield(domainId, instanceId) {
|
|
901
1146
|
await this.measuredEstimator(domainId, instanceId);
|
|
902
1147
|
return this.measuredCache.get((0, runtime_key_js_1.runtimeKey)(domainId, instanceId))?.yields;
|
|
@@ -913,7 +1158,7 @@ class TwinEngine {
|
|
|
913
1158
|
/* ์์
์ข
๋ฅ๋ณ ์ค์ธก โ ์ฐฝ์ ๋๋ํ(ํ๋ฃจ) ๋๊ณ ํ๋ณธ์ด ๋ชจ์๋ ์ข
๋ฅ๋ ์ถ์ ๊ธฐ๊ฐ ์ค์ค๋ก ๋บ๋ค. */
|
|
914
1159
|
const kpi = await (0, kpi_query_js_1.computeTwinKpi)({ domainId, instanceId, windowMinutes: 24 * 60, groupBy: 'taskKind' });
|
|
915
1160
|
value = (0, measured_estimator_js_1.buildMeasuredEstimator)(kpi?.groups?.items, {});
|
|
916
|
-
/* ๊ฐ์ ๊ทธ๋ฃน์์ ์ํ๋ฅ ๋ ๋ฐฐ์ด๋ค โ ํ ๋ฒ
|
|
1161
|
+
/* ๊ฐ์ ๊ทธ๋ฃน์์ ์ํ๋ฅ ๋ ๋ฐฐ์ด๋ค โ ํ ๋ฒ ๊ณ์ฐํ ์ ๋์ ๋์ด ๋๋ ์ด๋ค. */
|
|
917
1162
|
yields = (0, measured_yield_js_1.buildYieldEstimator)(kpi?.groups?.items, {});
|
|
918
1163
|
}
|
|
919
1164
|
catch (err) {
|
|
@@ -955,7 +1200,7 @@ class TwinEngine {
|
|
|
955
1200
|
}
|
|
956
1201
|
const plan = (0, declared_stimulus_js_1.planStimulus)(config, { hasScenarioEngine: !!inst.runtime?.scenario, mode: inst.mode }, validateScenario);
|
|
957
1202
|
if (plan.action === 'skip') {
|
|
958
|
-
/* ์ ์ธ์ด ์๋ ๊ฒ์ ์ ์์ด๋ฏ๋ก
|
|
1203
|
+
/* ์ ์ธ์ด ์๋ ๊ฒ์ ์ ์์ด๋ฏ๋ก ์๋ฆฌ์ง ์๊ณ ์ง๋๋ค. ๋๋จธ์ง ์
์ **๋งํ๋ค** โ ์ ์ธํ๋๋ฐ ์ ์ค๋ฆฐ ์ํ๋ค. */
|
|
959
1204
|
if (plan.reason !== 'none') {
|
|
960
1205
|
(0, log_js_1.twinWarn)(`[twin-engine] "${instanceId}": a stimulus is declared on its source but was not loaded (${plan.reason}${plan.detail ? `: ${plan.detail}` : ''}).` +
|
|
961
1206
|
(plan.reason === 'observed' ? ' This twin runs on observation โ we do not manufacture arrivals for it.' : ''));
|
|
@@ -1002,7 +1247,7 @@ class TwinEngine {
|
|
|
1002
1247
|
* ๋ณด์ฌ์ผ ํ๋ ํ๋ฉด์ด ์ ์ ๊ทธ๋ ์๋ฌด ๋ง๋ ๋ชป ํ๋ค.
|
|
1003
1248
|
*
|
|
1004
1249
|
* ๊ทธ ๋น์นธ์ ์ด๋ ฅ๋ก ๋ฉ์ด๋ค: ์ ๋์์ ๋ฐฐ์ด ์ข
๋ฅ๋ **์ถ์ ๊ธฐ๊ฐ ์ด๋ฏธ ๋ตํ ์ ์๋ ์ข
๋ฅ**์ด๋ฏ๋ก, ์ง์ด๋ด๋
|
|
1005
|
-
* ๊ฒ์ด ์๋๋ผ ์๋ ์ฌ์ค์ ๊บผ๋ด๋ ๊ฒ์ด๋ค. ๊ฐ์ ์บ์(60์ด)๋ฅผ ์ฐ๋ฏ๋ก ์กฐํ๋ง๋ค ์ ๋์ ๋ค์
|
|
1250
|
+
* ๊ฒ์ด ์๋๋ผ ์๋ ์ฌ์ค์ ๊บผ๋ด๋ ๊ฒ์ด๋ค. ๊ฐ์ ์บ์(60์ด)๋ฅผ ์ฐ๋ฏ๋ก ์กฐํ๋ง๋ค ์ ๋์ ๋ค์ ๊ณ์ฐํ์ง ์๋๋ค.
|
|
1006
1251
|
*/
|
|
1007
1252
|
static async measuredOperationKinds(domainId, instanceId) {
|
|
1008
1253
|
const measured = await this.measuredEstimator(domainId, instanceId);
|
|
@@ -1030,7 +1275,7 @@ class TwinEngine {
|
|
|
1030
1275
|
*
|
|
1031
1276
|
* ๊ณ์ฐ์ ์ปค๋์ด ์๊ธฐ ์ํ์์ ํ๋ค(`kernel.capacity`). ์ฌ๊ธฐ์ ํ๋ ์ผ์ **๊ธฐ์ค ์ฃผ๋ฅผ ์ ํด ์ฃผ๋
|
|
1032
1277
|
* ๊ฒ**๋ฟ์ด๋ค: ๊ณตํด์ผ์ด ์๋ ํ์์ฃผ์ฌ์ผ ํ๋ค โ ๊ณตํด์ผ์ ์ฐ๊ฐ ๊ฐ์ฉ๋์ ๋ฐ๋ก ๊น์ง, ์ด ๊ณต์ฅ์ ํ์์
|
|
1033
|
-
* ์ํ์ ์ ํ์ง ์๋๋ค. ์ปค๋์ด ์์๋ก ๊ณ ๋ฅด๊ฒ ๋๋ฉด ๊ทธ ์ฃผ์ ๊ณตํด์ผ์ด ๋ผ์์ ๋ ์ํ์ด
|
|
1278
|
+
* ์ํ์ ์ ํ์ง ์๋๋ค. ์ปค๋์ด ์์๋ก ๊ณ ๋ฅด๊ฒ ๋๋ฉด ๊ทธ ์ฃผ์ ๊ณตํด์ผ์ด ๋ผ์์ ๋ ์ํ์ด ์๋ฆฌ์ง ์๊ณ ๋ฎ์์ง๋ค.
|
|
1034
1279
|
*
|
|
1035
1280
|
* ํธ์์ด ๊ธฐ๋ ์ค์ด ์๋๋ฉด `undefined` ๋ค โ 0 ์ด ์๋๋ค. ๊ธฐ๋ํ์ง ์์ ํธ์์ ์ํ์ 0 ์ด๋ผ๊ณ ๋ตํ๋ฉด ํ๋ฉด์
|
|
1036
1281
|
* "์ด ๊ณต์ฅ์ ์๋ฌด๊ฒ๋ ๋ชป ๋ง๋ ๋ค" ๊ณ ๋งํ๋ค.
|
|
@@ -1085,7 +1330,7 @@ class TwinEngine {
|
|
|
1085
1330
|
});
|
|
1086
1331
|
}
|
|
1087
1332
|
/**
|
|
1088
|
-
* ๋ฏธ๋ฌ ๊ธฐ๋์ ์ฐ์์ฑ ์จ์ โ ์ด์ด๋ฐ์ ๊ฒ์ **๋งํ๋ค**(
|
|
1333
|
+
* ๋ฏธ๋ฌ ๊ธฐ๋์ ์ฐ์์ฑ ์จ์ โ ์ด์ด๋ฐ์ ๊ฒ์ **๋งํ๋ค**(์๋ฆฌ์ง ์๊ณ ์์ง ์๋๋ค).
|
|
1089
1334
|
*
|
|
1090
1335
|
* ์ปค๋์ด ๊ทธ ๋ฌธ์ ์ด์ด ๋์ง ์์์ผ๋ฉด ๊ทธ ์ฌ์ค๋ ๋งํ๋ค: ๊ทธ ํธ์์ ์ฌ๊ธฐ๋๋ง๋ค ์ด๋ฆฐ ๊ตฌ๊ฐ์ ์๋๋ค.
|
|
1091
1336
|
*/
|
|
@@ -1122,6 +1367,7 @@ class TwinEngine {
|
|
|
1122
1367
|
return this.instances[key];
|
|
1123
1368
|
const Kernel = kernelFor(kind);
|
|
1124
1369
|
const kernel = new Kernel(domainId, undefined, this.productionSpecOf(model));
|
|
1370
|
+
kernel.scopeId = id;
|
|
1125
1371
|
kernel.loadTwinModel(model); // ๊ตฌ์กฐ๋ง. ์ํ๋ ์๋ ์์คํํธ๊ฐ ์ฃผ์
ํ๋ค.
|
|
1126
1372
|
this.applyOperations(kernel, model, id); // ์๊ฐยท์์จ ๋ช
์ธ(์์ผ๋ฉด) โ ์์ผ๋ฉด ์ปค๋ ๊ธฐ๋ณธ๊ฐ
|
|
1127
1373
|
/* ์ถ์ ๊ธฐ๋ DB ์กฐํ๋ฅผ ํฌํจํด ๋น๋๊ธฐ โ ๊ธฐ๋์ ๋ง์ง ์๊ณ ๋ถ๋๋ค(๋ถ๊ธฐ ์ ์์
์ ๋ช
์ธยท์์๋ก ์ฐ์ถ). */
|
|
@@ -1173,6 +1419,7 @@ class TwinEngine {
|
|
|
1173
1419
|
/* ์ ์ฑ
์ ๋ถ๋ฅด๋ ์ชฝ์ด ์ ์ธํ๋ค โ ์ฌ๊ธฐ์ ๊ณ ๋ฅด๋ฉด ๊ฐ์ ํธ์์ด ๋ถ๋ฅด๋ ์๋ฆฌ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ฌ๊ธฐ๋ํ๋ค. */
|
|
1174
1420
|
restartPolicy: (0, restart_policy_js_1.readRestartPolicy)(restartPolicy, `start("${id}")`),
|
|
1175
1421
|
spaceId: model?.spaceId,
|
|
1422
|
+
model,
|
|
1176
1423
|
/*
|
|
1177
1424
|
* **์๋ฎฌ๋ ๊ณ๊ธฐ๋ฅผ ๋ ๋ค** (2026-08-20).
|
|
1178
1425
|
*
|
|
@@ -1213,7 +1460,7 @@ class TwinEngine {
|
|
|
1213
1460
|
* ๊ฒ์ ์๋ฎฌ๋ง ์๋ฌธ์ผ๋ก ๋ค์ด์ค๊ธฐ ๋๋ฌธ"* ์ด๋ผ ์๊ณ ํ ๊ทธ ์๋ฆฌ๋ค.
|
|
1214
1461
|
*
|
|
1215
1462
|
* **๋ฆฌ๋น์ ์ ์ปค๋์ ๊ฒ์ ๊ทธ๋๋ก ๋ ๋ค**(๋ผ์ด๋ธ๋ flush ๋ ํธ์คํธ๊ฐ ๋ถ์ฌํ๋ค). ์๋ฎฌ์ ์ ๋์
|
|
1216
|
-
* ์ปค๋ ๋ฆฌ๋น์ ์ผ๋ก
|
|
1463
|
+
* ์ปค๋ ๋ฆฌ๋น์ ์ผ๋ก ๋ฒํธ๊ฐ ์ ํด์ง๋ฏ๋ก ์ฌ๊ธฐ์ ๋ค์ ๋ฒํธ๋ฅผ ๋งค๊ธฐ๋ฉด ์๊ฐ์ฌํ์ด ์ด๊ธ๋๋ค.
|
|
1217
1464
|
*/
|
|
1218
1465
|
;
|
|
1219
1466
|
(inst.pendingJournal ?? (inst.pendingJournal = [])).push({ event: msg.event, revision: msg.revision });
|
|
@@ -1251,7 +1498,7 @@ class TwinEngine {
|
|
|
1251
1498
|
* ์ค์ค์ด ์๊ฒผ๋ค: ์์ธกํ๋ ค๋ฉด ์์ ์ปค๋์ ์ธ์์ผ ํ๊ณ (`buildForecastKernel`), ์ฃผ๋ชฉ ์ ํธ๋ฅผ ํธ์คํธ๊ฐ
|
|
1252
1499
|
* ๋ง๋ถ์ฌ์ผ ํ๊ณ (`withLiveAttentions`), AI ์์ธก ๋๊ตฌ๋ ๋ฏธ๋ฌ์์ "์ฐพ์ ์ ์๋ค" ๋ก ๋๋ฌ๋ค.
|
|
1253
1500
|
*
|
|
1254
|
-
* ์ด์ ๋ผ์ด๋ธ ์ธ์คํด์ค๋ **์ปค๋์ด๋ค.** ๊ฐ์ ๊ท์น(`ObservedReducer`)์ผ๋ก ์ด๋ฒคํธ๋ฅผ
|
|
1501
|
+
* ์ด์ ๋ผ์ด๋ธ ์ธ์คํด์ค๋ **์ปค๋์ด๋ค.** ๊ฐ์ ๊ท์น(`ObservedReducer`)์ผ๋ก ์ด๋ฒคํธ๋ฅผ ๊ณ์ฐํ๊ณ , ์ฃผ๋ชฉ ์ ํธ๋ฅผ
|
|
1255
1502
|
* ์ค์ค๋ก ๋ด๊ณ , ๊ทธ ์๋ฆฌ์์ `fork` ํด ์์ธกํ๋ค. ๊ตฌ๋๋ง ๋ค๋ฅด๋ค โ sim ์ `tick`, live ๋ `apply`.
|
|
1256
1503
|
*
|
|
1257
1504
|
* ์ค ์ด๋ฒคํธ์ = reference ์ด๋ํฐ openLiveFeed โ face2-adapter.ingest โ CanonicalEnvelope โ ingestLive().
|
|
@@ -1273,7 +1520,7 @@ class TwinEngine {
|
|
|
1273
1520
|
* ์ด๋ฆ์ด ๊ทธ๋๋ก ๊ตณ์ ๊ฒ), ์ผ๋ฐ ๊ธฐ์ ์ ํ ์์คํ
์ด๋ฆ์ด ๋ถ์ด ์์๊ธฐ ๋๋ฌธ์ ์ฐฝ๊ณ ํธ์์ด ์ด ์๋ฆฌ๋ฅผ
|
|
1274
1521
|
* ์ฐ์ง ๋ชปํ๋ค. ๋ณ๋ช
์ผ๋ก ๋จ๊ฒจ ๋๋ฉด ๊ทธ ํผ๋์ด ๊ณ์๋๋ฏ๋ก ํ๋๋ก ํต์ผํ๋ค.
|
|
1275
1522
|
*
|
|
1276
|
-
* ์ ์ด๋ฆ๋ง ๊ฐ์ง ๋ชจ๋ธ์ด ์์ผ๋ฉด
|
|
1523
|
+
* ์ ์ด๋ฆ๋ง ๊ฐ์ง ๋ชจ๋ธ์ด ์์ผ๋ฉด **์๋ฆฌ์ง ์๊ณ ์์ฐ ์ ์ธ์ ์๋ ๋์ ๋ถ๋ช
ํ ๋ฉ์ถ๋ค** โ ๊ทธ ํธ์์ ๊ณต์ ์ด
|
|
1277
1524
|
* ์๋ ์ฑ๋ก ๋๊ฒ ๋๊ณ (๋ผ์ธ์ด ์ ์๋ ์ฐฝ๊ณ ), ์์ธ์ ์ฐพ๊ธฐ ์ด๋ ต๋ค.
|
|
1278
1525
|
*/
|
|
1279
1526
|
static productionSpecOf(model) {
|
|
@@ -1314,6 +1561,7 @@ class TwinEngine {
|
|
|
1314
1561
|
return this.instances[key];
|
|
1315
1562
|
const Kernel = kernelFor(kind);
|
|
1316
1563
|
const kernel = new Kernel(domainId, undefined, this.productionSpecOf(model));
|
|
1564
|
+
kernel.scopeId = id;
|
|
1317
1565
|
kernel.loadTwinModel(model);
|
|
1318
1566
|
/* **์ธ์ฐ๋ ์ชฝ์ด ์๋ ์ฌ์ค์ ์ธ์ธ ๋ ๋งํ๋ค.** ์์ ์๋ ์ฒซ ์ด๋ฒคํธ๊ฐ ๋์ฐฉํด์ผ ์ปค๋์ด ์ค์ค๋ก๋ฅผ
|
|
1319
1567
|
๊ด์ธก ๊ตฌ๋์ผ๋ก ์ฌ๊ฒผ๊ณ , ๊ทธ๋์ ์์ง ์๋ฌด๊ฒ๋ ๋ชป ๋ฐ์ ๋ฏธ๋ฌ๋ ์๋ฎฌ๋ ์ด์
์ทจ๊ธ์ ๋ฐ์๋ค. */
|
|
@@ -1322,11 +1570,11 @@ class TwinEngine {
|
|
|
1322
1570
|
/* `projector` ํ๋๋ ์ ์ด๋ฆ์ผ๋ก ๋จ๊ธด๋ค โ ์๋น์ฒ๊ฐ `snapshot()` ์ ๋ถ๋ฅด๋ฏ๋ก ์์ ์ด๋ํฐ๋ก ์๋๋ค.
|
|
1323
1571
|
* (P3 ์์ ์๋น์ฒ๋ฅผ ์ปค๋ ์ดํ๋ก ๋ฐ๊พธ๋ฉด ์ฌ๋ผ์ง๋ค.) */
|
|
1324
1572
|
const projector = { apply: (e) => kernel.apply(e), snapshot: () => kernel.getSnapshot() };
|
|
1325
|
-
const inst = { id, domainId, mode: 'live', restartPolicy: 'resync', kernel, projector, oee: new oee_accumulator_js_1.OeeAccumulator(), spaceId: model?.spaceId, unsub: () => { } };
|
|
1573
|
+
const inst = { id, domainId, mode: 'live', restartPolicy: 'resync', kernel, projector, oee: new oee_accumulator_js_1.OeeAccumulator(), spaceId: model?.spaceId, model, unsub: () => { } };
|
|
1326
1574
|
/*
|
|
1327
1575
|
* โโ ์ปค๋์ด **ํ์ ์ผ๋ก ๋ธ ์ฌ์ค**๋ ์ ๋์ ๋จ๋๋ค (2026-08-14 ์ค์ธก์ผ๋ก ์ก์) โโโโ
|
|
1328
1576
|
*
|
|
1329
|
-
* ๋ผ์ด๋ธ๋ ์ธ์
๋ดํฌ๋ง ์ ๋์ ์ ๊ณ ์์๋ค(`ingestLive`). ๊ทธ๋ฐ๋ฐ ์ปค๋์ ๊ด์ธก์
|
|
1577
|
+
* ๋ผ์ด๋ธ๋ ์ธ์
๋ดํฌ๋ง ์ ๋์ ์ ๊ณ ์์๋ค(`ingestLive`). ๊ทธ๋ฐ๋ฐ ์ปค๋์ ๊ด์ธก์ ๊ณ์ฐํ๋ค๊ฐ **์๊ธฐ ์ฌ์ค**์
|
|
1330
1578
|
* ๋ธ๋ค โ ์๋์ง์ ์์ ๊ตฌ๊ฐ ๋ง๊ฐยทํผํฌ ๊ฒฝ์ ยท๊ฐ์ถ ์ ์์ด ๊ทธ๋ ๋ค(`emitOp`). ๊ทธ๊ฒ์ ๊ตฌ๋
ํ๋ ๊ณณ์ด
|
|
1331
1579
|
* ์์ด์ ๊ทธ ์ฌ์ค๋ค์ด **์ปค๋ ์์์ ์ฌ๋ผ์ก๋ค**: ํ๋ณธ 48๊ฑด์ด ์ ๋์ ์์๋๋ฐ ๊ตฌ๊ฐ ๋ง๊ฐ์ 0๊ฑด์ด์๊ณ ,
|
|
1332
1580
|
* ์ ๋์ ์ฝ๋ ์ฑ๊ณผ ํ๋ฉด์ ์ ๋ ฅ ํ์ผ์ ์์ํ ๋์ค์ง ์์๋ค.
|
|
@@ -1353,7 +1601,7 @@ class TwinEngine {
|
|
|
1353
1601
|
this.installEstimators(kernel, domainId, id, model).catch(err => (0, log_js_1.twinWarn)('[twin-engine] estimator install failed', err?.message));
|
|
1354
1602
|
inst.metrics = this.newMetrics();
|
|
1355
1603
|
this.instances[key] = inst;
|
|
1356
|
-
/* ๋ฏธ๋ฌ์๋ ๋ถ๋ฅธ๋ค โ ์ ์ธ์ด ์์ผ๋ฉด ใ๋ฏธ๋ฌ์๋ ์ฃ์ง ์๋๋คใ๊ณ ๋งํด์ผ ํ๋ค(
|
|
1604
|
+
/* ๋ฏธ๋ฌ์๋ ๋ถ๋ฅธ๋ค โ ์ ์ธ์ด ์์ผ๋ฉด ใ๋ฏธ๋ฌ์๋ ์ฃ์ง ์๋๋คใ๊ณ ๋งํด์ผ ํ๋ค(๋ค์ด์จ ๊ฒ์ด ์๋ ๋ฌด์ ๊ธ์ง). */
|
|
1357
1605
|
this.installStimulus(domainId, id, inst).catch(err => (0, log_js_1.twinWarn)(`[twin-engine] "${id}": stimulus check failed โ ${err?.message ?? err}`));
|
|
1358
1606
|
/*
|
|
1359
1607
|
* **์์ฒ์ด ๋ํ์ด ์ฃผ์ง ์๋ ๊ฒ๋ง ์๋๋ค** (2026-08-18 ์ค์ธก์ผ๋ก ๋ถ์).
|
|
@@ -1374,11 +1622,11 @@ class TwinEngine {
|
|
|
1374
1622
|
* ์ ์ ์ด ์ค์ง ์๋๋ค: ์ปค์๊ฐ ๋ฐ๋ผ์กํ ๋ค ์๋ณธ์ด ๋ณํ์ง ์์ผ๋ฉด ๋ฏธ๋ฌ๋ ์๊ตฌํ ๋น ์ฑ๋ก ๋จ๋๋ค.
|
|
1375
1623
|
* ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋น ์ฑ๋ก ํ๋ฉด์ด ใ์ด์ ์์ใ์ ๋ณด์๋ค โ ์ฌ์ค์ด ์ฌ๋ผ์ง๋ ๋์ ํ๋ฉด์ด ์์ฌ์ํจ ๊ฒ์ด๋ค.
|
|
1376
1624
|
*
|
|
1377
|
-
* ๋๋๋ฆฌ๋ ๊ฒ์ **์ํ๊ฐ ์๋๋ผ ์ฌ๊ฐ์ **์ด๋ค. ์ํ๋ง ์ฌ์ผ๋ฉด ๊ทธ ๋ค๋ฅผ ์ด์ด
|
|
1378
|
-
* ๊ฒฐ๊ณผ์
|
|
1379
|
-
* ์ฆ๋ช
ํ๋ค(`observed-checkpoint.test.ts` โ ์ฌ๊ฐ์ + ๊ผฌ๋ฆฌ == 0๋ถํฐ
|
|
1625
|
+
* ๋๋๋ฆฌ๋ ๊ฒ์ **์ํ๊ฐ ์๋๋ผ ์ฌ๊ฐ์ **์ด๋ค. ์ํ๋ง ์ฌ์ผ๋ฉด ๊ทธ ๋ค๋ฅผ ์ด์ด ๊ณ์ฐํ ๊ฒฐ๊ณผ๊ฐ 0๋ถํฐ ๊ณ์ฐํ
|
|
1626
|
+
* ๊ฒฐ๊ณผ์ ์ค๋ฅ ์์ด ๋ฌ๋ผ์ง๋ค(๋ฆฌ๋์๋ ๋ณด๋ฅ๋ ๋ด๊นยท์ง๊ณ ์ค์ธ ์๋๋ ๋ ๋ค). ๊ทธ ๋์น๋ ์ปค๋ ์ํ์ด
|
|
1627
|
+
* ์ฆ๋ช
ํ๋ค(`observed-checkpoint.test.ts` โ ์ฌ๊ฐ์ + ๊ผฌ๋ฆฌ == 0๋ถํฐ ๊ณ์ฐํ๊ธฐ).
|
|
1380
1628
|
*
|
|
1381
|
-
* ์จ์์ **๊ทธ ๊ณต์ฅ์ด ์์ง ๊ทธ ๊ณต์ฅ์ผ ๋๋ง** ์ค๊ณ , ๋ง์ง๋ง ์ฒดํฌํฌ์ธํธ ์ดํ์ ์ฌ์ค์ ์ด๋ฏธ
|
|
1629
|
+
* ์จ์์ **๊ทธ ๊ณต์ฅ์ด ์์ง ๊ทธ ๊ณต์ฅ์ผ ๋๋ง** ์ค๊ณ , ๋ง์ง๋ง ์ฒดํฌํฌ์ธํธ ์ดํ์ ์ฌ์ค์ ์ด๋ฏธ ๊ณ์ฐ๋์ด ๋ค์ด
|
|
1382
1630
|
* ์๋ค(`warmSeedFor`). ์จ์์ด ์์ผ๋ฉด ์ ๊ณผ ๊ฐ์ด ๋น ์ฑ๋ก ์์ํ๋ค โ ์ง์ด๋ด์ง ์๋๋ค.
|
|
1383
1631
|
*/
|
|
1384
1632
|
const seed = this.recovered[key]?.fold?.reducer;
|
|
@@ -1428,10 +1676,19 @@ class TwinEngine {
|
|
|
1428
1676
|
* ๋น๋๊ธฐ๋ผ ๊ทธ ์ฌ์ด์ ์ด๋ฒคํธ๊ฐ ๋ช ๊ฑด ๋ค์ด์ ์์ ์ ์๋๋ฐ, ๊ทธ๋ ๋ค๋ก ๋๋๋ฆฌ๋ ๊ฒ์ ์ปค๋์ด ๊ฑฐ์ ํ๋ค
|
|
1429
1677
|
* (๊ฒน์น๋ ๋ฒํธ๋ฅผ ๋ง๋ ๊ทธ ํ์ ์ด๋ค). ๊ฑฐ์ ์ ์ผํค์ง ์๊ณ ๋จ๊ธด๋ค.
|
|
1430
1678
|
*/
|
|
1679
|
+
/*
|
|
1680
|
+
* ๊ด๊ณ๋ก ๋ฌป์ง ์๋๋ค โ `findOne({ where: { domain: { id } } })` ์ ๋ ๋จ๊ณ ์ง์๊ฐ ๋๊ณ ์์ชฝ์
|
|
1681
|
+
* ์ํ์ด ์์ด ๊ทธ ํธ์์ ์ ๋์ **์ ๋ถ ๋ง๋ ๋ค** ํ ์ค์ ๊ณ ๋ฅธ๋ค(ยง`tipOf` ์ ์ค์ธก). ์ฌ๊ธฐ๋ ๋ถํ
|
|
1682
|
+
* ๊ฒฝ๋ก์ด๋ฏ๋ก ๊ทธ ๋น์ฉ์ด ๊ธฐ๋์ ๋ถ์ก๋๋ค. ์์ธ์ ๋ ํ ์ค๋ง ์ฝ๋๋ค.
|
|
1683
|
+
*/
|
|
1431
1684
|
(0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
1432
|
-
.
|
|
1685
|
+
.createQueryBuilder('e')
|
|
1686
|
+
.select('MAX(e.revision)', 'max')
|
|
1687
|
+
.where('e.domain = :domainId', { domainId })
|
|
1688
|
+
.andWhere('e.instanceId = :instanceId', { instanceId: id })
|
|
1689
|
+
.getRawOne()
|
|
1433
1690
|
.then(top => {
|
|
1434
|
-
const head = top?.
|
|
1691
|
+
const head = Number(top?.max) || 0;
|
|
1435
1692
|
inst.revision = head;
|
|
1436
1693
|
if (!head || typeof kernel.resumeRevision !== 'function')
|
|
1437
1694
|
return;
|
|
@@ -1455,18 +1712,107 @@ class TwinEngine {
|
|
|
1455
1712
|
*
|
|
1456
1713
|
* โโ ๋ฃ์ ์๋ฅผ **๋ตํ๋ค** (2026-08-20) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1457
1714
|
* ํธ์์ด ๋ผ์ด๋ธ๋ก ๋์ง ์์ผ๋ฉด ์ฌ๊ธฐ์ ๋ดํฌ๋ฅผ ๋ฒ๋ฆฐ๋ค. ๊ทธ๊ฒ ์์ฒด๋ ๋ง๋ค(๋ฃ์ ์ปค๋์ด ์๋ค). ๋ฌธ์ ๋
|
|
1458
|
-
*
|
|
1715
|
+
* **์๋ฆฌ์ง ์๊ณ ** ๋ฒ๋ฆฐ ๊ฒ์ด์๋ค: ํธ์์ด ๋ฉ์ถ ๋ค์๋ ํผ๋๋ ๋จ์ ๋ ์ฝ๋๋ฅผ ๋๋ฅด๊ณ , ์ ์
์ฅ๋ถ๋ ๊ทธ๊ฒ์
|
|
1459
1716
|
* ใํต๊ณผใ๋ก ์
๋ค. ํ๋ฉด์ ๋ฉ์ถ ํธ์ ์์ ใ150 ํต๊ณผ ยท 100%ใ๋ผ๊ณ ์ ์๋ค โ ์ฌ์ค์ด ์ฌ๋ผ์ง๋ ๋์
|
|
1460
1717
|
* ํ๋ฉด์ด ์์ฌ์ํจ ๊ฒ์ด๋ค.
|
|
1461
1718
|
*
|
|
1462
1719
|
* ๊ทธ๋์ **๋ฃ์ ์๋ฅผ ๋๋ ค์ค๋ค.** ๋ถ๋ฅด๋ ์ชฝ์ด ์ ์ ์์ ๊ฒฌ์ฃผ์ด ๋ฒ๋ ค์ง ์๋ฅผ ์ฅ๋ถ์ ์ ๋๋ค. ๋ฐํ์
|
|
1463
1720
|
* ๋ฌด์ํ๋ ํธ์ถ๋ถ๋ ๊ทธ๋๋ก ๋์ํ๋ค(์ ๊ณผ ๊ฐ๋ค).
|
|
1464
1721
|
*/
|
|
1465
|
-
|
|
1722
|
+
/**
|
|
1723
|
+
* ์ ์
๊ฒฐ๊ณผ๋ฅผ ์๋ก ๋ธ๋ค โ ๋ฐ์ ์ ยท ์ค๋ณต์ผ๋ก ๋ฒ๋ฆฐ ์ ยท ๋ณด๋ธ ์.
|
|
1724
|
+
*
|
|
1725
|
+
* `ingestLive` ๋ ๋ฐ์ ์๋ง ๋๋ ค์ฃผ๋๋ฐ, ์นํ
์ผ๋ก ๋ฐ์ ๋๋ **๋ช ๊ฑด์ด ์ค๋ณต์ด์๋์ง๋ ๋ตํด์ผ** ํ๋ค.
|
|
1726
|
+
* ๋ฐ์ด ์ฃผ๋ ์ชฝ์ด ๊ทธ ์๋ฅผ ๋ณด๊ณ ์๊ธฐ๊ฐ ๋ํ์ด ๋ณด๋ด๊ณ ์๋ค๋ ๊ฒ์ ์ ์ ์์ด์ผ ํ๊ณ , ๊ทธ๊ฒ์ ๋ชจ๋ฅด๋ฉด
|
|
1727
|
+
* ์ฐ๋ฆฌ ์๋ต์ด ใ์ ๋ถ ์ ๊ฒ์ด์๋คใ๋ก ์ฝํ๋ค.
|
|
1728
|
+
*/
|
|
1729
|
+
static ingestLiveResult(domainId, id, envelopes, source = 'poll') {
|
|
1730
|
+
const before = this.ingestLedgers[(0, runtime_key_js_1.runtimeKey)(domainId, id)]?.duplicates ?? 0;
|
|
1731
|
+
const offered = envelopes.length;
|
|
1732
|
+
const applied = this.ingestLive(domainId, id, envelopes, source);
|
|
1733
|
+
const after = this.ingestLedgers[(0, runtime_key_js_1.runtimeKey)(domainId, id)]?.duplicates ?? 0;
|
|
1734
|
+
return { offered, applied, duplicates: Math.max(0, after - before) };
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* **๋ง์คํฐ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋๋ค** โ ๋ณํ์ง ์๋ ์์ฑ์ ์ํ์ ์ธ์ด๋ค. ์ ๋์ ์ ์ง ์๋๋ค.
|
|
1738
|
+
*
|
|
1739
|
+
* โโ ์ ์ ๋์ ์ ์ง ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1740
|
+
* ์ ํต๊ธฐํยท๋กํธ๋ฒํธ ๊ฐ์ ๊ฐ์ ๊ทธ ๋ฌผ๊ฑด์ ์์ ๋์ ๊ฐ๋ค. ๊ทธ๋์ ใ๊ทธ๋๋ ์ผ๋ง์๋ใ๋ผ๋ ๋ฌผ์์ด
|
|
1741
|
+
* ์ฑ๋ฆฝํ์ง ์๋๋ค โ ์๊ฐ์ถ์ด ์๋ ๊ฐ์ด๋ฏ๋ก ์ฌ๊ฑด์ด ์๋๋ค. ๋์ธ์ธ ๊ทผ๊ฑฐ๋ ์ค๊ฐ ์ ์ฅ๋ณธ์ด ๋ ๋ค
|
|
1742
|
+
* (๋ฆฌ๋์๊ฐ ๊ทธ ๊ฐ์ ์ ์ฅ๋ณธ์ ๋ด๋๋ค).
|
|
1743
|
+
*
|
|
1744
|
+
* โโ ์ด ๋ฌธ์ด ์์ด์ ๋ฌด์์ด ๋ฌ๋ (2026-08-28 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1745
|
+
* ํ์ค์ ๊ทธ ๊ฐ์ `ObjectEvent(action=ADD)` ์๋ง ์ค์ ์ ์๊ฒ ํ๋ค. ๊ทธ๋์ ์ ๋์ ์ฝ๋ ์๋ณธ์ด
|
|
1746
|
+
* ์ฌ๊ณ ๋ฅผ ๋ค์ ๋งํ ๋๋ง๋ค **๋ค์ด์ค์ง ์์ ๊ฒ์ ใ๋ค์ด์๋คใ** ๊ณ ํ๊ณ , ์ฌ๊ฑด ๋จ์ ๊ฐ์ด๋ผ ์๋ฆฌ๋ณ๋ก
|
|
1747
|
+
* ๋ฌถ์ ์๋ ์์ด ๋ฑ๊ฐ๋ก ๋๊ฐ๋ค โ ์ฌ๊ธฐ๋ ํ ๋ฒ์ 2,665๊ฑด์ด ใ์ฝ์ ์๊ฐใ์ผ๋ก ์์๋ค.
|
|
1748
|
+
*
|
|
1749
|
+
* ๋๋ ค์ฃผ๋ ์๋ **์ํ์ ๋ฐ์๋ ๊ฑด์**๋ค. ๋ผ์ด๋ธ๋ก ๋์ง ์๋ ํธ์์ 0 ์ ๋ธ๋ค โ ๊ทธ ์ฐจ์ด๋ฅผ ๋ถ๋ฅด๋
|
|
1750
|
+
* ์ชฝ์ด ์์์ผ ํ๋ค(๋ฒ๋ ค์ง ๊ฒ์ ํต๊ณผ๋ก ์ธ๋ฉด ๋ฉ์ถ ํธ์์ด ์ ์์ผ๋ก ๋ณด์ธ๋ค).
|
|
1751
|
+
*
|
|
1752
|
+
* ์ค๊ณ: `operato-twin/design/plans/master-data.md`
|
|
1753
|
+
*/
|
|
1754
|
+
static applyMasterData(domainId, id, elements) {
|
|
1755
|
+
if (!elements.length)
|
|
1756
|
+
return 0;
|
|
1757
|
+
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, id)];
|
|
1758
|
+
if (inst?.mode !== 'live' || !inst.kernel)
|
|
1759
|
+
return 0;
|
|
1760
|
+
const kernel = inst.kernel;
|
|
1761
|
+
if (typeof kernel.applyMasterData !== 'function') {
|
|
1762
|
+
(0, log_js_1.twinWarn)(`[twin-engine] kernel for "${id}" cannot take master data (no applyMasterData) โ ` +
|
|
1763
|
+
'lot attributes such as expiry will stay empty for this twin.');
|
|
1764
|
+
return 0;
|
|
1765
|
+
}
|
|
1766
|
+
const n = kernel.applyMasterData(elements);
|
|
1767
|
+
/*
|
|
1768
|
+
* **๋์๋ค๋ ๊ฒ์ ๋ก๊ทธ๋ก ๋จ๊ธด๋ค** (2026-08-28).
|
|
1769
|
+
*
|
|
1770
|
+
* ์ด ๊ฐ์ ์ง๋ ๊ธฐ๋ก์ ์ ํ์ง ์์ผ๋ฏ๋ก(์๊ฐ์ถ์ด ์๋ค) ์ธ์ง ์์ผ๋ฉด ์ด ํต๋ก๊ฐ ๋์๋์ง ์๋ฌด ๋ฐ๋
|
|
1771
|
+
* ๋จ์ง ์๋๋ค. ์ฒ์์๋ ์ ์
์ฅ๋ถ์ ์๋ฅผ ๋ํ๋๋ฐ **๊ทธ๊ฒ์ด ํธ๋ฒ์ด์๋ค**: ์ ์
์ฅ๋ถ๋ ใ์๋ณธ์์
|
|
1772
|
+
* ์ฌ์ค์ด ์ผ๋ง๋ ๋ค์ด์ค๊ณ ๊ฑฐ๋ถ๋๊ณ ๋ฒ๋ ค์ง๋ใ๋ฅผ ๋ตํ๋ ์๋ฆฌ์ด๊ณ , ๋ง์คํฐ๋ฐ์ดํฐ๋ ์ฌ์ค์ ํ๋ฆ์ด ์๋๋ผ
|
|
1773
|
+
* ์ ์ธ์ ๋๊ธฐ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์๋ฅผ ์ฝ๋ ํ๋ฉด์ด ์์๋ค โ ๋ด๊ฐ ํ์ธํ๋ ค๊ณ ๋ง๋ ๊ฐ์ด์๋ค.
|
|
1774
|
+
*
|
|
1775
|
+
* ํ์ธ์ **๋ก๊ทธ์ ์ผ**์ด๋ค. ์ ์ ์ํ์์๋ ์ด ์ค์ด ์ ๋์ค๋ ๊ฒ์ด ๋ง๋ค โ ๊ฐ์ด ๊ทธ๋๋ก๋ฉด ์๋ณธ์ด
|
|
1776
|
+
* ๋ค์ ๋งํ์ง ์๋๋ค. ๋์ค๋ฉด ๊ทธ๋๊ฐ ๋ฌด์ธ๊ฐ ๋ฐ๋ ๋๋ค.
|
|
1777
|
+
*/
|
|
1778
|
+
if (n > 0)
|
|
1779
|
+
(0, log_js_1.twinLog)(`[twin-engine] "${id}": ๋ง์คํฐ๋ฐ์ดํฐ ${n}๊ฑด์ ์ํ์ ์ธ์ ๋ค(์ง๋ ๊ธฐ๋ก์๋ ์ ์ง ์๋๋ค).`);
|
|
1780
|
+
/* ์ํ๊ฐ ๋ฐ๋์์ผ๋ ๋ค์ ์ฐฝ์์ ํ๋ฉด์ผ๋ก ํ๋ฌ์ผ ํ๋ค โ ๊ด์ธก ๋ฐ์๊ณผ ๊ฐ์ ๊ท์จ์ด๋ค. */
|
|
1781
|
+
inst.dirty = true;
|
|
1782
|
+
this.ensureBroadcastCoalescer();
|
|
1783
|
+
return n;
|
|
1784
|
+
}
|
|
1785
|
+
static ingestLive(domainId, id, envelopes, source = 'poll') {
|
|
1466
1786
|
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, id)];
|
|
1467
1787
|
if (inst?.mode !== 'live' || !inst.projector)
|
|
1468
1788
|
return 0;
|
|
1469
1789
|
const tIngest = performance.now();
|
|
1790
|
+
/*
|
|
1791
|
+
* โโ ๊ฐ์ ์ฌ์ค์ ๋ ๋ฒ ๋ฐ์ผ๋ฉด ํ ๋ฒ๋ง ๋ฐ์ํ๋ค (2026-08-26) โโโโโโโโโโโโโโโโโ
|
|
1792
|
+
*
|
|
1793
|
+
* ์ด ์๋ฆฌ๊ฐ ์ ์
๊ฒฝ๊ณ๋ค โ ์ปค๋ฅํฐ๊ฐ ๋ฌผ์ด์ ๋ฐ์ ๊ฒ ยท ์๋๋ฆฌ์ค๊ฐ ๋ฃ๋ ๊ฒ ยท ๋ถํ ๋๊ตฌ๊ฐ ๋ฃ๋ ๊ฒ์ด
|
|
1794
|
+
* ๋ชจ๋ ์ฌ๊ธฐ๋ฅผ ์ง๋๋ค(์นํ
์ผ๋ก ๋ฐ๋ ๊ธธ์ด ์๊ธฐ๋ฉด ๊ทธ๊ฒ๋ ์ฌ๊ธฐ๋ก ์จ๋ค). ๊ทธ๋์ ์ค๋ณต์ ์ฌ๊ธฐ์ ํ ๋ฒ
|
|
1795
|
+
* ๊ฑฐ๋ฅธ๋ค.
|
|
1796
|
+
*
|
|
1797
|
+
* ์ง๊ธ๊น์ง๋ ์ปค๋ฅํฐ๋ง๋ค ๊ฐ์ ๋ง๊ณ ์์๋ค. ๊ทธ๋์ ์์ผ๋ฉด ํธ์์ด ๊ทธ๋๋ก ๋ ๋ฒ ์
๋ค โ ํ์๊ด
|
|
1798
|
+
* ์ปค๋ฅํฐ๊ฐ ํ ์ฃผ๊ธฐ์ 76๊ฑด์ ๋ํ์ด ๋ณด๋๊ณ , ์ปค๋ฅํฐ๋ฅผ ๊ณ ์ณ์ 2๊ฑด์ด ๋๋ค. ๋ค์ ์ปค๋ฅํฐ๊ฐ ๊ฐ์ ๊ฒ์
|
|
1799
|
+
* ์์ผ๋ฉด ๋ ๋๋ค.
|
|
1800
|
+
*
|
|
1801
|
+
* ์ ๋๊ฐ์ผ๋ก ๋งํ๋ ์ฌ์ค์ ๋ ๋ฒ ๋ฐ์ํด๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ง๋ง(์๋ ยท ์ํ ยท ์ ์ฐ), ์ธ๋ ๊ฐ์ ์๋๋ค:
|
|
1802
|
+
* ๊ตฌ๊ฐ์ ํ๋ณธ ์ ยท ํ๊ท ๋ถํ ยท OEE ์นด์ดํฐ ยท ์ ์
๊ณ์. ๊ทธ๋ฆฌ๊ณ ์ง๋ ๊ธฐ๋ก์ ๊ฐ์ ์ฌ์ค์ด ๋ ์ค๋ก
|
|
1803
|
+
* ๋จ์ผ๋ฉด, ๋์ค์ ๊ทธ ๊ธฐ๋ก์ผ๋ก ๋ค์ ๊ณ์ฐํ ๋ ๋ ๋ ๋ฒ ์ผ๋ค.
|
|
1804
|
+
*
|
|
1805
|
+
* **์ ํํ ๊ฐ์ ๊ฒ๋ง ๋ฒ๋ฆฐ๋ค.** ๋ฆ๊ฒ ๋์ฐฉํ ์ ์ฌ์ค์ ๋ฒ๋ฆฌ์ง ์๋๋ค โ ๊ทธ๊ฒ์ด ์๋ค๋ ๊ฒ๋ ์ฌ์ค์ด๊ณ ,
|
|
1806
|
+
* ์ํ์ ๋ฐ์ํ์ง ์๋ ํ๋จ์ ์ปค๋์ด ์ด๋ฏธ ํ๋ค.
|
|
1807
|
+
*/
|
|
1808
|
+
const { fresh, duplicates } = (inst.deduper ??= new ingest_dedupe_js_1.FactDeduper()).filter(envelopes);
|
|
1809
|
+
envelopes = fresh;
|
|
1810
|
+
const ledgerKey = (0, runtime_key_js_1.runtimeKey)(domainId, id);
|
|
1811
|
+
const ledger = this.ingestLedgers[ledgerKey] ?? (this.ingestLedgers[ledgerKey] = (0, ingest_health_js_1.newIngestLedger)());
|
|
1812
|
+
if (duplicates)
|
|
1813
|
+
(0, ingest_health_js_1.recordDuplicates)(ledger, duplicates, Date.now());
|
|
1814
|
+
if (envelopes.length)
|
|
1815
|
+
(0, ingest_health_js_1.recordIngestSource)(ledger, source, envelopes.length, Date.now());
|
|
1470
1816
|
/* ์ธ์
๋ดํฌ๋ฅผ ํ์ํด ๋๊ณ ๋ฃ๋๋ค โ ์ปค๋์ด ๊ทธ๊ฒ์ ์ฌ๋ฐฉ์ถํด๋ ์ ๋์ ๋ ๋ฒ ์ ํ์ง ์๊ฒ(์ ๊ตฌ๋
์ฃผ์). */
|
|
1471
1817
|
for (const e of envelopes) {
|
|
1472
1818
|
if (e && typeof e === 'object')
|
|
@@ -1491,20 +1837,41 @@ class TwinEngine {
|
|
|
1491
1837
|
* ๊ตฌ๊ฐ ์ฑ๊ณผ ๋ธ๋ก๋์บ์คํ
์ **์์ด๋ค**(2026-08-06). ์นด๋๊ฐ `twinKpi` ๋ฅผ ์ง์ ๋ฌป๋๋ค.
|
|
1492
1838
|
*
|
|
1493
1839
|
* ์: ์นด๋๋ฅผ ์ฌ๋ฌ ๋จ๊ณ(๊ณต๊ฐยทํธ์ยท๊ตฌ์ญยท์๋ฆฌยท์ค๋น)์ ๋ถ์ด๋ ค๋ฉด ๋ธ๋ก๋์บ์คํ
์ผ๋ก๋ ํ๊ทธ๊ฐ ํธ์๋น 1,200๊ฐ๊ฐ ๋๊ณ ,
|
|
1494
|
-
* **๋ชจ๋ธ์ ์นด๋๋ฅผ ํ๋๋ ์ ๋์๋** 30์ด๋ง๋ค ํธ์๋ง๋ค ์ ๋์
|
|
1840
|
+
* **๋ชจ๋ธ์ ์นด๋๋ฅผ ํ๋๋ ์ ๋์๋** 30์ด๋ง๋ค ํธ์๋ง๋ค ์ ๋์ ๊ณ์ฐํ๋ค. ์ง์๋ก ๋ฐ๊พธ๋ ๋ณด๊ณ ์๋ ์นด๋
|
|
1495
1841
|
* ์๋งํผ๋ง ๋ค๊ณ , ๊ฐ์ (๋์ยท์ฐฝยท์ถ) ์ ํด๋ผ์ด์ธํธ๊ฐ ํ๋๋ก ํฉ์น๋ค.
|
|
1496
1842
|
*
|
|
1497
1843
|
* ๋ค์ผ๋ก ์ง์๋ง ํ ์ ์๋ ๊ฒ์ด ๋ ์๊ฒผ๋ค โ **๊ณผ๊ฑฐ ์๊ฐ**(`toTime`)๊ณผ **๊ณต๊ฐ ๋จ์ ํฉ์ฐ**(์ฌ๋ฌ ํธ์์
|
|
1498
|
-
* ํ ๋ฒ์
|
|
1844
|
+
* ํ ๋ฒ์ ๊ณ์ฐ). ๋ธ๋ก๋์บ์คํ
๋ฃจํ๋ ํธ์๋ณ์ด๋ผ ๋ ๋ค ๋ชป ํ๋ค.
|
|
1499
1845
|
*
|
|
1500
1846
|
* ์ถ์ ๋๋ ๋ ํด๋ ๋น์ฉ์ด ๊ฐ๋ค๋ ์ค์ธก์ด ๊ทผ๊ฑฐ๋ค(`test/kpi-query-bench.test.ts`).
|
|
1501
1847
|
*/
|
|
1502
1848
|
/**
|
|
1503
1849
|
* ๋ช ์ฐฝ๋ง๋ค ํ ๋ฒ์ **์ ๋ถ** ๋ง๋๋ โ ์ฌ๊ฑด ์์ด ๊ฐ์ด ๋ฐ๋๋ ์๋ฆฌ์ ๋ํ ๊ทธ๋ฌผ.
|
|
1504
1850
|
*
|
|
1505
|
-
*
|
|
1851
|
+
* ๋ณด์ฅ์ด ์๋๋ผ ๊ทธ๋ฌผ์ด๋ค(์ `publishEntityData` ์ฃผ์). **์ธ๋ ๋จ์๋ ์ฐฝ์ด์ง๋ง ๋ป์ ์๊ฐ**์ด๋ฏ๋ก,
|
|
1852
|
+
* ๊ธฐ๋ณธ ์ฃผ๊ธฐ๋ฅผ 200๋ฐ๋ฆฌ์ด์์ 1์ด๋ก ๋๋ฆฐ ๋ ์ด ์๋ ํจ๊ป ์ค์๋ค(25์ฐฝ โ 5์ฐฝ). ๊ทธ๋ฌ์ง ์์ผ๋ฉด ๊ทธ๋ฌผ์ด
|
|
1853
|
+
* 5์ด์์ 25์ด๋ก ๋ฒ์ด์ ธ, ์๊ฐ๋ง์ผ๋ก ๋ฐ๋๋ ๊ฐ(์ ํจ ๊ธฐ๊ฐ ๋ง๋ฃ ๊ฐ์ ๊ฒ)์ด ๊ทธ๋งํผ ๋ฆ๊ฒ ๋ณด์ธ๋ค.
|
|
1854
|
+
*/
|
|
1855
|
+
static { this.FULL_BROADCAST_EVERY = 5; }
|
|
1856
|
+
/**
|
|
1857
|
+
* **ํ ์คํ ์ฐจ๋ก์ ๋ฐํํ ์ ์๋ ๊ฑด์** โ ์ด๋งํผ ๋ฐํํ๋ฉด ๋ฃจํ๋ฅผ ๋น์ ์ค๋ค (2026-08-27).
|
|
1858
|
+
*
|
|
1859
|
+
* โโ ์ ์ํ์ด ํ์ํ๊ฐ (์ค์ธก์ผ๋ก ์๋ฒ๊ฐ ๋ ๋ฒ ์ฃฝ์๋ค) โโโโโโโโโโโโโโโโโโโโโโ
|
|
1860
|
+
* ๊ตฌ๋
์ ๋๊ธฐ์ด์๋ ๋ฒํผ๊ฐ ์๋ค(`pubsub.subscribe` ๊ฐ `new Repeater(fn)` ์ ๋ฒํผ ์์ด ๋ง๋ ๋ค).
|
|
1861
|
+
* ๋ฐํํ๋ ์๊ฐ์ ใ๋ค์ ๊ฐ์ ๋ฌ๋ผใ๋ ์์ฒญ์ด ์ด๋ฏธ ๊ฑธ๋ ค ์์ด์ผ ๋ฐ๋ก ์ ๋ฌ๋๊ณ , ์๋๋ฉด ๋๊ธฐ์ด์
|
|
1862
|
+
* ์์ธ๋ค. ์ํ์ 1024 ์ด๊ณ ๋์ผ๋ฉด ์์ธ๊ฐ ๋๋ค(`@repeaterjs/repeater` ์ `MAX_QUEUE_LENGTH`).
|
|
1863
|
+
*
|
|
1864
|
+
* ๊ฐ์ ๊บผ๋ด๋ ์ชฝ์ ๋น๋๊ธฐ๋ค. ๊ทธ๋์ **๋๊ธฐ ๋ฐ๋ณต๋ฌธ์ด ๋๋ ์ค์๋ ํ ๊ฑด๋ ๊บผ๋ด์ง ๋ชปํ๋ค.** ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก
|
|
1865
|
+
* ์ง์ ์ฌ ๋ณธ ๊ฐ์ด๋ค โ ์๋น์๋ฅผ ๋ถ์ฌ ๋๊ณ 2,000๊ฑด์ ๋๊ธฐ๋ก ๋ฐํํ๋ฉด ์๋น์๊ฐ ๊บผ๋ธ ๊ฒ์ 1๊ฑด์ด์๊ณ
|
|
1866
|
+
* ๋๋จธ์ง๊ฐ ์์ฌ ์์ธ๊ฐ ๋ฌ๋ค.
|
|
1867
|
+
*
|
|
1868
|
+
* ๊ทธ ์์ธ๋ `publish()` ํธ์ถ์์๊ฒ ์ค์ง ์๋๋ค. `EventTarget` ์ด ๋ฆฌ์ค๋ ์์ธ๋ฅผ uncaughtException ์ผ๋ก
|
|
1869
|
+
* ๋ณด๋ด๋ฏ๋ก try/catch ๋ก๋ ์ก์ ์ ์๋ค(2026-08-14 ์ ๊ทธ ๊ฐ๋๋ฅผ ๋ถ์๋๋ฐ ๊ทธ๋์ ๋ฌด๋ ฅํ๋ค). ๋ง๋ ๋ฐฉ๋ฒ์
|
|
1870
|
+
* **ํ ์ฐจ๋ก์ ์ํ์ ๋๊ธฐ์ง ์๋ ๊ฒ** ํ๋๋ค.
|
|
1871
|
+
*
|
|
1872
|
+
* 1024 ๋ณด๋ค ๋๋ํ ์๊ฒ ๋๋ค โ ์๋น์๊ฐ ํ ์ฒญํฌ๋ฅผ ๋ค ๊บผ๋ด์ง ๋ชปํด๋ ๋ค์ ์ฒญํฌ๊น์ง ์ฌ์ ๊ฐ ๋จ๋๋ค.
|
|
1506
1873
|
*/
|
|
1507
|
-
static { this.
|
|
1874
|
+
static { this.PUBLISH_CHUNK = 200; }
|
|
1508
1875
|
/** ์ ๋ถ ๋ง๋ ํ์ โ ๋ฒ์๋ฅผ ์ขํ์ง ๋ชปํ ์ฐฝ์ด ์ผ๋ง๋ ๋๋์ง ๊ฐ์ผ๋ก ๋จ๋๋ค. */
|
|
1509
1876
|
static { this.broadcastFullPasses = 0; }
|
|
1510
1877
|
/**
|
|
@@ -1540,7 +1907,21 @@ class TwinEngine {
|
|
|
1540
1907
|
}
|
|
1541
1908
|
}
|
|
1542
1909
|
/** ๋ธ๋ก๋์บ์คํ
๋ณํฉ ์ฃผ๊ธฐ(ms) โ ๋ธ๋ก๋์บ์คํ
๋ฅ ์ํ. ์ธ์ ์คํธ๊ฐ ์๋ฌด๋ฆฌ ๋นจ๋ผ๋ ์ด ์ฃผ๊ธฐ๋ก๋ง ๋ธ๋ก๋์บ์คํ
. */
|
|
1543
|
-
|
|
1910
|
+
/*
|
|
1911
|
+
* โโ 200 โ 1000 (2026-08-25 ยท ์ฌ์ฉ์ ๊ฒฐ์ ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1912
|
+
* ํธ์ **๋**์์ ์ด๋ฏธ ์ฃผ๊ธฐ๋ฅผ ์ค์ค๋ก ๋๋ฆฌ๊ณ ์์๋ค(ํ ๋ฒ ๋ณด๋ด๋ ๋ฐ 270๋ฐ๋ฆฌ์ด). 200๋ฐ๋ฆฌ์ด๋ ์ํ๊ฐ
|
|
1913
|
+
* ์์ ๋์ ๊ฐ์ด๊ณ , ์ง๊ธ ์นํํธ๋ ํ๋๊ฐ ์ํฐํฐ 17,600๊ฐ๋ค(๋ฌผํ 6,494 ยท ์ค๋ 4,794 ยท ์์
6,353).
|
|
1914
|
+
*
|
|
1915
|
+
* ํ ๋ฒ ๋ณด๋ด๋ ๊ฐ์ ์ํ ํฌ๊ธฐ์ ๋น๋กํ๋ฏ๋ก ์ฃผ๊ธฐ๋ฅผ ๋๋ฆฌ๋ ๊ฒ์ผ๋ก ๊ทธ ๊ฐ์ด ์ค์ง๋ ์๋๋ค. ๋์ **๋จ์
|
|
1916
|
+
* ์๊ฐ์ ๊ทธ ๊ฐ์ ์น๋ฅด๋ ํ์**๊ฐ 5๋ถ์ 1์ด ๋๋ค. ๊ทธ ์ฌ์ด ํธ์คํธ๊ฐ HTTPยท๊ตฌ๋
์ ์ฒ๋ฆฌํ๋ค.
|
|
1917
|
+
*
|
|
1918
|
+
* ํ๋ฉด์ด ๋ฆ๊ฒ ๊ฐฑ์ ๋๋ ๊ฒ์ ์ต๋ 1์ด๋ค. ์ต์ -์ํ ์ฑ๋์ด๋ผ ๋ฐ๋ฆฐ ๊ฒ์ ์์ ๋ณด๋ด์ง ์๊ณ ๋ง์ง๋ง ํ๋๋ง
|
|
1919
|
+
* ๊ฐ๋ฏ๋ก, ๋ฆ์ด์ง ๋ฟ ๋ด์ฉ์ ๊ฐ๋ค.
|
|
1920
|
+
*
|
|
1921
|
+
* **๋น์ฉ์ ์ค์ธ ๊ฒ์ด ์๋๋ค.** ์ค์ด๋ ๊ฒ์ ๋ณ๊ฒฝ๋ถ๋ง ๋ง๋๋ ์ผ์ด๊ณ (๋ฐ๋ ๊ฒ๋ง ๋ค์ ๋ง๋๋ ์ผ) ๊ทธ๊ฒ์ ๋ณ
|
|
1922
|
+
* ์์
์ด๋ค โ ๊ณํ: `design/plans/live-broadcast-cost.md`.
|
|
1923
|
+
*/
|
|
1924
|
+
static { this.BROADCAST_COALESCE_MS = 1000; }
|
|
1544
1925
|
/**
|
|
1545
1926
|
* โโ ๋ธ๋ก๋์บ์คํ
์ฃผ๊ธฐ๋ **์ฌ ๋ณธ ๋น์ฉ์ ๋ง์ถ๋ค** (2026-08-21 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโ
|
|
1546
1927
|
* ํ ๋ฒ์ ๋ธ๋ก๋์บ์คํ
์ ์ํ ํฌ๊ธฐ์ ๋น๋กํ๋ค(์ค์ธก: ๋ฌผํ 2,400 ๊ฐ์ธ ํธ์ ํ๋๊ฐ 4.5ms โ ์ํ ํฌ์ 1.7ms,
|
|
@@ -1554,12 +1935,13 @@ class TwinEngine {
|
|
|
1554
1935
|
* ์ด๊ฒ์ ๋ธ๋ก๋์บ์คํ
๋น์ฉ์ **์ค์ด๋ ๊ฒ์ด ์๋๋ค** โ ๋น์ฉ์ ์ค์ด๋ ๊ฒ์ ๋ณ๊ฒฝ๋ถ๋ง ๋ง๋๋ ์ผ์ด๊ณ ๊ทธ๊ฒ์ ๋ณ
|
|
1555
1936
|
* ์์
์ด๋ค. ์ฌ๊ธฐ์๋ ๊ทธ๋๊น์ง ํธ์คํธ๊ฐ ๊ตถ์ง ์๊ฒ ์ํ์ ๋๋ค.
|
|
1556
1937
|
*/
|
|
1557
|
-
|
|
1938
|
+
/* ๊ธฐ๋ณธ์ด 1์ด๊ฐ ๋์์ผ๋ฏ๋ก ๋๋ฆด ์ฌ์ง๋ฅผ ํจ๊ป ์ฌ๋ฆฐ๋ค โ ์ํ์ด ๊ธฐ๋ณธ๊ณผ ๊ฐ์ผ๋ฉด ๋๋ฆด ๊ณณ์ด ์๋ค. */
|
|
1939
|
+
static { this.BROADCAST_MAX_COALESCE_MS = 2000; }
|
|
1558
1940
|
/** ์ฃผ๊ธฐ์ ๋ช ๋ชซ๊น์ง ๋ธ๋ก๋์บ์คํ
์ ์จ๋ ๋๋๊ฐ โ ๋์ผ๋ฉด ์ฃผ๊ธฐ๋ฅผ ๋๋ฆฐ๋ค(์ ๋ฐ์ด๋ฉด ๋๋จธ์ง ์ ๋ฐ์ ๋จ๊ธด๋ค). */
|
|
1559
1941
|
static { this.BROADCAST_LOAD_RATIO = 0.3; }
|
|
1560
1942
|
/** ์ง๊ธ ์ฐ๊ณ ์๋ ์ฃผ๊ธฐ(ms) โ ๊ณ๊ธฐํ์ด ์ด ๊ฐ์ ์ฝ๋๋ค. ๋์ด๋ ์ฑ๋ก ์์ผ๋ฉด ๊ทธ๊ฒ์ด ์ฌ์ค์ด๋ค. */
|
|
1561
1943
|
static { this.broadcastPeriodMs = 200; }
|
|
1562
|
-
/** ์ฃผ๊ธฐ๋ฅผ ๋๋ฆฐ ํ์ โ
|
|
1944
|
+
/** ์ฃผ๊ธฐ๋ฅผ ๋๋ฆฐ ํ์ โ ์๋ฆฌ์ง ์๊ณ ๋ฆ์ถ์ง ์๋๋ค. */
|
|
1563
1945
|
static { this.broadcastBackoffs = 0; }
|
|
1564
1946
|
/** live ๋ธ๋ก๋์บ์คํ
coalescer โ dirty ์ธ live ์ธ์คํด์ค๋ง ์ฃผ๊ธฐ์ ์ผ๋ก 1ํ ๋ธ๋ก๋์บ์คํ
(entitySigs ๋ก ๋ณ๊ฒฝ ์ํฐํฐ๋ง). */
|
|
1565
1947
|
static ensureBroadcastCoalescer() {
|
|
@@ -1606,7 +1988,31 @@ class TwinEngine {
|
|
|
1606
1988
|
* ํ tick ์์ ์๋ฐฑ ๋ฒ ๋ฐ๋ณต๋๋ฉฐ ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ๋ง์๋ค(์ `start()` ์ฃผ์์ 35์ด ํฑ). ๋ธ๋ก๋์บ์คํ
์ ๋ชจ์ผ๋
|
|
1607
1989
|
* ๊ท์จ์ ๋ชจ๋์ ์ฑ์ง์ด ์๋๋ผ **์ฑ๋์ ์ฑ์ง**์ด๋ค โ ์ต์ -์ํ ์ฑ๋์ด๋ฉด ์ค๊ฐ ์ํ๋ ๋ณด๋ผ ๊ฐ์ด ์๋ค.
|
|
1608
1990
|
*/
|
|
1991
|
+
/**
|
|
1992
|
+
* ๋ธ๋ก๋์บ์คํ
ํ ์ฐฝ โ **๊ฒน์ณ ๋์ง ์๋๋ค** (2026-08-27).
|
|
1993
|
+
*
|
|
1994
|
+
* ๋ฐํ์ด ์ฒญํฌ๋ก ๋๋์ด ์ฌ์ด์ ๋ฃจํ๋ฅผ ๋น์ ์ฃผ๋ฏ๋ก ํ ์ฐฝ์ด ์ฃผ๊ธฐ๋ฅผ ๋๊ธธ ์ ์๋ค. ๊ทธ๋ ๋ค์ ํ์ด๋จธ๊ฐ
|
|
1995
|
+
* ๊ฒน์ณ ๋ค์ด์ค๋ฉด ๊ฐ์ ํ๊ทธ๊ฐ ๋ ์์๋ก ๋๊ฐ๊ณ ์๊ทธ๋์ฒ ํ๊ฐ ์ํจ๋ค. ๊ทธ๋์ ์ ์ฐฝ์ด ๋๋ ๋๊น์ง
|
|
1996
|
+
* ๋ค์ ํ์ด๋จธ๋ ๊ทธ๋๋ก ๋์๊ฐ๋ค โ **์ฐฝ์ ๋ฒ๋ฆฌ๋ ๊ฒ์ด ์๋๋ค.** ๋ค์ ํ์ด๋จธ๊ฐ ์ด์ด์ ํ๋ค.
|
|
1997
|
+
*
|
|
1998
|
+
* ๊ฒน์น ํ์๋ฅผ ์ผ๋ค. ๊ณ์ ๊ฒน์น๋ฉด ์ฃผ๊ธฐ๋ณด๋ค ํ ์ฐฝ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ณ ์๋ค๋ ๋ป์ด๊ณ , ๊ทธ๊ฒ์
|
|
1999
|
+
* `adjustBroadcastPeriod` ๊ฐ ์ฃผ๊ธฐ๋ฅผ ์ฌ๋ ค ์ค์ค๋ก ํ์ด์ผ ํ๋ ์ฌ์ค์ด๋ค.
|
|
2000
|
+
*/
|
|
2001
|
+
static { this.flushInFlight = false; }
|
|
2002
|
+
static { this.flushOverruns = 0; }
|
|
1609
2003
|
static flushLiveBroadcasts() {
|
|
2004
|
+
if (this.flushInFlight) {
|
|
2005
|
+
this.flushOverruns++;
|
|
2006
|
+
return;
|
|
2007
|
+
}
|
|
2008
|
+
this.flushInFlight = true;
|
|
2009
|
+
void this.flushBroadcastWindow()
|
|
2010
|
+
.catch(err => (0, log_js_1.twinError)('[twin-engine] broadcast window failed', err?.message ?? err))
|
|
2011
|
+
.finally(() => {
|
|
2012
|
+
this.flushInFlight = false;
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
static async flushBroadcastWindow() {
|
|
1610
2016
|
const now = Date.now();
|
|
1611
2017
|
const flushStart = performance.now();
|
|
1612
2018
|
for (const inst of Object.values(this.instances)) {
|
|
@@ -1645,7 +2051,7 @@ class TwinEngine {
|
|
|
1645
2051
|
inst.fullBroadcastCountdown = left;
|
|
1646
2052
|
}
|
|
1647
2053
|
// โ ์ํฐํฐ data(tag) ๋ธ๋ก๋์บ์คํ
โ ๋ณด๋ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ ๋ ๋.
|
|
1648
|
-
this.publishEntityData(inst);
|
|
2054
|
+
await this.publishEntityData(inst);
|
|
1649
2055
|
if (m) {
|
|
1650
2056
|
m.broadcastTotal++;
|
|
1651
2057
|
m._accBroadcast++;
|
|
@@ -1693,7 +2099,7 @@ class TwinEngine {
|
|
|
1693
2099
|
correlationId: e?.correlationId,
|
|
1694
2100
|
revision,
|
|
1695
2101
|
/* **์ด ์ฌ์ค์ด ์ผ์ด๋ ๊ณต์ฅ**์ ํจ๊ป ์ฐ๋๋ค โ ์ด๊ฒ์ด ์์ผ๋ฉด ๋์ค์ ๊ตฌ์กฐ๊ฐ ๋ฐ๋์์ ๋ ์ด ํ์
|
|
1696
|
-
์ ๊ณต์ฅ์ ๋๊ณ
|
|
2102
|
+
์ ๊ณต์ฅ์ ๋๊ณ ๊ณ์ฐํ๊ฒ ๋๊ณ , ๊ทธ๋ ์๋ ์ค๋น์์ ์ผ์ด ์์๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. */
|
|
1697
2103
|
...(structureRev === undefined ? {} : { structureRev }),
|
|
1698
2104
|
/* ์ปค๋์ ISO ๋ฌธ์์ด์ ์ค๋ค. ์ปฌ๋ผ์ ๋ ์ง๋ค โ **์ฌ๊ธฐ์ ์ฎ๊ธด๋ค.** ๋ฌธ์์ด์ ๊ทธ๋๋ก ๋ฃ์ผ๋ฉด
|
|
1699
2105
|
๋๋ผ์ด๋ฒ๊ฐ ์ ํ์์ผ๋ก ์ ๊ทํํ์ง ์์, ๋์ค์ ๋ ์ง๋ก ๊ฑฐ๋ ์ง์์ ์ ๊ฑธ๋ฆฐ๋ค. */
|
|
@@ -1731,12 +2137,12 @@ class TwinEngine {
|
|
|
1731
2137
|
* ๋ชจ์ ๋ ์ ๋์ **ํ ๋ฒ์** ์ด๋ค โ ๋ ๊ตฌ๋์ด ๊ฐ์ ๋ฌธ์ ์ด๋ค (ยง7.1).
|
|
1732
2138
|
*
|
|
1733
2139
|
* โโ ์ ํ ํจ์์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1734
|
-
* ์ฐ๋ ์๋ฆฌ๊ฐ ๋์ด๋ฉด(์ฃผ๊ธฐ flush ยท ์ ์ง) ํ์ชฝ๋ง ๊ณ ์ณ์ง๊ณ , ๊ทธ ์ด๊ธ๋จ์ **์ฌ์ค์ด
|
|
2140
|
+
* ์ฐ๋ ์๋ฆฌ๊ฐ ๋์ด๋ฉด(์ฃผ๊ธฐ flush ยท ์ ์ง) ํ์ชฝ๋ง ๊ณ ์ณ์ง๊ณ , ๊ทธ ์ด๊ธ๋จ์ **์ฌ์ค์ด ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋**
|
|
1735
2141
|
* ๋ชจ์์ผ๋ก ๋ํ๋๋ค. ๊ทธ๋์ ํ๋ฆฌ๋ ๊ท์น์ ์ฌ๊ธฐ ํ ๊ณณ์ ๋๋ค.
|
|
1736
2142
|
*
|
|
1737
2143
|
* โโ ๋ฆฌ๋น์ ์ ๋๊ฐ ๋งค๊ธฐ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1738
2144
|
* ยท ๋ผ์ด๋ธ โ ์์ฒ์ ๋ฆฌ๋น์ ์ ์ฃผ์ง ์์ผ๋ฏ๋ก **ํธ์คํธ๊ฐ** ์ด์ด ๋ถ์ธ๋ค(์ ๋ high-water ์์ ์๋).
|
|
1739
|
-
* ยท ์๋ฎฌ โ **์ปค๋์ ๋ฆฌ๋น์ **์ด ์ค๋ ค ์จ๋ค(์ ๋์ด
|
|
2145
|
+
* ยท ์๋ฎฌ โ **์ปค๋์ ๋ฆฌ๋น์ **์ด ์ค๋ ค ์จ๋ค(์ ๋์ด ๊ทธ ๋ฒํธ๋ก ์ ๋ ฌ๋๊ณ ์๊ฐ์ฌํ์ด ๊ทธ๊ฒ์ ๋๋๋ค).
|
|
1740
2146
|
* ๊ทธ๋์ ๋ฒํผ๋ ๋ ๋ชจ์์ ํจ๊ป ๋ ๋ค: ๋ดํฌ๋ง ์์ผ๋ฉด ๋ผ์ด๋ธ, `{ event, revision }` ์ด๋ฉด ์๋ฎฌ์ด๋ค.
|
|
1741
2147
|
*/
|
|
1742
2148
|
static flushJournal(inst) {
|
|
@@ -1761,9 +2167,20 @@ class TwinEngine {
|
|
|
1761
2167
|
if (carried.length)
|
|
1762
2168
|
jobs.push(this.persistCarried(inst.domainId, inst.id, carried));
|
|
1763
2169
|
if (plain.length && inst.revision != null) {
|
|
2170
|
+
/*
|
|
2171
|
+
* โโ ๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค์ ํ ๋ฒ๋ง ์ ๋๋ค (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโโ
|
|
2172
|
+
*
|
|
2173
|
+
* ์ด๋ฏธ ์๋ ๊ฒ์ ๊ฑธ๋ฌ๋ธ ๋ค์ ๋ฒํธ๋ฅผ ๋งค๊ธด๋ค. ๊ฑธ๋ฌ๋ด๊ธฐ ์ ์ ๋งค๊ธฐ๋ฉด **์ฐ์ง ์์ ๋ฒํธ๊ฐ ๋น๊ณ **,
|
|
2174
|
+
* ๊ทธ ๊ตฌ๋ฉ์ด ์ ๋์ ๋ฆฌ๋น์ ์ฐ์์ฑ์ ๋๋๋ค.
|
|
2175
|
+
*/
|
|
2176
|
+
/*
|
|
2177
|
+
* ๋ฒํธ๋ **๋จผ์ ์ก๋๋ค**(๋๊ธฐ). ๊ฑธ๋ฌ๋ธ ๋ค์ ์ก์ผ๋ฉด ๋ flush ๊ฐ ๊ฒน์น ๋ ๊ฐ์ ๋ฒํธ๋ฅผ ๋ ๋ฒ ์ด๋ค.
|
|
2178
|
+
* ๊ฑธ๋ฌ์ง ๋งํผ ๋ฒํธ๊ฐ ๋น์ง๋ง, ๊ทธ ๊ตฌ๋ฉ์ ํด๋กญ์ง ์๋ค โ ๋ฆฌ๋น์ ์ ๊ฐ์ ์๊ฐ์ ๊ฐ๋ฆฌ๋ ๋ฐ๋ง ์ฐ๊ณ
|
|
2179
|
+
* ์ด์ด์ง์ ์๊ตฌํ์ง ์๋๋ค(์ ๋ ๋จธ๋ฆฌ๋ ์ต๋๊ฐ์ด๋ค).
|
|
2180
|
+
*/
|
|
1764
2181
|
const start = inst.revision;
|
|
1765
2182
|
inst.revision = start + plain.length;
|
|
1766
|
-
jobs.push(this.
|
|
2183
|
+
jobs.push(this.dropAlreadyWritten(inst.domainId, inst.id, plain).then(fresh => fresh.length ? this.persistBatch(inst.domainId, inst.id, fresh, start) : undefined));
|
|
1767
2184
|
}
|
|
1768
2185
|
if (!jobs.length)
|
|
1769
2186
|
return Promise.resolve();
|
|
@@ -1790,11 +2207,100 @@ class TwinEngine {
|
|
|
1790
2207
|
* ์์ ์๋ ์ด ๊ฒฝ๋ก๊ฐ **๋ธํ๋ง๋ค ํ ํ์ฉ** ์ ์ฅํ๋ค(๊ทธ๋ฆฌ๊ณ ํ๋ง๋ค ๊ตฌ์กฐ ๋ฆฌ๋น์ ์ ๋ฌผ์๋ค). ๊ท๋ชจ์์ ๊ทธ๊ฒ์ด
|
|
1791
2208
|
* ํธ์คํธ๋ฅผ ๋จน์๋ค(ยง7.1 ์ค์ธก). ์ฌ๊ธฐ์ ๊ตฌ์กฐ ๋ฆฌ๋น์ ์ **ํ ๋ฒ๋ง** ๋ฌป๋๋ค.
|
|
1792
2209
|
*/
|
|
2210
|
+
/**
|
|
2211
|
+
* **๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค์ ํ ๋ฒ๋ง ์ ๋๋ค** โ ๊ฐ์ ์ฌ์ค์ด ๋ ๋ฒ ์ค๋ฉด ํ ์ฌ์ค์ด๋ค (2026-08-30).
|
|
2212
|
+
*
|
|
2213
|
+
* โโ ์ ์ฐ๋ ์๋ฆฌ์์ ๋ง๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2214
|
+
* ์ปค๋์ด ๊ทธ ์ฌ์ค๋ค์ ์ ์ฒด์ฑ์ ๋ด์ฉ์์ ๋ง๋ ๋ค(์ข
๋ฅยท๋์ยท์์ยท๋). ๊ทธ๋ฐ๋ฐ ์ ๋์ ๊ธฐ๋ณธํค๋ ์๋ก
|
|
2215
|
+
* ๋ง๋๋ uuid ๋ผ, **id ๊ฐ ๊ธ์ ํ๋๊น์ง ๊ฐ์๋ ํ์ด ๋ฐ๋ก ์์๋ค.**
|
|
2216
|
+
*
|
|
2217
|
+
* ์ค์ธก(2026-08-30): ๋ฐ์ ๋จ๊ฐ๊ฐ ํ 7๊ฐยท์๋ก ๋ค๋ฅธ id 4๊ฐ์๋ค. 8์ 27์ผ ๋จ๊ฐ๊ฐ ์ธ ๋ฒ ์์๊ณ ,
|
|
2218
|
+
* ๊ทธ ๊ตฌ๊ฐ์ ์์ต์ด ์ธ ๋ฒ ์ธ์ด์ง๋ค.
|
|
2219
|
+
*
|
|
2220
|
+
* ์ปค๋ฅํฐ๊ฐ ์ปค์๋ก ๋ง๋ ๊ฒ์ด ์ฒซ ๋ฐฉ์ด์ ์ด๊ณ ๊ทธ์ชฝ๋ ๊ณ ์ณค๋ค. ๊ทธ๋ฐ๋ฐ **์ปค๋ฅํฐ๊ฐ ํ ๋ฒ ์ค์ํ๋ฉด ์ ๋์ด
|
|
2221
|
+
* ๋ถํ๊ณ ๊ทธ ์์ ๋ชจ๋ ํฉ์ด ํ๋ฆฐ๋ค.** ์ ์ฒด์ฑ์ ์ปค๋์ด ์ ์ธํ ์ฌ์ค์ด๋ฏ๋ก, ์ด๋ ๋ฌธ์ผ๋ก ๋ค์ด์ค๋
|
|
2222
|
+
* ์ง์ผ์ ธ์ผ ํ๋ค โ ์ฑ์ฐ๊ธฐ ๊ฒฝ๋ก์๋ง ์์ผ๋ฉด ๊ทธ ๋ณด์ฆ์ ใ์ด๋ ๋ฌธ์ผ๋ก ์๋๋ใ์ ๊ฑธ๋ฆฐ๋ค.
|
|
2223
|
+
*
|
|
2224
|
+
* โโ ๊ฐ์ด ์ผ ์ด์ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2225
|
+
* ๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค๋ง ๋ณธ๋ค(์์ ์ ๊ด์ธก์ ๊ทธ๋๋ก ์ง๋๋ค โ ๋ฐ๋ณต์ด ๋ป์ ๊ฐ์ง๋ค). ๊ทธ๊ฒ๋ค์ ๋๋ฌผ์ด์
|
|
2226
|
+
* (ํ ์๊ฐ์ ํ ์ค) ํ ๋ฌถ์์ ๋ช ๊ฐ๋ฟ์ด๊ณ , ๊ทธ ๊ตฌ๊ฐ์ ๊ทธ ์ข
๋ฅ๋ง ์์ธ์ผ๋ก ์ฝ๋๋ค.
|
|
2227
|
+
*/
|
|
2228
|
+
static { this.PERIOD_FACT_TYPES = new Set([
|
|
2229
|
+
'energy.usage.period',
|
|
2230
|
+
'energy.generation.period',
|
|
2231
|
+
'energy.generation.price',
|
|
2232
|
+
'energy.tariff.basis',
|
|
2233
|
+
'energy.bill'
|
|
2234
|
+
]); }
|
|
2235
|
+
static async dropAlreadyWritten(domainId, instanceId, envelopes) {
|
|
2236
|
+
const periodFacts = envelopes.filter(e => this.PERIOD_FACT_TYPES.has(String(e?.eventType)) && typeof e?.eventId === 'string');
|
|
2237
|
+
if (!periodFacts.length)
|
|
2238
|
+
return envelopes;
|
|
2239
|
+
const times = periodFacts.map(e => Date.parse(String(e.eventTime))).filter(n => Number.isFinite(n));
|
|
2240
|
+
if (!times.length)
|
|
2241
|
+
return envelopes;
|
|
2242
|
+
const types = [...new Set(periodFacts.map(e => String(e.eventType)))];
|
|
2243
|
+
const existing = await (0, shell_1.getRepository)(twin_event_js_1.TwinEvent)
|
|
2244
|
+
.createQueryBuilder('e')
|
|
2245
|
+
.select(['e.payload AS "payload"'])
|
|
2246
|
+
.where('e.domain = :domainId', { domainId })
|
|
2247
|
+
.andWhere('e.instanceId = :instanceId', { instanceId })
|
|
2248
|
+
.andWhere('e.eventType IN (:...types)', { types })
|
|
2249
|
+
.andWhere('e.eventTime BETWEEN :fromAt AND :toAt', { fromAt: new Date(Math.min(...times)), toAt: new Date(Math.max(...times)) })
|
|
2250
|
+
.getRawMany()
|
|
2251
|
+
.catch(() => []);
|
|
2252
|
+
const seen = new Set();
|
|
2253
|
+
for (const row of existing) {
|
|
2254
|
+
let p = row.payload;
|
|
2255
|
+
if (typeof p === 'string') {
|
|
2256
|
+
try {
|
|
2257
|
+
p = JSON.parse(p);
|
|
2258
|
+
}
|
|
2259
|
+
catch {
|
|
2260
|
+
p = undefined;
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
if (typeof p?.eventId === 'string' && p.eventId)
|
|
2264
|
+
seen.add(p.eventId);
|
|
2265
|
+
}
|
|
2266
|
+
/* ํ ๋ฌถ์ ์์ ๊ฐ์ ๊ฒ์ด ๋ ์์ด๋ ํ๋๋ง ์ ๋๋ค. */
|
|
2267
|
+
const kept = [];
|
|
2268
|
+
for (const e of envelopes) {
|
|
2269
|
+
if (!this.PERIOD_FACT_TYPES.has(String(e?.eventType)) || typeof e?.eventId !== 'string') {
|
|
2270
|
+
kept.push(e);
|
|
2271
|
+
continue;
|
|
2272
|
+
}
|
|
2273
|
+
if (seen.has(e.eventId))
|
|
2274
|
+
continue;
|
|
2275
|
+
seen.add(e.eventId);
|
|
2276
|
+
kept.push(e);
|
|
2277
|
+
}
|
|
2278
|
+
return kept;
|
|
2279
|
+
}
|
|
1793
2280
|
static async persistCarried(domainId, instanceId, items) {
|
|
1794
2281
|
const repo = (0, shell_1.getRepository)(twin_event_js_1.TwinEvent);
|
|
1795
2282
|
const structureRev = await this.structureRevOf(domainId, instanceId);
|
|
1796
2283
|
const rows = items.map(it => this.journalRow(repo, domainId, instanceId, it.event, it.revision, structureRev));
|
|
1797
2284
|
await this.insertRows(repo, rows);
|
|
2285
|
+
await this.writeSubjects(domainId, instanceId, items.map(it => ({ envelope: it.event, revision: it.revision })));
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* **๋์๋ณ ์ฌ๊ฑด ๋ชฉ๋ก์ ํจ๊ป ์ ๋๋ค** โ ์กฐํ์ฉ ํ์ ํ (2026-08-27).
|
|
2289
|
+
*
|
|
2290
|
+
* ์ ๋์ ์ฐ๋ ๋ ๋ฌธ(`persistBatch` ยท `persistCarried`) ๋ค์์ ๋ถ๋ฅธ๋ค. ๋ค๋ฅธ ์๋ฆฌ์์ ๋์ค์ ์ ์ผ๋ฉด
|
|
2291
|
+
* ใ์ ๋์๋ ์๊ณ ๊ทธ ํ์๋ ์๋ ์ฌ๊ฑดใ์ด ์๊ธฐ๊ณ , ๊ทธ๊ฒ์ ํ๋ฉด์์ ์ค๋ฅ ์์ด ๋น ์ง ์ฌ๊ฑด์ด ๋๋ค.
|
|
2292
|
+
*
|
|
2293
|
+
* **์ ๋์ด ๋จผ์ ๋ค.** ์ด ํ์ ์ ๋ค๊ฐ ์คํจํด๋ ์ ๋ ์ฐ๊ธฐ๋ฅผ ๋๋๋ฆฌ์ง ์๋๋ค โ ์ฌ์ค์ ์๋ณธ์ ์ ๋์ด๊ณ
|
|
2294
|
+
* ์ด ํ๋ ๋ค์ ๋ง๋ค ์ ์๋ค. ์คํจ๋ ์ธ์ด ๋จ๊ธด๋ค(ยง`subjectWriteFailures`).
|
|
2295
|
+
*
|
|
2296
|
+
* ์ค๊ณ: `operato-twin/design/plans/read-models.md`
|
|
2297
|
+
*/
|
|
2298
|
+
static async writeSubjects(domainId, instanceId, entries) {
|
|
2299
|
+
if (!entries.length)
|
|
2300
|
+
return;
|
|
2301
|
+
const reg = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
2302
|
+
const itemOf = (0, item_resolver_js_1.itemResolverFor)(domainId, instanceId, reg?.model);
|
|
2303
|
+
await (0, twin_subject_writer_js_1.writeSubjectRows)(domainId, instanceId, entries, itemOf).catch(err => (0, log_js_1.twinWarn)(`[twin-subject] "${instanceId}" ๋์ ๋ชฉ๋ก ์ฐ๊ธฐ ์คํจ โ ${err?.message ?? err}`));
|
|
1798
2304
|
}
|
|
1799
2305
|
/**
|
|
1800
2306
|
* ์ ๋ ํ์ ๋ฃ๋๋ค โ **๋ฃ๊ธฐ๋ง ํ๋ค**(2026-08-20).
|
|
@@ -1837,6 +2343,7 @@ class TwinEngine {
|
|
|
1837
2343
|
const structureRev = await this.structureRevOf(domainId, instanceId);
|
|
1838
2344
|
const rows = envelopes.map((e, i) => this.journalRow(repo, domainId, instanceId, e, startRevision + i + 1, structureRev));
|
|
1839
2345
|
await this.insertRows(repo, rows);
|
|
2346
|
+
await this.writeSubjects(domainId, instanceId, envelopes.map((e, i) => ({ envelope: e, revision: startRevision + i + 1 })));
|
|
1840
2347
|
}
|
|
1841
2348
|
/** ๋ ์ง์คํธ๋ฆฌ upsert(๋๋ฉ์ธ+instanceId ์ ๋ํฌ). status ์ธ์๋ก provision(stopped)/start(running) ๊ณต์ฉ. */
|
|
1842
2349
|
static async register(domainId, instanceId, kind, model, status = 'running', restartPolicy, origin,
|
|
@@ -1859,7 +2366,7 @@ class TwinEngine {
|
|
|
1859
2366
|
areaId: model?.areaId ?? existing?.areaId,
|
|
1860
2367
|
/* ์ฌ๊ธฐ๋ ์ ์ฑ
(ADR-0029 ยง2) โ ๋ช
์๊ฐ ์ฐ์ , ์์ผ๋ฉด ๊ธฐ์กด๊ฐ ๋ณด์กด(์ฌํ๋ก๋น์ ์ด ์ ์ธ์ ์ง์ฐ์ง ์๊ฒ).
|
|
1861
2368
|
**๋ ๋ค ์์ผ๋ฉด ์ค๋ฅ๋ฅผ ๋ธ๋ค**: ์์ ์๋ ์ฌ๊ธฐ์ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ธํ๋๋ฐ, ๊ทธ ๊ธฐ๋ณธ๊ฐ์ด ใ์ ๋ ์ด๊ธฐํใ๋ผ์
|
|
1862
|
-
์ ์ธ์ ๋น ๋จ๋ฆฐ ํ๋ก๋น์ ๋์ด
|
|
2369
|
+
์ ์ธ์ ๋น ๋จ๋ฆฐ ํ๋ก๋น์ ๋์ด ์๋ฆฌ์ง ์๊ณ ์ด๋ ฅ์ ์ง์ฐ๋ ํธ์์ ๋ง๋ค์๋ค. ์ ์ธ์ ๋ถ๋ฅด๋ ์ชฝ์ ๋ชซ์ด๋ค. */
|
|
1863
2370
|
restartPolicy: restartPolicy ??
|
|
1864
2371
|
(0, restart_policy_js_1.readRestartPolicy)(existing?.restartPolicy, `register("${instanceId}") did not declare a restart policy and the stored row has none`),
|
|
1865
2372
|
/* ์ฉ๋๋ ๊ฐ์ธํ๋ค. ๋ฒค์น๋ก ๋ค์ง๋ ๊ฒ์ `setPurpose` ํ๋๋ฟ์ด๋ฏ๋ก ๊ธฐ์กด๊ฐ์ ๋ฐ๋์ ๋ณด์กดํ๋ค
|
|
@@ -1878,6 +2385,23 @@ class TwinEngine {
|
|
|
1878
2385
|
}));
|
|
1879
2386
|
}
|
|
1880
2387
|
/**
|
|
2388
|
+
* โโ **ํธ์์ ์ค๋น์ ๋ง์คํฐ๊ฐ ์๋๋ค** (์ฌ์ฉ์ ๊ฒฐ์ 2026-08-30) โโโโโโโโโโโโโ
|
|
2389
|
+
*
|
|
2390
|
+
* ์ธ์ยท์ค๋นยท์์ฐ์ ๋ง์คํฐ๋ `@things-factory/ops-master` ๋ค. ํธ์์ ๊ทธ๊ฒ์ **๋น๊ฒจ ์** ๋ชจ๋ธ์
|
|
2391
|
+
* ๋ฐ์ํ๊ณ , ์ฌ๊ธฐ ๋จ๋ ๊ฒ์ ๊ทธ ๊ฒฐ๊ณผ์ ์บ์๋ค.
|
|
2392
|
+
*
|
|
2393
|
+
* ๊ทธ๋์ ์ด ํจ์๊ฐ ํ๋ ์ผ์ ์ ์ด ์๋ค.
|
|
2394
|
+
*
|
|
2395
|
+
* ํธ์ ์์์ ์ฌ๋์ด ๋ํ ์ค๋น ๊ฐ์ ยท์๋ฎฌ๋ ์ด์
์ ์ฌ์ค์ด๋ค โ ํธ์์ด ๋ ๋ค (์ง๊ธ ์ด ํจ์)
|
|
2396
|
+
* ํ์ฅ์ ์ค์ ๋ก ์๋ ์ค๋น ๋ง์คํฐ์ ์ฌ์ค์ด๋ค โ ํธ์์ด ๋ง๋ค์ง ์๋๋ค
|
|
2397
|
+
*
|
|
2398
|
+
* ์ด ํจ์๋ **ํธ์ ์ ์ด ๋ช
๋ น**(`resource.add`) ๋ค์๋ง ๋ถ๋ฆฐ๋ค. ๊ด์ธก์์ ์ค๋น๊ฐ ์๊ธฐ๋ ๊ฒฝ๋ก๊ฐ ์๋๋ค.
|
|
2399
|
+
* ๊ด์ธก์ผ๋ก ๋ชจ๋ฅด๋ ์ค๋น๊ฐ ๋ค์ด์ค๋ฉด ๊ทธ๊ฒ์ **๋ง์คํฐ์ ์๋ ๊ฒ**์ด๊ณ , ํธ์์ด ์กฐ์ฉํ ๋ง๋ค์ด ์ฃผ๋ฉด ๋
|
|
2400
|
+
* ๊ณณ์ด ์๋ก ๋ค๋ฅธ ์ค๋น ๋ชฉ๋ก์ ๊ฐ๊ฒ ๋๋ค. ๊ทธ๋๋ ๋ง๋ค์ง ๋ง๊ณ ใ๋ชจ๋ฅด๋ ์ค๋น๊ฐ ์๋คใ๋ก ์ธ์ด์ผ ํ๋ค.
|
|
2401
|
+
*
|
|
2402
|
+
* ๋น๊ฒจ ์ค๋ ๊ธธ์ด ๋ถ์ผ๋ฉด ์ด ์ฃผ์์ ์์ชฝ ์ ๋ฐ๋ง ๋จ๋๋ค.
|
|
2403
|
+
*
|
|
2404
|
+
* โโ ์๋ ์ค๋ช
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1881
2405
|
* ๋ผ์ด๋ธ ๊ตฌ์กฐ ๋ณ์ด(resource.add ๋ฑ)๋ฅผ ์ ์ฅ๋ model ์ ๋ฐ์ โ ๋ฐํ์ ์ปค๋์ ๋ฌด๋ฒ๋ฅผ registry model.equipment ์ ๋๊ธฐ.
|
|
1882
2406
|
* ์ด๊ฒ ์์ผ๋ฉด ๋ฐํ์์ ์ถ๊ฐ๋ผ๋(์ํยท์ ๋์ ๋ฐ์) ์ ์ฅ model ๋ ์๋ณธ์ด๋ผ ํ๋ก๋น์ ๋ ํธ์ง๊ธฐยท์ฌ๊ธฐ๋(loadTwinModel)์ด
|
|
1883
2407
|
* ์ถ๊ฐ๋ถ์ ์๋๋ค. ๊ธฐ์กด model.equipment ํญ๋ชฉ์ ๋ณด์กด(homeLocation ์ ์ง)ํ๊ณ ์ id ๋ง append(์ถ๊ฐ ์์ location=homeLocation).
|
|
@@ -1912,7 +2436,7 @@ class TwinEngine {
|
|
|
1912
2436
|
/**
|
|
1913
2437
|
* ์คํ ์ค์ด๋ฉด ๊ตฌ์กฐ๋ฅผ ๊ต์ฒดํ์ง ์๋๋ค โ **ํ์ ๋ฌธ์ฅ์ ํ ๊ณณ์ ๋๋ค.**
|
|
1914
2438
|
*
|
|
1915
|
-
* ์ธ์ ์คํธ๋ ์ ๋ ๊ต์ฒด๋ผ, ์ด๋ฒคํธ๋ฅผ
|
|
2439
|
+
* ์ธ์ ์คํธ๋ ์ ๋ ๊ต์ฒด๋ผ, ์ด๋ฒคํธ๋ฅผ ๊ณ์ฐํ๊ณ ์๋ ์ปค๋ ๋ฐ์์ ๋ฐ๋ฅ์ ๋ฐ๊พธ๋ ์
์ด ๋๋ค. ์ง๊ธ์ ๊ฑฐ์ ์ด
|
|
1916
2440
|
* ์ ์ผํ ๋ต์ด์ง๋ง ์ต์ข
ํ์ ์๋๋ค(`adoptStructure` ๋ฐฐ์ ). ๋ ๊ณณ์์ ๊ฐ์ ๋ฌธ์ฅ์ผ๋ก ๊ฑฐ์ ํด์ผ
|
|
1917
2441
|
* ๋์ค์ ์ด ๊ท์น์ ๊ฑท์ด๋ผ ๋ ๊ฑท์ด๋ผ ๊ฒ์ด ํ๋๋ก ๋ณด์ธ๋ค.
|
|
1918
2442
|
*/
|
|
@@ -1943,7 +2467,7 @@ class TwinEngine {
|
|
|
1943
2467
|
* ์ธ ๊ฐ์ง๊ฐ **ํจ๊ป** ์ผ์ด๋์ผ ํ๋ค. ํ๋๋ผ๋ ๋น ์ง๋ฉด ์ธต์ด ์ด๊ธ๋๋ค:
|
|
1944
2468
|
* โ ๋ฆฌ๋น์ โ ์ด ์์ ์ดํ์ ์ด๋ฒคํธ๊ฐ ์ ๋ฒํธ๋ฅผ ๋ฌ๊ณ ๋ค๋๋ค(์ฌ์์ด ๋ง๋๋ฅผ ๋๋ ์ ์๊ฒ)
|
|
1945
2469
|
* โก ์ ์ฅ modelยท๊ตฌ์กฐ ํ โ ์กฐํ๊ฐ ์ ๊ตฌ์กฐ๋ฅผ ๋ณธ๋ค
|
|
1946
|
-
* โข ์ปค๋ โ ์ง๊ธ
|
|
2470
|
+
* โข ์ปค๋ โ ์ง๊ธ ๊ณ์ฐ์ ๋ค์ด๊ฐ๋ ์ด๋ฒคํธ๊ฐ ์ ๊ตฌ์กฐ ์์์ ๊ณ์ฐ๋๋ค
|
|
1947
2471
|
*/
|
|
1948
2472
|
static async adoptStructure(domainId, instanceId, model, comment, origin) {
|
|
1949
2473
|
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
@@ -1956,7 +2480,7 @@ class TwinEngine {
|
|
|
1956
2480
|
throw new Error(`instance "${instanceId}" is running but not registered โ refusing to adopt into an unknown twin`);
|
|
1957
2481
|
const rev = await this.recordStructure(domainId, instanceId, model, comment);
|
|
1958
2482
|
await this.register(domainId, instanceId, reg.kind, model, 'running', undefined, origin);
|
|
1959
|
-
/* ์ปค๋์ **๋ง์ง๋ง์** ์ ํํ๋ค โ ์ ์ฅ์ด ์คํจํ๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ง ์ ๊ตฌ์กฐ๊ฐ ๋์ด, ์ฌ๊ธฐ๋ํ๋ฉด
|
|
2483
|
+
/* ์ปค๋์ **๋ง์ง๋ง์** ์ ํํ๋ค โ ์ ์ฅ์ด ์คํจํ๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ง ์ ๊ตฌ์กฐ๊ฐ ๋์ด, ์ฌ๊ธฐ๋ํ๋ฉด ์๋ฆฌ์ง ์๊ณ
|
|
1960
2484
|
์ ๊ตฌ์กฐ๋ก ๋์๊ฐ๋ค(๊ณ ์น๊ธฐ ์ด๋ ค์ด ์ด๊ธ๋จ์ด๋ค). */
|
|
1961
2485
|
const shift = inst.kernel.adoptStructure(model);
|
|
1962
2486
|
/*
|
|
@@ -1973,14 +2497,14 @@ class TwinEngine {
|
|
|
1973
2497
|
* ์ค๋ค**(๋ฃ์ ๊ฐ์ด ํ๋ฉด์์ ๋ณด์ด์ง ์๋๋ค). ๊ตฌ์กฐ๊ฐ ๋ฐ๋ ์๊ฐ์ด ๊ณง ์บ์๋ฅผ ๋ค์ ๊ทธ๋ฆด ์๊ฐ์ด๋ค.
|
|
1974
2498
|
*
|
|
1975
2499
|
* ์คํจ๋ ํก์ํ๋ค: ํฌ์์ด ๋งํ๋(์: ๋ชจ๋ธ์ ์ค๋ณต id) ์ปค๋์ ์ด๋ฏธ ์ ๊ตฌ์กฐ๋ก ๋๊ณ ์์ผ๋ฏ๋ก ๊ทธ ์ฌ์ค์
|
|
1976
|
-
* ๋๋๋ฆฌ์ง ์๋๋ค โ ๋ค๋ง
|
|
2500
|
+
* ๋๋๋ฆฌ์ง ์๋๋ค โ ๋ค๋ง ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๊ณ ๋งํ๋ค.
|
|
1977
2501
|
*/
|
|
1978
2502
|
await (0, project_structure_js_1.projectStructure)(domainId, instanceId, model, instanceId).catch((err) => (0, log_js_1.twinWarn)(`[twin-engine] "${instanceId}" adopted a new structure but its projected rows were not refreshed โ ${err?.message ?? err}`));
|
|
1979
2503
|
/*
|
|
1980
2504
|
* **๊ตฌ์กฐ๊ฐ ๋ฐ๋ ์๊ฐ์ด ์ํ๊ฐ ๋ฐ๋ ์๊ฐ์ด๋ค** โ ๊ทธ๋ฌ๋ ๋ธ๋ก๋์บ์คํ
ํ๋ค.
|
|
1981
2505
|
*
|
|
1982
2506
|
* โโ ๋ฌด์์ด ๋ฌ๋ (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1983
|
-
* ๊ตฌ์กฐ ์ ํ์ ์ปค๋๋ง ๊ฐ๊ณ
|
|
2507
|
+
* ๊ตฌ์กฐ ์ ํ์ ์ปค๋๋ง ๊ฐ๊ณ ์๋ฆฌ์ง ์๊ณ ๋๋ฌ๋ค. ๊ทธ๋ฐ๋ฐ ํ๋ฉด์ด ๋ณด๋ ๊ฒ ์๋น์๊ฐ ๊ตฌ์กฐ์์ ํ์๋๋ค โ
|
|
1984
2508
|
* ๊ณ์ฝ ๋๋น ํ์ , ์ฃผ๋ชฉ ์ ํธ, ์๋ฆฌ ์. ํ์ฅ์ด ๊ณ์ฝ์ ๊ณ ์ณ ์ ์ธํ ์๊ฐ ์กฐ๊ฑด์ด ์ฑ๋ฆฝํ๋๋ฐ๋, ์ํ
|
|
1985
2509
|
* ๋ธ๋ก๋์บ์คํ
์ด ์์ด์ ์ง๋ ๋ ์ผ์ **๋ค์ ๊ณ์ธก ํ๋ณธ์ด ์ฌ ๋๊น์ง** ์ ํ๋ฉด์ ๋ค๊ณ ์์๋ค(๊ทธ ์ฌ์ด ํค๋
|
|
1986
2510
|
* ๋ฐฐ์ง๋ 4์ด ํด๋ง์ผ๋ก ๋จผ์ ์์, ใ๋ฐฐ์ง์ ์๊ณ ๋ชฉ๋ก์ ์๋ใ ์ด๊ธ๋ ํ๋ฉด์ด ์ค์ ๋ก ๋ณด์๋ค).
|
|
@@ -1999,7 +2523,7 @@ class TwinEngine {
|
|
|
1999
2523
|
* **์ฌ๊ธฐ๋ ์ ์ฑ
์ ์์ฑ ์์ ์ ์ ์ธ์ด๋ค**(ADR-0029 ยง2) โ ํธ์์ ์ ์ฑ
์์ด ์กด์ฌํ ์ ์๋ค.
|
|
2000
2524
|
*
|
|
2001
2525
|
* ์์ ์๋ ์ด ์๋ฆฌ๊ฐ ์์๊ณ `register` ๊ฐ ๊ธฐ๋ณธ๊ฐ(`sim-experiment` = ์ ๋ ์ด๊ธฐํ)์ ๊ฐ์ธํ๋ค. ๊ทธ๋์
|
|
2002
|
-
* ์ ์ธ์ ๋น ๋จ๋ฆฐ ํ๋ก๋น์ ๋์ด **์ฌ๊ธฐ๋๋ง๋ค ์ด๋ ฅ์ ์ง์ฐ๋ ํธ์**์
|
|
2526
|
+
* ์ ์ธ์ ๋น ๋จ๋ฆฐ ํ๋ก๋น์ ๋์ด **์ฌ๊ธฐ๋๋ง๋ค ์ด๋ ฅ์ ์ง์ฐ๋ ํธ์**์ ์๋ฆฌ์ง ์๊ณ ๋ง๋ค์๋ค. ์ด์ ๋ง๋๋ ์ชฝ์ด
|
|
2003
2527
|
* ๋งํด์ผ ํ๋ค: ์ด ํธ์์ด ์๊ธฐ ๊ณผ๊ฑฐ๋ฅผ ์ด๋ป๊ฒ ๋ํ๋์ง๋ ๋ง๋๋ ์ฌ๋์ด ์๋ ์ฌ์ค์ด๋ค.
|
|
2004
2528
|
*/
|
|
2005
2529
|
restartPolicy, comment, origin,
|
|
@@ -2015,12 +2539,12 @@ class TwinEngine {
|
|
|
2015
2539
|
* **๊ตฌ์กฐ๊ฐ ๋ฐ๋์ด๋ ์ญ์ฌ๋ฅผ ์ง์ฐ์ง ์๋๋ค.**
|
|
2016
2540
|
*
|
|
2017
2541
|
* ์์ ์๋ ์๋ช
์ด ๋ค๋ฅด๋ฉด ๊ทธ ํธ์์ ์ ๋์ ํต์งธ๋ก ์ง์ ๋ค. ์ ์ง์ฐ๋ฉด ์ ์ด๋ฒคํธ๋ฅผ ์ ๊ณต์ฅ์ ๋๊ณ
|
|
2018
|
-
*
|
|
2019
|
-
*
|
|
2542
|
+
* ๊ณ์ฐํ๊ฒ ๋์ด ์ด๋ ฅ์ด ๊ฑฐ์ง๋ง์ ํ๊ธฐ ๋๋ฌธ์ด๋ค โ ๋ถ์ค๊ฐ ๋์ด๋ ์์ ์ ์ฌ์ค์ ์ฌ์ฏ ๊ฐ์ง๋ฆฌ ๊ณต์ฅ์
|
|
2543
|
+
* ๊ณ์ฐํ๋ฉด ๊ทธ๋ ์๋ ๋ถ์ค์์ ์ผ์ด ์์๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ์ ํ์ง๊ฐ **์ญ์ฌ๋ฅผ ์๊ฑฐ๋ ๊ฑฐ์ง๋ง์
|
|
2020
2544
|
* ํ๊ฑฐ๋** ๋๋ฟ์ด์๊ณ , ๊ทธ๋์ ๊ณต์ฅ์ ๊ณ ์น ๋๋ง๋ค ์ด๋ ฅ์ ๋ฒ๋ ค์ผ ํ๋ค.
|
|
2021
2545
|
*
|
|
2022
2546
|
* ์ด์ ์
์งธ ๊ธธ๋ก ๊ฐ๋ค: ๋ฐ๋ ๊ตฌ์กฐ๋ฅผ **์ ๋ฆฌ๋น์ **์ผ๋ก ๋จ๊ธฐ๊ณ , ์์ผ๋ก ์ฐ์ด๋ ์ด๋ฒคํธ๊ฐ ๊ทธ ๋ฒํธ๋ฅผ
|
|
2023
|
-
* ๋ฌ๊ณ ๋ค๋๋ค. ์ฌ์์ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ์ง์ ์์ ์ ํํ ๋ค
|
|
2547
|
+
* ๋ฌ๊ณ ๋ค๋๋ค. ์ฌ์์ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ์ง์ ์์ ์ ํํ ๋ค ์ด์ด์ ๊ณ์ฐํ๋ค(`replaySegments`).
|
|
2024
2548
|
*/
|
|
2025
2549
|
await this.recordStructure(domainId, instanceId, model, comment);
|
|
2026
2550
|
await this.register(domainId, instanceId, kind, model, existing?.status === 'running' ? 'stopped' : existing?.status ?? 'stopped', restartPolicy, origin, meta);
|
|
@@ -2172,7 +2696,7 @@ class TwinEngine {
|
|
|
2172
2696
|
* ์์คํํธ ์ฌ๋ฃ๋ฅผ **์ฌ๊ธฐ์ ํ์คํ ํ๋ณดํ๋ค.**
|
|
2173
2697
|
* `start()` ๋ ๋๊ธฐ๋ผ ์ค์ค๋ก ์บ์๋ฅผ ์ฝ์ ์ ์์ด์ `recovered` ์ ๋ฏธ๋ฆฌ ๋ด๊ฒจ ์๊ธฐ๋ฅผ ๊ธฐ๋ํ๋๋ฐ,
|
|
2174
2698
|
* ๊ทธ๊ฑด `bootstrap()` ์ด ๋จผ์ ๋์์ ๋๋ง ์ฐธ์ด๋ค. ๋ถํ
์์์ ๊ธฐ๋๋ฉด ์ด๋ค ๋ ์ ์ฌ๊ณ ๊ฐ ์ด์๋๊ณ
|
|
2175
|
-
* ์ด๋ค ๋ ์
|
|
2699
|
+
* ์ด๋ค ๋ ์ ์๋ฆฌ์ง ์๊ณ ๋น ์ฑ๋ก ๋ฌ๋ค โ ์ฌํ๋์ง ์๋ ๊ฒฐํจ์ด ๊ฐ์ฅ ๋์๋ค.
|
|
2176
2700
|
* ์ฒดํฌํฌ์ธํธ ์บ์ ์ฐ์ (O(1) + ๋ผ์ด๋ธ ํ์์ํ ๋ณด์กด), ์์ผ๋ฉด ์ ๋ replay ํด๋ฐฑ(๋ถํ
๊ณผ ๊ฐ์ ์์).
|
|
2177
2701
|
*/
|
|
2178
2702
|
if (!this.recovered[key] && reg.purpose !== 'bench') {
|
|
@@ -2201,9 +2725,9 @@ class TwinEngine {
|
|
|
2201
2725
|
.getRawOne();
|
|
2202
2726
|
return this.start(instanceId, domainId,
|
|
2203
2727
|
/* ์ปค๋ ์ข
๋ฅยทํ์ค ์ ์ธ์ ๋ ์ง์คํธ๋ฆฌ์ ๋ฐ๋์ ์๋ค(๋ ๋ค NOT NULL). ์์ ์๋ `?? 'wms'` ๋ก
|
|
2204
|
-
๋ฉ์ ๋๋ฐ, ๊ทธ๊ฑด YMS/MES ํธ์์
|
|
2728
|
+
๋ฉ์ ๋๋ฐ, ๊ทธ๊ฑด YMS/MES ํธ์์ **์๋ฆฌ์ง ์๊ณ WMS ๋ก ๋ถํ
**์ํค๋ ๊ธธ์ด์๋ค โ ์ค๋ฅ ์์ด ๋ค๋ฅธ ๊ณต์ฅ์ด ๋ฌ๋ค. */
|
|
2205
2729
|
reg.kind, reg.model,
|
|
2206
|
-
/* ์ ์ฅ๋ ๊ฐ์ ์์์ **์๊ฒฉํ** ์ฝ์๋ค โ ๋ชจ๋ฅด๋ ๊ฐ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ฉ์ฐ๋ฉด ๊ทธ ํธ์์ด
|
|
2730
|
+
/* ์ ์ฅ๋ ๊ฐ์ ์์์ **์๊ฒฉํ** ์ฝ์๋ค โ ๋ชจ๋ฅด๋ ๊ฐ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ฉ์ฐ๋ฉด ๊ทธ ํธ์์ด ์๋ฆฌ์ง ์๊ณ ๋ค๋ฅด๊ฒ ์ฌ๊ธฐ๋ํ๋ค. */
|
|
2207
2731
|
policy, reg.purpose, Number(last?.max ?? 0) || 0);
|
|
2208
2732
|
}
|
|
2209
2733
|
/**
|
|
@@ -2230,7 +2754,7 @@ class TwinEngine {
|
|
|
2230
2754
|
* ์๋๋ฐ ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์๋ใ ์ํ๊ฐ ๋๋ค.
|
|
2231
2755
|
*
|
|
2232
2756
|
* ์ด๊ฒ์ `start` ๊ฐ ์ด๋ฏธ ๋ฐฐ์ด ๊ตํ๊ณผ ๊ฐ์ ์๋ฆฌ๋ค: ๋ถํ
์์์ ๊ธฐ๋๋ฉด ์ด๋ค ๋ ์ ์ํ๊ฐ ์ด์๋๊ณ
|
|
2233
|
-
* ์ด๋ค ๋ ์
|
|
2757
|
+
* ์ด๋ค ๋ ์ ์๋ฆฌ์ง ์๊ณ ๋น ์ฑ๋ก ๋ฌ๋ค โ **์ฌํ๋์ง ์๋ ๊ฒฐํจ์ด ๊ฐ์ฅ ๋์๋ค.** ๊ทธ๋์ ์์์ ๊ธฐ๋์ง ์๊ณ
|
|
2234
2758
|
* ์ด ์๋ฆฌ์์ ํ๋ณดํ๋ค(์ด๋ฏธ ๋ด๊ฒจ ์์ผ๋ฉด ๊ทธ๊ฒ์ ์ด๋ค).
|
|
2235
2759
|
*/
|
|
2236
2760
|
const key = (0, runtime_key_js_1.runtimeKey)(domainId, instanceId);
|
|
@@ -2430,7 +2954,7 @@ class TwinEngine {
|
|
|
2430
2954
|
const agg = new Map();
|
|
2431
2955
|
for (const r of insts) {
|
|
2432
2956
|
/* ๋ฒค์น ์ ์ธ๋ **์ ์ธ์ผ๋ก๋ง** ํ๋จํ๋ค. ์์ ์๋ spaceId ์ด๋ฆ(`bench-`ยท`loadtest*`)์ผ๋ก๋ ์ถ์ธกํ๋๋ฐ,
|
|
2433
|
-
๊ทธ๋ฌ๋ฉด ๊ทธ๋ ๊ฒ ์ด๋ฆ ์ง์ ์ง์ง ์ด์ ๊ณต๊ฐ์ด ๋ชฉ๋ก์์
|
|
2957
|
+
๊ทธ๋ฌ๋ฉด ๊ทธ๋ ๊ฒ ์ด๋ฆ ์ง์ ์ง์ง ์ด์ ๊ณต๊ฐ์ด ๋ชฉ๋ก์์ ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋ค. purpose ๊ฐ ์ ๋ณธ์ด๋ค. */
|
|
2434
2958
|
if (!r.spaceId || r.purpose === 'bench')
|
|
2435
2959
|
continue;
|
|
2436
2960
|
const model = r.model ?? {};
|
|
@@ -2516,7 +3040,7 @@ class TwinEngine {
|
|
|
2516
3040
|
* ๋ค์ ๊ทธ๋ฆฌ๋ฉด ๊ทธ๋๋ก ์ฌ๋ผ์ง๋ค โ ๊ธ์ก์ด ์ฌ๋ผ์ง๊ณ , ์ฌ์ฉ์๋ ์๊ธฐ๊ฐ ๋ฃ์ ๊ฐ์ด ์ด๋๋ก ๊ฐ๋์ง ์ ์ ์๋ค.
|
|
2517
3041
|
* ๊ทธ๋์ ๊ฒน์ผ๋ก ๋ณด๊ดํ ์ ์ธ์ ๋งค๋ฒ ๋ค์ ์น๋๋ค(`engine/local-declarations`).
|
|
2518
3042
|
*
|
|
2519
|
-
* ๋์์ด ์ฌ๋ผ์ก์ผ๋ฉด(๊ตฌ์กฐ๊ฐ ๋ฐ๋์๋ค) ๊ทธ ์ฌ์ค์ ๊ฒฝ๊ณ ๋ก ๋ธ๋ค โ ๊ฐ ๊ณณ ์๋ ์ ์ธ์
|
|
3043
|
+
* ๋์์ด ์ฌ๋ผ์ก์ผ๋ฉด(๊ตฌ์กฐ๊ฐ ๋ฐ๋์๋ค) ๊ทธ ์ฌ์ค์ ๊ฒฝ๊ณ ๋ก ๋ธ๋ค โ ๊ฐ ๊ณณ ์๋ ์ ์ธ์ ์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค.
|
|
2520
3044
|
*/
|
|
2521
3045
|
const prior = await (0, shell_1.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: master.source } });
|
|
2522
3046
|
/*
|
|
@@ -2553,7 +3077,7 @@ class TwinEngine {
|
|
|
2553
3077
|
}
|
|
2554
3078
|
}
|
|
2555
3079
|
const repo = (0, shell_1.getRepository)(twin_space_js_1.TwinSpace);
|
|
2556
|
-
/* ํฉ์น ๊ณต๊ฐ์ ๊ณจ๋์ผ๋ฉด **์๋์ง ๋จผ์ ํ์ธํ๋ค** โ ์๋ ๊ณณ์
|
|
3080
|
+
/* ํฉ์น ๊ณต๊ฐ์ ๊ณจ๋์ผ๋ฉด **์๋์ง ๋จผ์ ํ์ธํ๋ค** โ ์๋ ๊ณณ์ ์๋ฆฌ์ง ์๊ณ ์ ๊ณต๊ฐ์ ๋ง๋ค๋ฉด ์ฌ์ฉ์๋
|
|
2557
3081
|
ํฉ์ณค๋ค๊ณ ๋ฏฟ๊ณ ํ๋ฉด์ ๋ฐ๋ก ๋
ผ๋ค. ํ์ ํจ์๊ฐ ๊ทธ ๊ฒฝ์ฐ ๊ฑฐ์ ํ๋ค. */
|
|
2558
3082
|
const wanted = (into?.spaceId ?? '').trim();
|
|
2559
3083
|
const wantedExists = wanted
|
|
@@ -2564,7 +3088,7 @@ class TwinEngine {
|
|
|
2564
3088
|
model.spaceId = spaceId; // ๋ณด๋(์ปค๋ ์๋น)๋ ๊ฐ์ ๊ณต๊ฐ์ ๊ฐ๋ฆฌ์ผ์ผ ํ๋ค
|
|
2565
3089
|
const existing = await repo.findOne({ where: { domain: { id: domainId }, spaceId } });
|
|
2566
3090
|
if (choice.joined) {
|
|
2567
|
-
/* ๊ฐ์ id ์ ๊ตฌ์ญยท๋๋๋งํฌ๋ ํฉ์งํฉ์ผ๋ก
|
|
3091
|
+
/* ๊ฐ์ id ์ ๊ตฌ์ญยท๋๋๋งํฌ๋ ํฉ์งํฉ์ผ๋ก ํฉ์ณ์ง๋ค โ ๊ตฌ๋ถํ ์ ์๋ ๊ฒ์ ๊ณ ๋ฅด์ง ์๊ณ ๋ฌด์์ด
|
|
2568
3092
|
ํฉ์ณ์ก๋์ง ๋งํ๋ค(์ ๋นํ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ฏ๋ก ๋ง์ง ์๋๋ค). */
|
|
2569
3093
|
}
|
|
2570
3094
|
/*
|
|
@@ -2589,7 +3113,7 @@ class TwinEngine {
|
|
|
2589
3113
|
* ๋ํ ํํ ํฌ์ธํฐ๋ **ํํ์ ์ ์ฅํ ๋ค** ์ค์ ํ id ๋ก ์ฑ์ด๋ค(์๋). ์ฌ๊ธฐ์ ๋ง์คํฐ์ ๋
ผ๋ฆฌ
|
|
2590
3114
|
* id(`r-map` ๋ฐ์)๋ฅผ ๋ฃ์ผ๋ฉด ํํ ํ์ ์์ฑ uuid ๋ฅผ ๋ฐ์ผ๋ฏ๋ก ํฌ์ธํฐ๊ฐ **์ฒ์๋ถํฐ ํ๊ณต์
|
|
2591
3115
|
* ๊ฐ๋ฆฌํจ๋ค** โ ์ค์ ๋ก 13๊ฐ ํ์ฅ์ด ๊ทธ ์ํ์๊ณ ์ ํฉ์ฑ ์ ๊ฒ์ด ์ก์๋ค(2026-08-13). ํ๋ฉด์
|
|
2592
|
-
* ํ์ `isPrimary` ๋ก โ
๋ฅผ ๊ทธ๋ ค์ ์ฆ์์ด ๋ณด์ด์ง ์์๋ค(์ฌ์ค์ด ๋ ๋ฒ์ด๋ฉด ์ด๋ ๊ฒ
|
|
3116
|
+
* ํ์ `isPrimary` ๋ก โ
๋ฅผ ๊ทธ๋ ค์ ์ฆ์์ด ๋ณด์ด์ง ์์๋ค(์ฌ์ค์ด ๋ ๋ฒ์ด๋ฉด ์ด๋ ๊ฒ ๋ค์ด์จ ๊ฒ์ด ์๋ค).
|
|
2593
3117
|
*/
|
|
2594
3118
|
primaryRepresentationId: existing?.primaryRepresentationId ?? null
|
|
2595
3119
|
}));
|
|
@@ -2650,7 +3174,7 @@ class TwinEngine {
|
|
|
2650
3174
|
}
|
|
2651
3175
|
if (running) {
|
|
2652
3176
|
/* ์คํ ์ค์ธ ๋ฏธ๋ฌ โ ๋ฉ์ถ์ง ์๊ณ ์ ํํ๋ค. ๋ฌด์์ด ์ฌ๋ผ์ก๋์ง๋ **๊ฒฝ๊ณ ๋ก ๋งํ๋ค**
|
|
2653
|
-
(๋ฉ์ท๋ค ์ธ์ฐ๋ ๋ง๋๊ฐ ์์ผ๋ฏ๋ก, ๋งํ์ง ์์ผ๋ฉด ์๋ฆฌ ํ๋๊ฐ
|
|
3177
|
+
(๋ฉ์ท๋ค ์ธ์ฐ๋ ๋ง๋๊ฐ ์์ผ๋ฏ๋ก, ๋งํ์ง ์์ผ๋ฉด ์๋ฆฌ ํ๋๊ฐ ์๋ฆฌ์ง ์๊ณ ์์ด์ง๋ค). */
|
|
2654
3178
|
const shift = await this.adoptStructure(domainId, master.source, model, undefined, master.origin);
|
|
2655
3179
|
warnings.push((0, reference_master_js_3.structureAdopted)(shift.rev, shift));
|
|
2656
3180
|
}
|
|
@@ -2667,7 +3191,7 @@ class TwinEngine {
|
|
|
2667
3191
|
*
|
|
2668
3192
|
* ์ธ์ ์คํธ๊ฐ ์ ์ผํ ์ฐ๊ธฐ ๊ฒฝ๋ก๋ค. ์ฌ๊ธฐ์ ์คํจํด๋ ์ธ์ ์คํธ ์์ฒด๋ ์ฑ๊ณต์ผ๋ก ๋๋ค โ
|
|
2669
3193
|
* ํ์ **์๋ณธ์์ ์ธ์ ๋ ๋ค์ ๊ทธ๋ฆด ์ ์๋ ์บ์**์ด๊ณ , ํธ์ ์์ฒด๋ model ๋ก ์ด๋ฏธ ๋์ํ๋ค.
|
|
2670
|
-
* ๋ค๋ง
|
|
3194
|
+
* ๋ค๋ง **์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค**: ๋ชป ์ด์ ์ฐธ์กฐ๋ ์ธ์ ์คํธ ๊ฒฝ๊ณ ๋ก ์ฌ๋ผ๊ฐ๋ค.
|
|
2671
3195
|
*/
|
|
2672
3196
|
try {
|
|
2673
3197
|
const projected = await (0, project_structure_js_1.projectStructure)(domainId, master.source, model, master.source);
|
|
@@ -2681,7 +3205,7 @@ class TwinEngine {
|
|
|
2681
3205
|
*/
|
|
2682
3206
|
if (model?.utcOffsetMinutes === undefined) {
|
|
2683
3207
|
for (const e of (model?.equipment ?? [])) {
|
|
2684
|
-
const hasProfile = (e?.properties ?? []).some(p => String(p?.id) ===
|
|
3208
|
+
const hasProfile = (e?.properties ?? []).some(p => String(p?.id) === ops_contract_1.EMS_PROPERTY.genDailyProfile && String(p?.value ?? '').trim());
|
|
2685
3209
|
if (hasProfile)
|
|
2686
3210
|
warnings.push((0, reference_master_js_3.generationWithoutTimeZone)(String(model?.spaceId ?? ''), String(e.id)));
|
|
2687
3211
|
}
|
|
@@ -2728,6 +3252,19 @@ class TwinEngine {
|
|
|
2728
3252
|
* ๋ชป ๋ณด๋ธ ๊ฒ์ **์ฌ์ค๋ก ๋จ๊ธด๋ค**(ํ์๋ฅผ ์ธ๊ณ ์ฐฝ๋ง๋ค ํ ์ค ๋จ๊ธด๋ค). ์ผํค๋ฉด ใ๋ณด๋๋๋ฐ ํ๋ฉด์ด ๋ก์๋คใ๊ฐ
|
|
2729
3253
|
* ๋๊ณ , ๊ทธ๊ฑด ๊ฐ์ฅ ์ฐพ๊ธฐ ์ด๋ ค์ด ๋ถ๋ฅ๋ค.
|
|
2730
3254
|
*/
|
|
3255
|
+
/**
|
|
3256
|
+
* ๋ธ๋ก๋์บ์คํ
ํ ๊ฑด โ **์ด ๊ฐ๋๊ฐ ๋๊ธฐ์ด ๋์นจ์ ๋ง์ง๋ ๋ชปํ๋ค** (2026-08-27 ์ธก์ ์ผ๋ก ๋ฐ๋ก์ก์).
|
|
3257
|
+
*
|
|
3258
|
+
* 2026-08-14 ์ ์ด ํจ์๋ฅผ ใ๋ฐฉ์ก์ด ํธ์คํธ๋ฅผ ์ฃฝ์ด์ง ๋ชปํ๊ฒใ๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ถ์๋ค. ๊ทธ๊ฒ์ด ์ฌ์ค์ด ์๋๋ค.
|
|
3259
|
+
* ๋๊ธฐ์ด์ด ๋์น ๋ ๋๋ ์์ธ๋ `EventTarget` ์ด ๋ถ๋ฅธ ๋ฆฌ์ค๋ ์์์ ๋๋ค. ๋ฐํ์์ ๋ฆฌ์ค๋ ์์ธ๋ฅผ
|
|
3260
|
+
* ํธ์ถ์์๊ฒ ์ฃผ์ง ์๊ณ uncaughtException ์ผ๋ก ๋ณด๋ธ๋ค. ๊ทธ๋์ ์ด try/catch ์๋ ์ก์ ๊ฒ์ด ์๋ค.
|
|
3261
|
+
* ์ค์ ๋ก ๊ทธ ๋ค 3์ฃผ ๋์ ๋งํ ์ค ์๊ณ ์์๊ณ , 2026-08-27 10:24 ์ ๊ฐ์ ์์ธ๋ก ๋ค์ ์ฃฝ์๋ค.
|
|
3262
|
+
*
|
|
3263
|
+
* ๋์นจ์ ๋ง๋ ๊ฒ์ **ํ ์คํ ์ฐจ๋ก์ ๋ฐํํ๋ ์๋ฅผ ์ํ ์๋๋ก ๋๋ ๊ฒ**์ด๋ค(ยง`PUBLISH_CHUNK`).
|
|
3264
|
+
*
|
|
3265
|
+
* ๊ทธ๋๋ ์ด ๊ฐ๋๋ฅผ ๋จ๊ธฐ๋ ์ด์ ๋ ๋์ด๋ค. `publish` ๊ฐ ์ง์ ๋์ง๋ ๊ฒฝ์ฐ(์ง๋ ฌํ ์คํจ ๋ฑ)๋ฅผ ์ก๊ณ ,
|
|
3266
|
+
* ๋ชป ๋ณด๋ธ ํ๊ทธ์ ์๊ทธ๋์ฒ๋ฅผ ๋๋๋ฆฐ๋ค โ ๋จ๊ฒจ ๋๋ฉด ๊ทธ ํ๊ทธ๊ฐ ์ค๋ฅ ์์ด ์์ํ ๋ก์ ๊ฐ์ ๋ณด์ธ๋ค.
|
|
3267
|
+
*/
|
|
2731
3268
|
static publishGuarded(channel, payload, what) {
|
|
2732
3269
|
try {
|
|
2733
3270
|
shell_1.pubsub.publish(channel, payload);
|
|
@@ -2745,7 +3282,7 @@ class TwinEngine {
|
|
|
2745
3282
|
return false;
|
|
2746
3283
|
}
|
|
2747
3284
|
}
|
|
2748
|
-
static publishEntityData(inst) {
|
|
3285
|
+
static async publishEntityData(inst) {
|
|
2749
3286
|
const domain = inst.domain;
|
|
2750
3287
|
if (!domain)
|
|
2751
3288
|
return;
|
|
@@ -2778,7 +3315,7 @@ class TwinEngine {
|
|
|
2778
3315
|
* ๋ฌธ์์ด๋ก ๋ฐ๊พผ ๋ค ใ๊ฐ๋คใ๋ฅผ ํ์ธํ๊ณ ๋ฒ๋ ธ๋ค.
|
|
2779
3316
|
*
|
|
2780
3317
|
* ๋ฒ์๋ ์ด ์ฐฝ์ ๋ค์ด์จ ์ฌ๊ฑด์์ ๋ชจ์๋ค(`touchedItemKeys`). **๋งํ ์ ์๋ ์ฌ๊ฑด์ด ํ๋๋ผ๋ ์์ผ๋ฉด
|
|
2781
|
-
* ๋ฒ์๋ ์๊ณ ์ ๋ถ ๋ง๋ ๋ค** โ ๋ฏ์ ์ดํ๊ฐ ์ค๋ฉด
|
|
3318
|
+
* ๋ฒ์๋ ์๊ณ ์ ๋ถ ๋ง๋ ๋ค** โ ๋ฏ์ ์ดํ๊ฐ ์ค๋ฉด ์๋ฆฌ์ง ์๊ณ ๋น ๋จ๋ฆฌ๋ ๋์ ๋น์ธ๊ฒ ์์ ํ ์ชฝ์ผ๋ก ๋จ์ด์ง๋ค.
|
|
2782
3319
|
*
|
|
2783
3320
|
* ๊ทธ๋ฆฌ๊ณ ์ฃผ๊ธฐ๋ง๋ค ํ ๋ฒ์ **๋ฌด์กฐ๊ฑด ์ ๋ถ** ๋ง๋ ๋ค(`FULL_BROADCAST_EVERY`). ์ปค๋์ด ์ฌ๊ฑด ์์ด ๋ฌผํ์
|
|
2784
3321
|
* ๋ฐ๊พธ๋ ์๋ฆฌ๊ฐ ์๊ธฐ๋ฉด ๊ทธ ๊ฐ์ด ํ๋ฉด์ ๋จ์ ์ ์๋๋ฐ, ๊ทธ ์ฐฝ์ ๋ช ์ด๋ก ๋ฌถ๋ ๊ทธ๋ฌผ์ด๋ค. **๋ณด์ฅ์ด ์๋๋ผ
|
|
@@ -2794,6 +3331,22 @@ class TwinEngine {
|
|
|
2794
3331
|
inst.fullBroadcastDue = false;
|
|
2795
3332
|
(0, load_meter_js_1.recordPhase)(load, 'deltas', performance.now() - tDelta);
|
|
2796
3333
|
const tPub = performance.now();
|
|
3334
|
+
/*
|
|
3335
|
+
* โโ **ํ ์คํ ์ฐจ๋ก์ ์ํ๊น์ง๋ง ๋ฐํํ๋ค** (2026-08-27 ์ค์ธก์ผ๋ก ๊ณ ์นจ) โโโโโโโโ
|
|
3336
|
+
*
|
|
3337
|
+
* ์ด ๋ฐ๋ณต๋ฌธ์ด ๋๊ธฐ์๋ค. ๊ตฌ๋
์ ๋๊ธฐ์ด์๋ ๋ฒํผ๊ฐ ์๊ณ , ๋ฐํํ๋ ์๊ฐ์ ใ๋ค์ ๊ฐ์ ๋ฌ๋ผใ๋ ์์ฒญ์ด
|
|
3338
|
+
* ๊ฑธ๋ ค ์์ง ์์ผ๋ฉด ์์ธ๋ค. ๊ฐ์ ๊บผ๋ด๋ ์ชฝ์ ๋น๋๊ธฐ๋ผ์ **๋๊ธฐ ๋ฐ๋ณต๋ฌธ์ด ๋๋ ์ค์๋ ํ ๊ฑด๋ ๊บผ๋ด์ง
|
|
3339
|
+
* ๋ชปํ๋ค.** ๊ทธ๋์ N ๊ฑด์ ๋ฐํํ๋ฉด ์ฒซ ๊ฑด๋ง ์ ๋ฌ๋๊ณ ๋๋จธ์ง๊ฐ ์์๊ณ , 1024 ๋ฅผ ๋๋ ์๊ฐ ์์ธ๊ฐ ๋์
|
|
3340
|
+
* ํ๋ก์ธ์ค๊ฐ ๋ด๋ ค๊ฐ๋ค(2026-08-27 10:24 ยท 2026-08-14 ์๋ ๊ฐ์ ์์ธ).
|
|
3341
|
+
*
|
|
3342
|
+
* `PUBLISH_CHUNK` ๋ง๋ค ๋ฃจํ๋ฅผ ๋น์ ์ค๋ค. ๊ทธ ํ์ ์๋น์๊ฐ ๋๊ธฐ์ด์ ๊บผ๋ด ๊ฐ๋ค.
|
|
3343
|
+
*
|
|
3344
|
+
* **๊ฑด๋๋ฐ์ง ์๋๋ค.** ์ด ์ฐฝ์ ๋ฐํ์ ๋๊น์ง ํ๋ค โ ์ค๊ฐ์ ๊ทธ๋ง๋๋ฉด ๊ทธ ํ๊ทธ๊ฐ ๋ก์ ๊ฐ์ผ๋ก ๋จ๋๋ค.
|
|
3345
|
+
* ์ด ํจ์๊ฐ ์ฃผ๊ธฐ๋ณด๋ค ์ค๋ ๊ฑธ๋ฆฌ๋ฉด ๋ค์ ํ์ด๋จธ๋ ๊ทธ๋๋ก ๋์๊ฐ๊ณ (ยง`flushLiveBroadcasts`),
|
|
3346
|
+
* `adjustBroadcastPeriod` ๊ฐ ์ฃผ๊ธฐ๋ฅผ ์ฌ๋ฆฐ๋ค.
|
|
3347
|
+
*/
|
|
3348
|
+
let published = 0;
|
|
3349
|
+
let sinceYield = 0;
|
|
2797
3350
|
for (const { tag, data } of deltas) {
|
|
2798
3351
|
seen.add(tag);
|
|
2799
3352
|
const sig = JSON.stringify(data);
|
|
@@ -2806,8 +3359,26 @@ class TwinEngine {
|
|
|
2806
3359
|
*/
|
|
2807
3360
|
if (!this.publishGuarded('data', { data: { domain, tag, data } }, `data:${inst.id}`))
|
|
2808
3361
|
sigs.delete(tag);
|
|
3362
|
+
published++;
|
|
3363
|
+
if (++sinceYield >= this.PUBLISH_CHUNK) {
|
|
3364
|
+
sinceYield = 0;
|
|
3365
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
3366
|
+
}
|
|
2809
3367
|
}
|
|
2810
3368
|
(0, load_meter_js_1.recordPhase)(load, 'publish', performance.now() - tPub);
|
|
3369
|
+
/*
|
|
3370
|
+
* โโ **๋ช ๊ฑด์ ๋ฐํํ๋์ง ๋จ๊ธด๋ค** (2026-08-27) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
3371
|
+
*
|
|
3372
|
+
* 10:24 ์ ์๋ฒ๊ฐ ์ฃฝ์์ ๋ ๊ทธ ์ฐฝ์ด ๋ช ๊ฑด์ ๋ฐํํ๋์ง ์ ์ ์์๋ค. ๊ทธ ์๊ฐ ์์ผ๋ฉด ใ๋๊ธฐ์ด์ด
|
|
3373
|
+
* ๋์ณค๋คใ๋ ์ฌ์ค๋ง ์๊ณ ๋ฌด์์ด ๋๊ฒผ๋์ง ํ๋จํ ์ ์์ด, ์์ธ์ ์ถ์ธก์ผ๋ก ๊ณ ๋ฅด๊ฒ ๋๋ค.
|
|
3374
|
+
*
|
|
3375
|
+
* ์ํ์ ๋๊ธด ์ฐฝ๋ง ๋จ๊ธด๋ค โ ๋งค ์ฐฝ์ ๋จ๊ธฐ๋ฉด ๋ก๊ทธ๊ฐ ๊ทธ ์์ฒด๋ก ๋ถํ๊ฐ ๋๋ค.
|
|
3376
|
+
*/
|
|
3377
|
+
inst.publishedTotal = (inst.publishedTotal ?? 0) + published;
|
|
3378
|
+
if (published >= this.PUBLISH_CHUNK) {
|
|
3379
|
+
(0, log_js_1.twinLog)(`[twin-engine] "${inst.id}" ์ด๋ฒ ์ฐฝ์์ ${published}๊ฑด ๋ฐํ ` +
|
|
3380
|
+
`(์ ์ฒด ${deltas.length}๊ฑด ์ค ยท ${full ? '์ ๋' : '์ขํ'} ยท ์ฒญํฌ ${this.PUBLISH_CHUNK})`);
|
|
3381
|
+
}
|
|
2811
3382
|
/*
|
|
2812
3383
|
* ์ฌ๋ผ์ง ์ํฐํฐ์ ์๊ทธ๋์ฒ ์ ๋ฆฌ(๋งต ๋ฌดํ ์ฑ์ฅ ๋ฐฉ์ง) โ **์ ๋ถ ๋ง๋ ์ฐฝ์์๋ง.**
|
|
2813
3384
|
* ๋ฒ์๋ฅผ ์ขํ ์ฐฝ์ `seen` ์๋ ๋ง๋ค์ง ์์ ์ํฐํฐ๊ฐ ์์ผ๋ฏ๋ก, ๊ทธ๋ ์ ๋ฆฌํ๋ฉด ์ด์ ์๋ ํ๊ทธ์
|
|
@@ -2846,18 +3417,18 @@ class TwinEngine {
|
|
|
2846
3417
|
return this.snapshot(domainId, instanceId);
|
|
2847
3418
|
}
|
|
2848
3419
|
/*
|
|
2849
|
-
* **๋์ ์๋ ์ค๋
์ท์ด๋ฉด
|
|
3420
|
+
* **๋์ ์๋ ์ค๋
์ท์ด๋ฉด ๊ณ์ฐํ์ง ์๋๋ค.**
|
|
2850
3421
|
*
|
|
2851
|
-
* ๋ฉ์ถ ํธ์์ ์กฐํํ ๋๋ง๋ค ์ ๋์ ์ ๋
|
|
3422
|
+
* ๋ฉ์ถ ํธ์์ ์กฐํํ ๋๋ง๋ค ์ ๋์ ์ ๋ ๊ณ์ฐํ๊ณ ์์๋ค โ ํธ์์ ํ๋๋ ์ ๋๋ ค๋ ๋ชจ๋ธ ์กฐํ๊ฐ
|
|
2852
3423
|
* 4.6~7.7์ด์๋ ์ด์ ๋ค(crew-probe 23,731๊ฑด). ์ค๋
์ท์ ๊ฐ์ ํด๋์ ๊ฒฐ๊ณผ์ด๋ฏ๋ก, ๊ทธ ๋ค๋ก ์ด๋ฒคํธ๋
|
|
2853
|
-
* ๊ตฌ์กฐ ๋ณ๊ฒฝ๋ ์๋ค๋ฉด **๋ค์
|
|
3424
|
+
* ๊ตฌ์กฐ ๋ณ๊ฒฝ๋ ์๋ค๋ฉด **๋ค์ ๊ณ์ฐํด ๋ด์ผ ๊ฐ์ ๊ฐ**์ด๋ค.
|
|
2854
3425
|
*
|
|
2855
|
-
* ์ฐ์ง ์๋ ์กฐ๊ฑด์ ์ข๊ฒ ์ก๋๋ค: ์ง๊ธ์ ๋ฌผ์์ ๋๋ง(์๊ฐ์ฌํ์ ๊ทธ ์์ ๊น์ง
|
|
2856
|
-
* ๋๊ณผ ๊ฐ์ ๋๋ง, ๊ตฌ์กฐ ๋ฆฌ๋น์ ๊น์ง ๊ฐ์ ๋๋ง. ํ๋๋ผ๋ ์ด๊ธ๋๋ฉด
|
|
3426
|
+
* ์ฐ์ง ์๋ ์กฐ๊ฑด์ ์ข๊ฒ ์ก๋๋ค: ์ง๊ธ์ ๋ฌผ์์ ๋๋ง(์๊ฐ์ฌํ์ ๊ทธ ์์ ๊น์ง ๊ณ์ฐํด์ผ ํ๋ค), ๋ฆฌ๋น์ ์ด
|
|
3427
|
+
* ๋๊ณผ ๊ฐ์ ๋๋ง, ๊ตฌ์กฐ ๋ฆฌ๋น์ ๊น์ง ๊ฐ์ ๋๋ง. ํ๋๋ผ๋ ์ด๊ธ๋๋ฉด ๊ณ์ฐํ๋ค โ ์บ์๊ฐ ์ฌ์ค์ ์ด๊ธฐ์ง ์๋๋ค.
|
|
2857
3428
|
*/
|
|
2858
3429
|
const asOfNowRead = untilRevision == null && untilTime == null;
|
|
2859
3430
|
const tip = asOfNowRead ? await this.tipOf(domainId, instanceId).catch(() => null) : null;
|
|
2860
|
-
/* ํ ๋ฒ๋ง ์ฝ๋๋ค โ ๋์ ์์ผ๋ฉด ๊ทธ๋๋ก ์ฐ๊ณ , ์๋๋ฉด ์๋์์ **์ด์ด
|
|
3431
|
+
/* ํ ๋ฒ๋ง ์ฝ๋๋ค โ ๋์ ์์ผ๋ฉด ๊ทธ๋๋ก ์ฐ๊ณ , ์๋๋ฉด ์๋์์ **์ด์ด ๊ณ์ฐํ๋ ์จ์**์ผ๋ก ์ด๋ค. */
|
|
2861
3432
|
const cachedForResume = asOfNowRead && tip ? await this.loadSnapshot(domainId, instanceId).catch(() => null) : null;
|
|
2862
3433
|
if (cachedForResume) {
|
|
2863
3434
|
const state = (0, warm_start_js_1.unwrapState)(cachedForResume.state);
|
|
@@ -2868,22 +3439,22 @@ class TwinEngine {
|
|
|
2868
3439
|
if (!reg?.model)
|
|
2869
3440
|
throw new Error(`twin instance "${instanceId}" not registered (no model to replay)`);
|
|
2870
3441
|
/*
|
|
2871
|
-
* โโ ์ฌ๊ฐ์ ์์
|
|
3442
|
+
* โโ ์ฌ๊ฐ์ ์์ **์ด์ด์ ๊ณ์ฐํ๋ค** (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2872
3443
|
*
|
|
2873
|
-
* ์ฐ๋ฆฌ๋ ์ด๋ฏธ
|
|
2874
|
-
* ์ ๋ถ + ๊ฐ๋ ๋์ ๊ธฐ)์ด ํจ๊ป ์์ผ๋ฉด, ๊ทธ ๋ค์ ์ผ์ด๋ ๊ฒ๋ง
|
|
2875
|
-
* ์ปค๋ ์ํ์ด ์ฆ๋ช
ํ๋ค(0๋ถํฐ
|
|
3444
|
+
* ์ฐ๋ฆฌ๋ ์ด๋ฏธ ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ ๋จ๊ธฐ๊ณ ์๋ค(`saveFoldedSnapshot`). ๊ทธ ์ง์ ์ **์ฌ๊ฐ์ **(๋ฆฌ๋์ ๋ด๋ถ ์ํ
|
|
3445
|
+
* ์ ๋ถ + ๊ฐ๋ ๋์ ๊ธฐ)์ด ํจ๊ป ์์ผ๋ฉด, ๊ทธ ๋ค์ ์ผ์ด๋ ๊ฒ๋ง ๊ณ์ฐํด๋ ๊ฐ์ ๋ต์ด ๋์จ๋ค โ ๊ทธ ๋์น๋
|
|
3446
|
+
* ์ปค๋ ์ํ์ด ์ฆ๋ช
ํ๋ค(0๋ถํฐ ๊ณ์ฐํ๊ธฐ == ์ฌ๊ฐ์ + ๊ผฌ๋ฆฌ).
|
|
2876
3447
|
*
|
|
2877
3448
|
* ์ฐ๋ ์กฐ๊ฑด์ ์ข๊ฒ ์ก๋๋ค: **์ง๊ธ์ ๋ฌผ์์ ๋๋ง**(์๊ฐ์ฌํ์ ๋ชฉํ ์ด์ ์ฌ๊ฐ์ ์ด ํ์ํ๋ฐ ์ง๊ธ์
|
|
2878
3449
|
* ์ต์ ํ๋๋ง ๋จ๊ธด๋ค โ ์ฌ์ฌ์ ๋ค์ ๋จ๊ณ๋ค), ๊ตฌ์กฐ๊ฐ ๊ทธ๋๋ก์ผ ๋๋ง(๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ฉด ๊ทธ ๊ฒฝ๊ณ์์ ๊ฐ๋ผ
|
|
2879
|
-
*
|
|
3450
|
+
* ๊ณ์ฐํด์ผ ํ๋ค), ์ฌ๊ฐ์ ์ด ์ ๋ ๋๋ณด๋ค ์์ค ๋๋ง. ํ๋๋ผ๋ ์ด๊ธ๋๋ฉด 0๋ถํฐ ๊ณ์ฐํ๋ค โ **์บ์๊ฐ ์ฌ์ค์
|
|
2880
3451
|
* ์ด๊ธฐ์ง ์๋๋ค.**
|
|
2881
3452
|
*/
|
|
2882
3453
|
/*
|
|
2883
3454
|
* ์จ์์ ๋ ์ค ํ๋๋ค: **์ง๊ธ**์ ๋ฌผ์ผ๋ฉด ์ต์ ์ฌ๊ฐ์ , **๊ณผ๊ฑฐ**๋ฅผ ๋ฌผ์ผ๋ฉด ์ฌ์ฌ์์ ๋ชฉํ ์ง์ ์ง์ .
|
|
2884
3455
|
*
|
|
2885
|
-
* ๊ณผ๊ฑฐ ์จ์์ ๊ตฌ์กฐ๊ฐ ํ ๋ฒ๋ ๋ฐ๋์ง ์์ ํธ์์์๋ง ์ด๋ค โ ๊ตฌ์กฐ๊ฐ ๊ฐ๋ฆฐ ์ ๋์ ๋ง๋๋ง๋ค ๊ฐ์
|
|
2886
|
-
* ํ๊ณ , ๋ง๋๋ฅผ ๊ฑด๋๋ด ์จ์์ ๊ทธ ๊ฒฝ๊ณ์ ํ์ ์ ์๋๋ค(๊ทธ๋๋ 0๋ถํฐ
|
|
3456
|
+
* ๊ณผ๊ฑฐ ์จ์์ ๊ตฌ์กฐ๊ฐ ํ ๋ฒ๋ ๋ฐ๋์ง ์์ ํธ์์์๋ง ์ด๋ค โ ๊ตฌ์กฐ๊ฐ ๊ฐ๋ฆฐ ์ ๋์ ๋ง๋๋ง๋ค ๊ฐ์ ๊ณ์ฐํด์ผ
|
|
3457
|
+
* ํ๊ณ , ๋ง๋๋ฅผ ๊ฑด๋๋ด ์จ์์ ๊ทธ ๊ฒฝ๊ณ์ ํ์ ์ ์๋๋ค(๊ทธ๋๋ 0๋ถํฐ ๊ณ์ฐํ๋ ๊ฒ์ด ์ณ๋ค).
|
|
2887
3458
|
*/
|
|
2888
3459
|
const structureCount = asOfNowRead
|
|
2889
3460
|
? 0
|
|
@@ -2911,10 +3482,10 @@ class TwinEngine {
|
|
|
2911
3482
|
const cutoffMs = untilTime != null ? Date.parse(untilTime) : NaN;
|
|
2912
3483
|
const useTime = untilTime != null && !Number.isNaN(cutoffMs);
|
|
2913
3484
|
const baseWhere = { domain: { id: domainId }, instanceId };
|
|
2914
|
-
/* ์ด์ด
|
|
3485
|
+
/* ์ด์ด ๊ณ์ฐํ ๋๋ **๊ทธ ๋ค๋ง** ์ฝ๋๋ค โ ์ฌ๊ฐ์ ๊น์ง์ ์ฌ์ค์ ์ด๋ฏธ ์จ์ ์์ ์๋ค. */
|
|
2915
3486
|
const from = resume ? (resume.revision ?? 0) : undefined;
|
|
2916
3487
|
/*
|
|
2917
|
-
* journal-fold: ์ฌ์์ ์ฌ์ค์ ํ๋์ฉ
|
|
3488
|
+
* journal-fold: ์ฌ์์ ์ฌ์ค์ ํ๋์ฉ ๊ณ์ฐํ๋ ๊ฒ์ด๋ฏ๋ก ๊ทธ ๊ตฌ๊ฐ์ ํ์ด ํ์ํ๋ค. ์ปค์(`from`)์ ์๊ฐ
|
|
2918
3489
|
* ์ํ์ด ๊ตฌ๊ฐ์ ์๋ฅด๊ณ , ์ฒดํฌํฌ์ธํธ๊ฐ ์์ชฝ์ ์จ์์ผ๋ก ๋์ ํ๋ค โ ํ ์ ์ฒด๋ฅผ ์ฝ์ง ์๋๋ค.
|
|
2919
3490
|
*/
|
|
2920
3491
|
const rows = await (0, shell_1.getRepository)(twin_event_js_1.TwinEvent).find({
|
|
@@ -2940,14 +3511,14 @@ class TwinEngine {
|
|
|
2940
3511
|
});
|
|
2941
3512
|
const wanted = rows;
|
|
2942
3513
|
/*
|
|
2943
|
-
* **๊ทธ๋์ ๊ณต์ฅ์ผ๋ก
|
|
3514
|
+
* **๊ทธ๋์ ๊ณต์ฅ์ผ๋ก ๊ณ์ฐํ๋ค.**
|
|
2944
3515
|
*
|
|
2945
|
-
* ์์ ์๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์ง๊ธ ๋ฑ๋ก๋ ๋ณด๋ ํ๋๋ก
|
|
2946
|
-
* ๋ค์๋ ์ ์ฌ์ค์ ์ ๊ณต์ฅ์ ๋๊ณ
|
|
3516
|
+
* ์์ ์๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์ง๊ธ ๋ฑ๋ก๋ ๋ณด๋ ํ๋๋ก ๊ณ์ฐํ๋ค. ๊ตฌ์กฐ๊ฐ ๋ฐ๋ ์ ์์ผ๋ฉด ๋ง์ง๋ง, ๋ฐ๋
|
|
3517
|
+
* ๋ค์๋ ์ ์ฌ์ค์ ์ ๊ณต์ฅ์ ๋๊ณ ๊ณ์ฐํ๊ฒ ๋์ด โ ๊ทธ๋ ์๋ ์ค๋น์์ ์ผ์ด ์์๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค.
|
|
2947
3518
|
* (๊ทธ๋์ ์์ ํ๋ก๋น์ ๋์ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ฉด ์ ๋์ ์์ ์ง์ ๋ค. ์ญ์ฌ๋ฅผ ์๊ฑฐ๋ ๊ฑฐ์ง๋ง์ ํ๊ฑฐ๋.)
|
|
2948
3519
|
*
|
|
2949
|
-
* ์ด์ ์ด๋ฒคํธ๊ฐ ์๊ธฐ ๊ตฌ์กฐ๋ฅผ ๋ฌ๊ณ ์ค๋ฏ๋ก, ๋ฆฌ๋น์ ์ด ๋ฐ๋๋ ์ง์ ์์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ํ๋ฉฐ
|
|
2950
|
-
* ๋ฆฌ๋น์ ์ด ํ๋๋ฟ์ด๊ฑฐ๋(๋๋ค์) ์์ ์์ผ๋ฉด(๊ตฌ์กฐ ์ด๋ ฅ ์ด์ ) ์์ ๊ณผ ๋๊ฐ์ด ํ ๋ฒ์
|
|
3520
|
+
* ์ด์ ์ด๋ฒคํธ๊ฐ ์๊ธฐ ๊ตฌ์กฐ๋ฅผ ๋ฌ๊ณ ์ค๋ฏ๋ก, ๋ฆฌ๋น์ ์ด ๋ฐ๋๋ ์ง์ ์์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ํ๋ฉฐ ์ด์ด์ ๊ณ์ฐํ๋ค.
|
|
3521
|
+
* ๋ฆฌ๋น์ ์ด ํ๋๋ฟ์ด๊ฑฐ๋(๋๋ค์) ์์ ์์ผ๋ฉด(๊ตฌ์กฐ ์ด๋ ฅ ์ด์ ) ์์ ๊ณผ ๋๊ฐ์ด ํ ๋ฒ์ ๊ณ์ฐํ๋ค.
|
|
2951
3522
|
*/
|
|
2952
3523
|
const structures = await (0, shell_1.getRepository)(twin_structure_js_1.TwinStructure).find({
|
|
2953
3524
|
where: { domain: { id: domainId }, instanceId },
|
|
@@ -2973,7 +3544,7 @@ class TwinEngine {
|
|
|
2973
3544
|
* **๊ฐ์ฅ ์ ๊ตฌ์กฐ๊ฐ ์ง๊ธ์ ๊ณต์ฅ์ด๋ค** โ ๊ทธ ์๋์์ ์์ง ์๋ฌด ์ผ๋ ์์๋๋ผ๋.
|
|
2974
3545
|
*
|
|
2975
3546
|
* ์ฌํ๋ก๋น์ ๋ ์งํ๊ฐ ์ ํํ ๊ทธ ์ํ๋ค: ๋ถ์ค๋ฅผ ๋ท ๋๋ ธ๋๋ฐ ์ ์ด๋ฒคํธ๋ ์์ง ํ๋๋ ์๋ค. ์ด๋
|
|
2976
|
-
* ๋ง์ง๋ง ์ด๋ฒคํธ์ ๊ตฌ์กฐ๋ก๋ง
|
|
3547
|
+
* ๋ง์ง๋ง ์ด๋ฒคํธ์ ๊ตฌ์กฐ๋ก๋ง ๊ณ์ฐํ๋ฉด ํ๋ฉด์ **์ ๊ณต์ฅ**์ ๋ณด์ฌ์ค๋ค โ ๋ฐฉ๊ธ ๋๋ฆฐ ๊ฒ์ด ์ ๋ณด์ธ๋ค.
|
|
2977
3548
|
* ๊ทธ๋์ ๋ง๋์ ๋์ ์ง๊ธ ๊ตฌ์กฐ๋ฅผ ํ ๋ฒ ๋ ์น๋๋ค(์ด๋ฒคํธ ์๋ ๋ง๋).
|
|
2978
3549
|
*
|
|
2979
3550
|
* **๋ค๋ง "์ง๊ธ" ์ ๋ฌผ์์ ๋๋ง์ด๋ค.** ๊ณผ๊ฑฐ ์์ ์ ๋ฌผ์๋๋ฐ ์ต์ ๊ตฌ์กฐ๋ฅผ ์น์ผ๋ฉด, ๊ทธ ์์ ์ ์๋
|
|
@@ -2984,9 +3555,9 @@ class TwinEngine {
|
|
|
2984
3555
|
if (asOfNow && newest && segments[segments.length - 1]?.model !== newest)
|
|
2985
3556
|
segments.push({ model: newest, events: [] });
|
|
2986
3557
|
/*
|
|
2987
|
-
*
|
|
3558
|
+
* ๊ณ์ฐํ ์ํ์ **์ฃผ์ ์ ํธ์ ์๊ฐ์ ์ฑ์ด๋ค.**
|
|
2988
3559
|
*
|
|
2989
|
-
* ๋ผ์ด๋ธยท์๋ฎฌ์ ์ปค๋์ด ์ ํธ๋ฅผ ์ค์ค๋ก ๋ด์ง๋ง, ์ ๋์
|
|
3560
|
+
* ๋ผ์ด๋ธยท์๋ฎฌ์ ์ปค๋์ด ์ ํธ๋ฅผ ์ค์ค๋ก ๋ด์ง๋ง, ์ ๋์ ๊ณ์ฐํ๋ ์ด ๊ฒฝ๋ก๋ ํ๋ก์ ํฐ ์ํ๋ง ๋ธ๋ค โ ์ ํธ๋
|
|
2990
3561
|
* `nowTime` ๋ ์๋ค. ๊ทธ๋์ **๊ณผ๊ฑฐ๋ฅผ ๋ค์ ๊ณ์ฐํ๋ฉด ์ฃผ์ ๋ ์ผ์ด ํ
๋น์๊ณ **(์ง๋๋ `snap.attentions` ๋ฅผ
|
|
2991
3562
|
* ์ฝ๋๋ค), ๊ธฐ๋๋ผ ์์ง ์์ ํธ์์ ๋ณด๋ ํ๋ฉด๋ ๊ฐ์๋ค. ์ ํธ๋ ์ํ์์ ๊ณ์ฐ๋๋ ๊ฒ์ด๋ฏ๋ก
|
|
2992
3563
|
* ์ฌ๊ธฐ์ ๊ฐ์ ๊ณต์(`deriveAttentions`)์ผ๋ก ์ฑ์ฐ๋ฉด ๋๋ค โ ๋ ๋ฒ์ ๋์ง ์๋๋ค.
|
|
@@ -3000,7 +3571,7 @@ class TwinEngine {
|
|
|
3000
3571
|
* **๊ฐ๋ ์ด๋ ฅ๋ ๋์ด๋ฆฐ๋ค** โ ๋ค์ ๊ณ์ฐํ ํ๋ฉด์ ์ค๋น ๊ณ์ธก์ด ๋น์ด ์๋ ๊ฒ.
|
|
3001
3572
|
*
|
|
3002
3573
|
* OEE ๋ ์ ์์คํ
์ด ๋์ ์ ๋ณด๋ด ์ฃผ์ง ์์ ํธ์คํธ๊ฐ ์ํ ์ ์ด๋ฅผ ์ ๋ถํด ๋ง๋ ๋ค(๊ทธ๋์ ์ปค๋์ด ์๋๋ผ
|
|
3003
|
-
* ์ฌ๊ธฐ ์๋ค). ๊ทธ๋ฐ๋ฐ ๊ทธ ๋์ ๊ธฐ๋ **๋ผ์ด๋ธ์์๋ง** ๋์๊ณ , ์ ๋์
|
|
3574
|
+
* ์ฌ๊ธฐ ์๋ค). ๊ทธ๋ฐ๋ฐ ๊ทธ ๋์ ๊ธฐ๋ **๋ผ์ด๋ธ์์๋ง** ๋์๊ณ , ์ ๋์ ๊ณ์ฐํ๋ ๊ฒฝ๋ก๋ ๊ทธ ๊ณ์ฐ์ ํ์ง ์์๋ค โ
|
|
3004
3575
|
* ๊ณผ๊ฑฐ๋ฅผ ๋ค์ ๊ณ์ฐํ๋ฉด ๋ชจ๋ ์ค๋น๊ฐ "๊ฐ๋ ์ด๋ ฅ์ด ์ ํ ์์" ์ผ๋ก ๋ณด์๋ค.
|
|
3005
3576
|
*
|
|
3006
3577
|
* ์๋ ๊ฒ์ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ ๊ณ์ฐ์ด๋ค: ์
๋ ฅ(`equipment.status` ์ ์ดยท`quality.output`)์ ์ ๋์ ๋ค
|
|
@@ -3010,7 +3581,7 @@ class TwinEngine {
|
|
|
3010
3581
|
* ๊ฐ๋ ์ด๋ ฅ์ด ๋์จ๋ค(๊ทธ ๋ค์ ์ผ์ด๋ ๊ณ ์ฅ์ด ๊ณผ๊ฑฐ ํ๋ฉด์ ์์ด์ง ์๋๋ค).
|
|
3011
3582
|
*/
|
|
3012
3583
|
const oee = new oee_accumulator_js_1.OeeAccumulator();
|
|
3013
|
-
/* ์ฌ๊ฐ์ ์ด ์์ผ๋ฉด ๊ทธ ์์ ๊ผฌ๋ฆฌ๋ง ์น๋๋ค โ ์์ผ๋ฉด ๊ผฌ๋ฆฌ๋ถ๋ง ์ธ์ด ๊ฐ์ฉ๋ฅ ์ด
|
|
3584
|
+
/* ์ฌ๊ฐ์ ์ด ์์ผ๋ฉด ๊ทธ ์์ ๊ผฌ๋ฆฌ๋ง ์น๋๋ค โ ์์ผ๋ฉด ๊ผฌ๋ฆฌ๋ถ๋ง ์ธ์ด ๊ฐ์ฉ๋ฅ ์ด ์๋ฆฌ์ง ์๊ณ ์์์ง๋ค. */
|
|
3014
3585
|
if (resume?.fold?.oee)
|
|
3015
3586
|
oee.restore(resume.fold.oee);
|
|
3016
3587
|
for (const r of wanted) {
|
|
@@ -3031,20 +3602,20 @@ class TwinEngine {
|
|
|
3031
3602
|
const withMetrics = (0, oee_accumulator_js_1.withLiveOee)(based, oee, Number.isFinite(nowMs) ? nowMs : undefined);
|
|
3032
3603
|
return (0, live_attentions_js_1.withLiveAttentions)(withMetrics);
|
|
3033
3604
|
};
|
|
3034
|
-
/*
|
|
3605
|
+
/* ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ ๋จ๊ธด๋ค โ **์ง๊ธ์ ๋ฌผ์์ ๋๋ง**(์๊ฐ์ฌํ ๊ฒฐ๊ณผ๋ฅผ "์ง๊ธ" ์ผ๋ก ์ ์ฅํ๋ฉด ๊ฑฐ์ง์ด ๋๋ค). */
|
|
3035
3606
|
/*
|
|
3036
|
-
*
|
|
3607
|
+
* ๊ณ์ฐํ ์ง์ ์ ๋ฆฌ๋น์ โ ์ฌ์ฌ์ ์ ์ ์ด๋ฆ์ด๋ค. ๊ผฌ๋ฆฌ๋ฅผ ๊ณ์ฐํ์ผ๋ฉด ๊ทธ ๊ผฌ๋ฆฌ์ ๋, ์๋ฌด๊ฒ๋ ์ ์ฝ์์ผ๋ฉด
|
|
3037
3608
|
* ์จ์์ ์๋ฆฌ ๊ทธ๋๋ก๋ค(๋ชจ๋ฅด๋ฉด 0).
|
|
3038
3609
|
*/
|
|
3039
3610
|
const foldedTo = rows.length ? (rows[rows.length - 1]?.revision ?? 0) : (from ?? 0);
|
|
3040
3611
|
const keep = (st, fold) => {
|
|
3041
|
-
/* ์ฌ๊ฐ์ ์ ํจ๊ป ๋จ๊ธด๋ค โ ์ํ๋ง ๋จ๊ธฐ๋ฉด ๋ค์ ๋ฒ์ ๋ 0๋ถํฐ
|
|
3612
|
+
/* ์ฌ๊ฐ์ ์ ํจ๊ป ๋จ๊ธด๋ค โ ์ํ๋ง ๋จ๊ธฐ๋ฉด ๋ค์ ๋ฒ์ ๋ 0๋ถํฐ ๊ณ์ฐํด์ผ ํ๋ค(๊ทธ๊ฒ์ด ์ด ์์
์ ์์ ์ด๋ค).
|
|
3042
3613
|
**๊ตฌ์กฐ๊ฐ ๊ฐ๋ฆฐ ํด๋์๋ ์ฌ๊ฐ์ ์ ๋ถ์ด์ง ์๋๋ค**: ๋ง๋๋ฅผ ๊ฑด๋๋ด ์จ์์ ๊ทธ ๊ฒฝ๊ณ์ ํ์ ์ ์๋๋ค. */
|
|
3043
3614
|
if (asOfNowRead && tip && st) {
|
|
3044
3615
|
void this.saveFoldedSnapshot(domainId, instanceId, { revision: tip.revision, state: st, structureRev: tip.structureRev, fold });
|
|
3045
3616
|
}
|
|
3046
3617
|
/*
|
|
3047
|
-
* ์ฌ์ฌ์๋ **๊ณผ๊ฑฐ๋ฅผ
|
|
3618
|
+
* ์ฌ์ฌ์๋ **๊ณผ๊ฑฐ๋ฅผ ๊ณ์ฐํ์ ๋๋** ํ ์ง์ ์ ๋จ๊ธด๋ค (2026-08-18 ์ค์ธก์ผ๋ก ๊ณ ์นจ).
|
|
3048
3619
|
*
|
|
3049
3620
|
* ์ฒ์์๋ ใ์ง๊ธ ์ฝ๊ธฐใ์์๋ง ๋จ๊ฒผ๋ค. ๊ทธ๋ฐ๋ฐ ๋๋ ํธ์์ ์ง๊ธ ์ฝ๊ธฐ๋ ์ปค๋ ์ค๋
์ท์ผ๋ก ์ฆ์ ๋ตํ๊ณ
|
|
3050
3621
|
* ํด๋์ ๋ฟ์ง ์๋๋ค โ ๊ทธ๋์ ์ฌ์ฌ์ด **์์ํ ๋น์ด ์์๋ค**(์ค์ธก: ์ง์ 0๊ฐ, ์๊ฐ์ฌํ 3.7s ๊ทธ๋๋ก).
|
|
@@ -3065,26 +3636,26 @@ class TwinEngine {
|
|
|
3065
3636
|
return st;
|
|
3066
3637
|
};
|
|
3067
3638
|
/*
|
|
3068
|
-
* ์จ์์ด ์์ผ๋ฉด
|
|
3069
|
-
* ์ ์ฌ๊ฐ์ ๋ ํจ๊ป ๋จ๊ธด๋ค: ๋ค์ ๋ฒ์ ๋ ๊ผฌ๋ฆฌ๋ง
|
|
3639
|
+
* ์จ์์ด ์์ผ๋ฉด **์ด์ด์ ๊ณ์ฐํ๋ค** โ ํ ๊ตฌ์กฐ ์์์๋ง(๊ตฌ์กฐ๊ฐ ๊ฐ๋ฆฌ๋ฉด ์๋ ๋ง๋ ๊ฒฝ๋ก๊ฐ ๋งก๋๋ค).
|
|
3640
|
+
* ์ ์ฌ๊ฐ์ ๋ ํจ๊ป ๋จ๊ธด๋ค: ๋ค์ ๋ฒ์ ๋ ๊ผฌ๋ฆฌ๋ง ๊ณ์ฐํ ์ ์์ด์ผ ์ด ์ง๋ฆ๊ธธ์ด ๊ณ์ ์ฐ๋ค.
|
|
3070
3641
|
*/
|
|
3071
3642
|
if (resume?.fold?.reducer && segments.length <= 1) {
|
|
3072
3643
|
const model = (segments[0]?.model ?? (asOfNow && newest) ?? reg.model);
|
|
3073
|
-
const out = replayFrom(model, resume.fold.reducer, segments[0]?.events ?? []);
|
|
3644
|
+
const out = replayFrom(model, resume.fold.reducer, segments[0]?.events ?? [], replayOptions(reg, domainId));
|
|
3074
3645
|
return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() });
|
|
3075
3646
|
}
|
|
3076
3647
|
if (!segments.length) {
|
|
3077
3648
|
const model = ((asOfNow && newest) || reg.model);
|
|
3078
|
-
const out = replayWithCheckpoint(model, []);
|
|
3649
|
+
const out = replayWithCheckpoint(model, [], replayOptions(reg, domainId));
|
|
3079
3650
|
return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() });
|
|
3080
3651
|
}
|
|
3081
3652
|
if (segments.length === 1) {
|
|
3082
|
-
const out = replayWithCheckpoint(segments[0].model, segments[0].events);
|
|
3653
|
+
const out = replayWithCheckpoint(segments[0].model, segments[0].events, replayOptions(reg, domainId));
|
|
3083
3654
|
return keep(withNow(out.state), { reducer: out.checkpoint, oee: oee.serialize() });
|
|
3084
3655
|
}
|
|
3085
3656
|
/* ์ปค๋ ๊ณ์ฝ๋ `model` ์ด๋ค(0.6.14) โ ๊ฒฝ๊ณ์์ ์ดํ๋ฅผ ๋๋๋ ค ๋ด๋ ๋ธ๋ฆฟ์ง๊ฐ ์ฌ๋ผ์ก๋ค. */
|
|
3086
|
-
const { state, shifts } = replaySegments(segments);
|
|
3087
|
-
/* ๊ฒฝ๊ณ์์ ์ฌ๋ผ์ง ๊ฒ์
|
|
3657
|
+
const { state, shifts } = replaySegments(segments, replayOptions(reg, domainId));
|
|
3658
|
+
/* ๊ฒฝ๊ณ์์ ์ฌ๋ผ์ง ๊ฒ์ ์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค โ ์๊ฐ ์ค์ด๋ ์ด์ ๋ฅผ ์ด๋๊ฐ์๋ ๋จ๊ฒจ์ผ ํ๋ค. */
|
|
3088
3659
|
for (const sh of shifts)
|
|
3089
3660
|
if (sh.equipmentDropped || sh.locationsDropped || sh.personsDropped || sh.assetsDropped)
|
|
3090
3661
|
console.info(`[twin-engine] "${instanceId}" replay crossed a structure change โ dropped ${sh.equipmentDropped} equipment, ${sh.locationsDropped} locations, ${sh.personsDropped} persons, ${sh.assetsDropped} assets that no longer exist.`);
|
|
@@ -3172,10 +3743,10 @@ class TwinEngine {
|
|
|
3172
3743
|
/*
|
|
3173
3744
|
* **๋๊ธฐ ์ ์ ๋จ๊ธด๋ค** โ ์ง๊ธ์ด ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ง์ค์ธ ๋ง์ง๋ง ์๊ฐ์ด๋ค.
|
|
3174
3745
|
*
|
|
3175
|
-
* ๋จ๊ธฐ์ง ์์ผ๋ฉด ๋ค์ ์กฐํ๊ฐ ์ ๋์ ์ ๋ ๋ค์
|
|
3176
|
-
* ์ฒดํฌํฌ์ธํธ ๋ฃจํ๊ฐ 20์ด๋ง๋ค ๋จ์ง๋ง ๊ทธ ์ฌ์ด์ ๋ฉ์ถ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ํต์งธ๋ก ๋ค์
|
|
3746
|
+
* ๋จ๊ธฐ์ง ์์ผ๋ฉด ๋ค์ ์กฐํ๊ฐ ์ ๋์ ์ ๋ ๋ค์ ๊ณ์ฐํ๋ค(๊ทธ ๊ฐ์ ์ด์ฐจํผ ๋ฐฉ๊ธ ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๊ฒ์ด๋ค).
|
|
3747
|
+
* ์ฒดํฌํฌ์ธํธ ๋ฃจํ๊ฐ 20์ด๋ง๋ค ๋จ์ง๋ง ๊ทธ ์ฌ์ด์ ๋ฉ์ถ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ํต์งธ๋ก ๋ค์ ๊ณ์ฐ๋๋ค.
|
|
3177
3748
|
*/
|
|
3178
|
-
await this.persistSnapshot(domainId, id).catch(err => (0, log_js_1.twinError)(`[twin-engine] snapshot on stop fail "${id}"`, err?.message ?? err));
|
|
3749
|
+
await this.persistSnapshot(domainId, id, true).catch(err => (0, log_js_1.twinError)(`[twin-engine] snapshot on stop fail "${id}"`, err?.message ?? err));
|
|
3179
3750
|
/*
|
|
3180
3751
|
* **๋ชจ์ ๋ ์ ๋๋ ์ง๊ธ ํ๋ฆฐ๋ค** โ ์ฃผ๊ธฐ flush ์ฌ์ด(์ต๋ `BROADCAST_COALESCE_MS`)์ ๋ฉ์ถ๋ฉด ๊ทธ ๊ตฌ๊ฐ์
|
|
3181
3752
|
* ์ฌ์ค์ด ์ฌ๋ผ์ง๋ค. ์ค๋
์ท๋ง ๋จ๊ธฐ๋ฉด ์ํ๋ ์ด์๋ **์ ๊ทธ๋ ๊ฒ ๋๋์ง**๊ฐ ๋น๋ค(์ ๋์ด ๋ตํ๋ ๊ฒ์ด๋ค).
|
|
@@ -3204,7 +3775,7 @@ class TwinEngine {
|
|
|
3204
3775
|
* ์ ์ธ์ด ๋ชจ๋ ํ
๋ํธ๋ฅผ ๋ฉ์ถ ์
์ด๋ค. ๋ฌธ ์์์ ๋ง๋ ๊ฒ์ด 1์ฐจ ๋ฐฉ๋ฒฝ์ด๊ณ (`validateScenario`),
|
|
3205
3776
|
* ์ด๊ฒ์ด 2์ฐจ ๋ฐฉ๋ฒฝ์ด๋ค.
|
|
3206
3777
|
*
|
|
3207
|
-
*
|
|
3778
|
+
* **์๋ฆฌ์ง ์๊ณ ์ผํค์ง ์๋๋ค.** ์คํ์ ๋ฉ์ถ๊ณ ๊ทธ ์ฌ์ค์ ๋จ๊ธด๋ค โ ์์ธ๋ฅผ ๋ฌด์ํ๊ณ ๊ณ์ tick ํ๋ฉด
|
|
3208
3779
|
* ๊ฐ์ ์ค๋ฅ๊ฐ ๋งค ์ฃผ๊ธฐ ์์์ง๊ณ , ๊ทธ ํธ์์ "๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ฉด์" ์๋ฌด๊ฒ๋ ์งํํ์ง ์๋๋ค.
|
|
3209
3780
|
*/
|
|
3210
3781
|
/**
|
|
@@ -3334,7 +3905,7 @@ class TwinEngine {
|
|
|
3334
3905
|
* ๋ฏธ๋ฌ โ ๊ด์ธก ์ปค๋๋ก ๋ณด๋ด๊ณ , **์ปค๋งจ๋๊ฐ ๋ธ ์ฌ์ค์ ์ ๋ ํ์ ์ค์ด** ์ฝ์ผ๋ ์๊ฐ ๋ฒํธ๋ฅผ ๋ถ์ฌํ๊ฒ ํ๋ค.
|
|
3335
3906
|
* ๋ฏธ๋ฌ์๋ State ๊ตฌ๋
๋ฐฐ๊ด์ด ์์ด(์๋ฎฌ์ ๊ทธ ๊ฒฝ๋ก๋ก ์ ๋๋ง) ์ปค๋ ๋ฐฉ์ถ์ด ์๋ฌด ๋ฐ๋ ๋ฟ์ง ์๋๋ค.
|
|
3336
3907
|
* ์ฌ๊ธฐ์ DB ๋ฅผ ๋ฐ๋ก ์ฝ์ด ๋ฒํธ๋ฅผ ๋งค๊ธฐ๋ฉด ์ธ๋ฉ๋ชจ๋ฆฌ ์นด์ดํฐ์ ์ด๊ธ๋ ๋ฆฌ๋น์ ์ด ๊ฒน์น๋ค(๊ฒน์นจ์ ์ค๋ฅ๋ฅผ
|
|
3337
|
-
* ๋ด์ง ์๊ณ ์ฌ์ ์์๋ง
|
|
3908
|
+
* ๋ด์ง ์๊ณ ์ฌ์ ์์๋ง ์๋ฆฌ์ง ์๊ณ ๋ค์๋๋ค).
|
|
3338
3909
|
*/
|
|
3339
3910
|
const kernel = inst.kernel;
|
|
3340
3911
|
const emitted = [];
|
|
@@ -3419,7 +3990,7 @@ class TwinEngine {
|
|
|
3419
3990
|
const snap = kernel?.getSnapshot?.() ?? this.snapshot(domainId, id);
|
|
3420
3991
|
return { instanceId: id, attentions: snap?.attentions ?? [] };
|
|
3421
3992
|
});
|
|
3422
|
-
/* ๋ชจ์ผ๋ ๊ท์น(ํ๊น
ยท๊ธํ ์์ยท์๋ฆฌ ์)์ ์์ ํจ์๊ฐ ๋ค๊ณ ์๋ค โ ์ฌ๊ธฐ์ ์์ผ๋ก
|
|
3993
|
+
/* ๋ชจ์ผ๋ ๊ท์น(ํ๊น
ยท๊ธํ ์์ยท์๋ฆฌ ์)์ ์์ ํจ์๊ฐ ๋ค๊ณ ์๋ค โ ์ฌ๊ธฐ์ ์์ผ๋ก ๊ณ์ฐํ์ง ์๋๋ค. */
|
|
3423
3994
|
return (0, attention_digest_js_1.mergeLensAttentions)(lenses, limit);
|
|
3424
3995
|
}
|
|
3425
3996
|
/** ๋ผ์ด๋ธ ์ปค๋(ForecastTwin) โ forecast/divergence ์์ธก ์ฐ์ฐ์ฉ. */
|
|
@@ -3533,6 +4104,51 @@ class TwinEngine {
|
|
|
3533
4104
|
* `offered` ๋ **์ ์๋ ๋ ์ฝ๋ ์**๋ค(๊ฑฐ๋ถ ์ฌ๋ถ ๋ฌด๊ด). ํต๊ณผ์จ์ ์๋ก ๋ค๋ฅธ ๋ ๊ณ์๊ธฐ์์ ๋๋ ๊ณ์ฐํ๋ฉด
|
|
3534
4105
|
* ๋ถ๋ชจ์ ๋ถ์๊ฐ ๋ค๋ฅธ ๊ฒ์ ์ธ๊ฒ ๋๋ฏ๋ก, ํ์๋ฆฌ์์ ๋ณธ ์๋ฅผ ๊ทธ๋๋ก ๋๊ธด๋ค.
|
|
3535
4106
|
*/
|
|
4107
|
+
/**
|
|
4108
|
+
* ์ด ํธ์์ ์ ๋์ด ์ง๊ธ ๋ช ๋ฒ๊น์ง ์ ํ๋ โ **์ ๊ทผ์๋ก ๋ธ๋ค.**
|
|
4109
|
+
*
|
|
4110
|
+
* ๋ ์ง์คํธ๋ฆฌ๋ฅผ ๋ฐ์์ ์ง์ ์์ธํ์ง ์๊ฒ ํ๋ ๊ฒ์ด ์ด ์ ์ฅ์์ ๊ท์จ์ด๋ค(ยง`engine-registry-access`).
|
|
4111
|
+
* ์ง๋ ๊ธฐ๋ก์ ์ฑ์ฐ๋ ๊ธธ์ด ๋ค์ ๋ฒํธ๋ฅผ ์์์ผ ํด์ ์ด์๋ค.
|
|
4112
|
+
*
|
|
4113
|
+
* ํธ์์ด ๋๋ ์ค์ด ์๋๋ฉด 0 ์ด๋ค โ ๊ทธ๋๋ ์ ๋๋ง ์๊ณ ์ด์ด ๋ถ์ผ ๋ฒํธ๋ฅผ ์ปค๋์ด ๋ค๊ณ ์์ง ์๋ค.
|
|
4114
|
+
*/
|
|
4115
|
+
/**
|
|
4116
|
+
* ๋ง๊ฐ๋ ๊ตฌ๊ฐ ์ฌ์ค์ **์ด๋ฆ์ ์ง์ ๋ ์ธ ๋ฒ์์ ์ ์ธ** โ ์ ์
๋ฌธ์ ๋๊ธด๋ค.
|
|
4117
|
+
*
|
|
4118
|
+
* โโ ์ ํธ์คํธ๊ฐ ์ฃผ๋ (2026-08-30) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
4119
|
+
* ์ปค๋์ `new Kernel(domainId, โฆ)` ์ผ๋ก ์๋ฏ๋ก **์๊ธฐ๊ฐ ์ด๋ ํธ์์ธ์ง ๋ชจ๋ฅธ๋ค.** ๊ทธ๋ฐ๋ฐ ์ค๋น ๋ฒํธ๋
|
|
4120
|
+
* ํธ์ ์์์๋ง ํตํ๋ ์ด๋ฆํ๋ผ, ํ ๋๋ฉ์ธ์ ํ์ฅ์ด ๋์ด๋ฉด ์๋ก ๋ค๋ฅธ ์ค๋น์ ๊ฐ์ ๋ ์ด ํ ์ฌ์ค์ด
|
|
4121
|
+
* ๋๋ค. ์ค์ธก์ผ๋ก ๊ทธ ์ผ์ด ๋ฌ๋ค โ ๋ ๋ฐ์ ์์ `002` ๊ฐ ๊ฒน์ณ, ์ฌ๋ฌ ํ์ฅ์ ํจ๊ป ๊ณ์ฐํ๋ ์ฑ๊ณผ ํ๋ฉด์์
|
|
4122
|
+
* ํ์ชฝ ๋ฐ์ ๋์ด ์ฌ๋ผ์ง๋ค.
|
|
4123
|
+
*
|
|
4124
|
+
* ์ ์ธ๋ ์ ์ฒด์ฑ์ **์ปค๋์ด ๋ตํ๋ค**(ยง`FlowEngine.equipmentIdentity`) โ ํ์ ์ ๋ ๊ณณ์ ๋์ง ์๋๋ค.
|
|
4125
|
+
* ํธ์์ด ๋๊ณ ์์ง ์์ผ๋ฉด ์ ์ธ์ ๋ฌผ์ ๊ณณ์ด ์์ผ๋ฏ๋ก ๋ฒ์๋ง ๋๊ธด๋ค(๊ทธ๋๋ ๊ฒน์น์ง๋ ์๋๋ค).
|
|
4126
|
+
*/
|
|
4127
|
+
static factScope(domainId, instanceId) {
|
|
4128
|
+
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
4129
|
+
const kernel = inst?.kernel;
|
|
4130
|
+
if (typeof kernel?.equipmentIdentity !== 'function')
|
|
4131
|
+
return { scopeId: instanceId };
|
|
4132
|
+
return {
|
|
4133
|
+
scopeId: instanceId,
|
|
4134
|
+
identityOf: (kind, localId) => (kind === 'equipment' ? kernel.equipmentIdentity(localId) : undefined)
|
|
4135
|
+
};
|
|
4136
|
+
}
|
|
4137
|
+
static journalHead(domainId, instanceId) {
|
|
4138
|
+
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
4139
|
+
return Number(inst?.revision ?? 0);
|
|
4140
|
+
}
|
|
4141
|
+
/**
|
|
4142
|
+
* ์ ๋์ ๊ทธ๋งํผ ์ ์์ผ๋ ๋ฒํธ๋ฅผ ๋ฐ์ด ์ค๋ค.
|
|
4143
|
+
*
|
|
4144
|
+
* ๋ฐ์ด ์ฃผ์ง ์์ผ๋ฉด ๋ค์์ ๋ผ์ด๋ธ๊ฐ **๊ฐ์ ๋ฒํธ๋ฅผ ๋ค์ ์ด๋ค** โ ๊ฐ์ ์๊ฐ์ ๋ ์ฌ์ค์ ๊ฐ๋ฆด ์ ์๊ฒ ๋๋ค.
|
|
4145
|
+
*/
|
|
4146
|
+
static advanceJournalHead(domainId, instanceId, by) {
|
|
4147
|
+
const inst = this.instances[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
4148
|
+
if (!inst || !(by > 0))
|
|
4149
|
+
return;
|
|
4150
|
+
inst.revision = Number(inst.revision ?? 0) + by;
|
|
4151
|
+
}
|
|
3536
4152
|
static recordIngestResult(domainId, instanceId, offered, rejected, nowMs = Date.now(),
|
|
3537
4153
|
/**
|
|
3538
4154
|
* ๋งคํ์ ํต๊ณผํ๋๋ฐ **์ปค๋์ด ๋ฐ์ง ์์** ์(`ingestLive` ์ ๋ฐํ๊ณผ ๊ฒฌ์ฃผ์ด ์ป๋๋ค).
|
|
@@ -3548,22 +4164,32 @@ class TwinEngine {
|
|
|
3548
4164
|
* **์๋ณธ์ ๋ฟ์ง ๋ชปํ๋ค**๋ฅผ ์ ๋๋ค โ ใ๋ฐ์ ๊ฒ์ด ์๋คใ์ ๊ฐ๋ฅธ๋ค(ยง`recordReadFailure`).
|
|
3549
4165
|
*
|
|
3550
4166
|
* ์ด ๋ฌธ์ด ์๋ ๋์ ์ค ์๋ณธ์ด ๋๊ฒจ๋ ํธ์์ ์กฐํ ๊ฐ๋ฅํ ์ํ์ ๊ทธ ์ฌ์ค์ด ์์๋ค. ํ๋ฉด์ด ๋ณผ ์ ์๋
|
|
3551
|
-
* ๊ฒ์ ใ์ ์ฌ์ค์ด ์๋คใ๋ฟ์ด์๊ณ ๊ทธ๊ฒ์
|
|
4167
|
+
* ๊ฒ์ ใ์ ์ฌ์ค์ด ์๋คใ๋ฟ์ด์๊ณ ๊ทธ๊ฒ์ ใ์ฐ๊ฒฐ๋ ์์คํ
์์ ๋ค์ด์จ ๊ฒ์ด ์๋คใ์ ๊ตฌ๋ณ๋์ง ์๋๋ค โ ์ค์ฆ ์ค์ ์๋ณธ์ด
|
|
3552
4168
|
* ๋๊ธฐ๋ฉด ์ฌ์ฉ์๊ฐ ์์ธ์ ์ฐพ์ ์ ์๋ค.
|
|
3553
4169
|
*
|
|
3554
4170
|
* ๋ก๊ทธ๋ก๋ ๋งํ๊ณ ์์๋ค(์ด๋ํฐ๊ฐ ์ฌ์๋๋ฅผ ๊ฒฝ๊ณ ํ๋ค). ๊ทธ๋ฌ๋ **๋ก๊ทธ๋ ์ฌ๋์ด ๋ณผ ๋๋ง ๊ฐ์ด ์๋ค** โ
|
|
3555
4171
|
* ํ๋ฉด์ด ๋งํ๋ ค๋ฉด ์ํ์ ์์ด์ผ ํ๋ค.
|
|
3556
4172
|
*/
|
|
3557
|
-
static recordIngestReadFailure(domainId, instanceId, reason, nowMs = Date.now(), stream) {
|
|
4173
|
+
static recordIngestReadFailure(domainId, instanceId, reason, nowMs = Date.now(), stream, nextRetryMs) {
|
|
4174
|
+
const key = (0, runtime_key_js_1.runtimeKey)(domainId, instanceId);
|
|
4175
|
+
const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = (0, ingest_health_js_1.newIngestLedger)());
|
|
4176
|
+
(0, ingest_health_js_1.recordReadFailure)(ledger, reason, nowMs, stream, nextRetryMs);
|
|
4177
|
+
}
|
|
4178
|
+
/**
|
|
4179
|
+
* **๋๊ฒผ๋ค๊ฐ ๋์์๋ค** โ ์คํจ ๊ธฐ๋ก์ ์ง์ฐ๊ณ ๊ทธ ์ฌ์ค์ ๋จ๊ธด๋ค (2026-08-27).
|
|
4180
|
+
*
|
|
4181
|
+
* `clearIngestReadFailure` ์ ๋๋์ด ๋๋ค: ์ง์ฐ๊ธฐ๋ง ํ๋ฉด ใ๋๊ธด ์ ์ด ์์๋คใ๊ฐ ํ๋ฉด์์ ์ฌ๋ผ์ง๋ค.
|
|
4182
|
+
*/
|
|
4183
|
+
static recordIngestRecovered(domainId, instanceId, afterFailures, downMs, nowMs = Date.now()) {
|
|
3558
4184
|
const key = (0, runtime_key_js_1.runtimeKey)(domainId, instanceId);
|
|
3559
4185
|
const ledger = this.ingestLedgers[key] ?? (this.ingestLedgers[key] = (0, ingest_health_js_1.newIngestLedger)());
|
|
3560
|
-
(0, ingest_health_js_1.
|
|
4186
|
+
(0, ingest_health_js_1.recordRecovered)(ledger, afterFailures, downMs, nowMs);
|
|
3561
4187
|
}
|
|
3562
4188
|
/**
|
|
3563
4189
|
* ์ฝ๊ธฐ๊ฐ ์ฑ๊ณตํ๋ค โ ๋จ์ ๊ธฐ๋ก์ ์ง์ด๋ค.
|
|
3564
4190
|
*
|
|
3565
4191
|
* **๋น ์ฝ๊ธฐ๋ ์ฑ๊ณต์ด๋ค.** ์๋ณธ์ด ใ์ ๊ฒ์ด ์๋คใ๊ณ ๋ตํ ๊ฒ์ ๋ฟ์๋ค๋ ๋ป์ด๋ฏ๋ก, ๊ทธ๋๋ ๋ถ๋ฅธ๋ค.
|
|
3566
|
-
* ๊ทธ ๋์ ๊ฐ๊ฒ ๋๋ฉด
|
|
4192
|
+
* ๊ทธ ๋์ ๊ฐ๊ฒ ๋๋ฉด ๋ค์ด์จ ๊ฒ์ด ์๋ ์ฐ๊ฒฐ์ด ๋๊ธด ์๋ณธ์ผ๋ก ๋ณด์ธ๋ค.
|
|
3567
4193
|
*/
|
|
3568
4194
|
static clearIngestReadFailure(domainId, instanceId) {
|
|
3569
4195
|
const ledger = this.ingestLedgers[(0, runtime_key_js_1.runtimeKey)(domainId, instanceId)];
|
|
@@ -3588,7 +4214,7 @@ class TwinEngine {
|
|
|
3588
4214
|
* **์๋ณธ์ ์๋๋ฐ ์ธ์ฐ์ง ์์ ๊ฒ์ ์ ๋๋ค** โ ์ด์ ์ ์(ยง`IngestLedger.withheld`).
|
|
3589
4215
|
*
|
|
3590
4216
|
* ์ด๋ํฐ๊ฐ ์ฃผ๊ธฐ๋ง๋ค ๋ถ๋ฌ๋ ๋๋ค: ์ฅ๋ถ๊ฐ ์ด์ ๋ก ๋ฌถ์ด **๋ง์ง๋ง ์๋ก ๋ฎ๋๋ค**(๋์ ํ์ง ์๋๋ค).
|
|
3591
|
-
* `count: 0` ์ ใ๊ทธ ์ด์ ๊ฐ ํ๋ ธ๋คใ๋ก ๊ทธ ์ค์ ์ง์ด๋ค โ
|
|
4217
|
+
* `count: 0` ์ ใ๊ทธ ์ด์ ๊ฐ ํ๋ ธ๋คใ๋ก ๊ทธ ์ค์ ์ง์ด๋ค โ ์๋ฆฌ์ง ์๊ณ ๊ทธ์น๋ฉด ๋ก์ ์๊ฐ ๋จ๋๋ค.
|
|
3592
4218
|
*/
|
|
3593
4219
|
static recordIngestWithheld(domainId, instanceId, reason, count, nowMs = Date.now()) {
|
|
3594
4220
|
const key = (0, runtime_key_js_1.runtimeKey)(domainId, instanceId);
|
|
@@ -3693,7 +4319,7 @@ class TwinEngine {
|
|
|
3693
4319
|
/**
|
|
3694
4320
|
* ๋๋ ์ธ์คํด์ค ์ ์ฒด์ ๊ณ์ธก(๋ชจ๋ํฐ ๋์๋ณด๋์ฉ) โ **์๋ฎฌ๊ณผ ๋ฏธ๋ฌ๋ฅผ ํจ๊ป**.
|
|
3695
4321
|
*
|
|
3696
|
-
* ์์ ์๋ ์๋ฎฌ์ ๊ณ๊ธฐ๊ฐ ์์ด ์ด ๋ชฉ๋ก์์
|
|
4322
|
+
* ์์ ์๋ ์๋ฎฌ์ ๊ณ๊ธฐ๊ฐ ์์ด ์ด ๋ชฉ๋ก์์ ์๋ฆฌ์ง ์๊ณ ๋น ์ก๋ค(๊ณ๊ธฐ๊ฐ `null` ์ด๋ผ ๊ฑธ๋ฌ์ก๋ค). ๋๋ ํธ์
|
|
3697
4323
|
* ๋๋ถ๋ถ์ด ์๋ฎฌ์ธ ์๋ฒ์์ ๊ทธ ๋ชฉ๋ก์ ใ๋ถํ๊ฐ ๊ฑฐ์ ์๋คใ๋ก ๋ณด์๋ค.
|
|
3698
4324
|
*/
|
|
3699
4325
|
static async allMetrics(domainId) {
|
|
@@ -3750,10 +4376,10 @@ class TwinEngine {
|
|
|
3750
4376
|
return null;
|
|
3751
4377
|
const cutoff = untilTime != null ? Date.parse(untilTime) : Infinity;
|
|
3752
4378
|
/*
|
|
3753
|
-
* journal-fold: ์ค๋์ ๋ง์ง๋ง ์ํ๋ ๊ทธ ์ค๋์ ์ผ์ด๋ ์ฌ์ค๋ค์
|
|
4379
|
+
* journal-fold: ์ค๋์ ๋ง์ง๋ง ์ํ๋ ๊ทธ ์ค๋์ ์ผ์ด๋ ์ฌ์ค๋ค์ ๊ณ์ฐํด์ผ ๋์จ๋ค.
|
|
3754
4380
|
*
|
|
3755
4381
|
* **์์ด์ง ์กฐ๊ฑด** โ ์ง๊ธ ์ด ์ฝ๊ธฐ์๋ ์ํ์ด ์๊ณ `eventType` ์ ์ธ๋ฑ์ค๋ ์๋ค. ๊ทธ๋์ ์ ๋์ด ํฐ
|
|
3756
|
-
* ํธ์์์๋ ์ด ํ ๋ฒ์ด ๊ทธ ํธ์์ ์ ๋ ์ ์ฒด ์ฃผ์ฌ๋ค. ์ค๋ ์ํ๋ฅผ ๋ฐ๋ก
|
|
4382
|
+
* ํธ์์์๋ ์ด ํ ๋ฒ์ด ๊ทธ ํธ์์ ์ ๋ ์ ์ฒด ์ฃผ์ฌ๋ค. ์ค๋ ์ํ๋ฅผ ๋ฐ๋ก ๊ณ์ฐํด ๋ ํ(ํฌ์)๋ฅผ ๋๊ฑฐ๋,
|
|
3757
4383
|
* `(domain, instanceId, eventType, revision)` ์ธ๋ฑ์ค๋ฅผ ๋ถ์ด๊ณ ์ปค์๋ฅผ ๋ฃ์ผ๋ฉด ์ด ์์ธ๋ ์ฌ๋ผ์ง๋ค.
|
|
3758
4384
|
* ์๊ฐ ์ํ(`cutoff`)์ SQL ๋ก ๋ด๋ ค๋ ์ ๋ฐ์ ์ค๋ค.
|
|
3759
4385
|
*/
|