@things-factory/headless-twin 10.0.18 โ 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/engine/canonical-ingest.d.ts +10 -1
- package/dist-server/engine/canonical-ingest.js +110 -33
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/event-time.d.ts +25 -0
- package/dist-server/engine/event-time.js +98 -0
- package/dist-server/engine/event-time.js.map +1 -0
- package/dist-server/engine/index.d.ts +2 -0
- package/dist-server/engine/index.js +23 -0
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/ingest-dedupe.d.ts +18 -6
- package/dist-server/engine/ingest-dedupe.js +201 -15
- package/dist-server/engine/ingest-dedupe.js.map +1 -1
- package/dist-server/engine/ingest-health.d.ts +60 -1
- package/dist-server/engine/ingest-health.js +43 -8
- package/dist-server/engine/ingest-health.js.map +1 -1
- package/dist-server/engine/kpi-fold.d.ts +19 -0
- package/dist-server/engine/kpi-fold.js +4 -1
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.js +23 -3
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +35 -2
- package/dist-server/engine/oee-accumulator.js +56 -4
- package/dist-server/engine/oee-accumulator.js.map +1 -1
- package/dist-server/engine/twin-engine.d.ts +72 -3
- package/dist-server/engine/twin-engine.js +118 -5
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/index.js +21 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.d.ts +5 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js +66 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +1 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.d.ts +5 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js +79 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +1 -0
- package/dist-server/migrations/index.js +5 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/routes.js +19 -16
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/actuation/actuation-advisor.d.ts +60 -0
- package/dist-server/service/actuation/actuation-advisor.js +53 -0
- package/dist-server/service/actuation/actuation-advisor.js.map +1 -0
- package/dist-server/service/actuation/actuation-outcome.d.ts +52 -0
- package/dist-server/service/actuation/actuation-outcome.js +34 -0
- package/dist-server/service/actuation/actuation-outcome.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule-resolver.d.ts +19 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js +161 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule.d.ts +55 -0
- package/dist-server/service/actuation/actuation-rule.js +130 -0
- package/dist-server/service/actuation/actuation-rule.js.map +1 -0
- package/dist-server/service/actuation/approval-gateway.d.ts +20 -0
- package/dist-server/service/actuation/approval-gateway.js +14 -0
- package/dist-server/service/actuation/approval-gateway.js.map +1 -0
- package/dist-server/service/actuation/catch-up-effects.d.ts +16 -0
- package/dist-server/service/actuation/catch-up-effects.js +120 -0
- package/dist-server/service/actuation/catch-up-effects.js.map +1 -0
- package/dist-server/service/actuation/command-dispatcher.d.ts +230 -0
- package/dist-server/service/actuation/command-dispatcher.js +269 -0
- package/dist-server/service/actuation/command-dispatcher.js.map +1 -0
- package/dist-server/service/actuation/command-store.d.ts +11 -0
- package/dist-server/service/actuation/command-store.js +219 -0
- package/dist-server/service/actuation/command-store.js.map +1 -0
- package/dist-server/service/actuation/dispatch-after-approval.d.ts +11 -0
- package/dist-server/service/actuation/dispatch-after-approval.js +73 -0
- package/dist-server/service/actuation/dispatch-after-approval.js.map +1 -0
- package/dist-server/service/actuation/effect-match.d.ts +53 -0
- package/dist-server/service/actuation/effect-match.js +65 -0
- package/dist-server/service/actuation/effect-match.js.map +1 -0
- package/dist-server/service/actuation/index.d.ts +25 -0
- package/dist-server/service/actuation/index.js +30 -0
- package/dist-server/service/actuation/index.js.map +1 -0
- package/dist-server/service/actuation/retry-plan.d.ts +63 -0
- package/dist-server/service/actuation/retry-plan.js +99 -0
- package/dist-server/service/actuation/retry-plan.js.map +1 -0
- package/dist-server/service/actuation/rule-evaluate.d.ts +127 -0
- package/dist-server/service/actuation/rule-evaluate.js +205 -0
- package/dist-server/service/actuation/rule-evaluate.js.map +1 -0
- package/dist-server/service/actuation/rule-loop.d.ts +5 -0
- package/dist-server/service/actuation/rule-loop.js +156 -0
- package/dist-server/service/actuation/rule-loop.js.map +1 -0
- package/dist-server/service/actuation/rule-runner.d.ts +52 -0
- package/dist-server/service/actuation/rule-runner.js +135 -0
- package/dist-server/service/actuation/rule-runner.js.map +1 -0
- package/dist-server/service/actuation/rule-wiring.d.ts +24 -0
- package/dist-server/service/actuation/rule-wiring.js +80 -0
- package/dist-server/service/actuation/rule-wiring.js.map +1 -0
- package/dist-server/service/actuation/settle-effects.d.ts +21 -0
- package/dist-server/service/actuation/settle-effects.js +101 -0
- package/dist-server/service/actuation/settle-effects.js.map +1 -0
- package/dist-server/service/actuation/sweep-dispatch.d.ts +37 -0
- package/dist-server/service/actuation/sweep-dispatch.js +125 -0
- package/dist-server/service/actuation/sweep-dispatch.js.map +1 -0
- package/dist-server/service/actuation/twin-command-resolver.d.ts +120 -0
- package/dist-server/service/actuation/twin-command-resolver.js +406 -0
- package/dist-server/service/actuation/twin-command-resolver.js.map +1 -0
- package/dist-server/service/actuation/twin-command.d.ts +111 -0
- package/dist-server/service/actuation/twin-command.js +170 -0
- package/dist-server/service/actuation/twin-command.js.map +1 -0
- package/dist-server/service/actuation/twin-now.d.ts +41 -0
- package/dist-server/service/actuation/twin-now.js +65 -0
- package/dist-server/service/actuation/twin-now.js.map +1 -0
- package/dist-server/service/index.d.ts +5 -2
- package/dist-server/service/index.js +28 -17
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/actuation-routing.d.ts +60 -0
- package/dist-server/service/reference/actuation-routing.js +126 -0
- package/dist-server/service/reference/actuation-routing.js.map +1 -0
- package/dist-server/service/reference/actuation-target.d.ts +65 -0
- package/dist-server/service/reference/actuation-target.js +94 -0
- package/dist-server/service/reference/actuation-target.js.map +1 -0
- package/dist-server/service/reference/connection-portability-resolver.d.ts +29 -0
- package/dist-server/service/reference/connection-portability-resolver.js +181 -0
- package/dist-server/service/reference/connection-portability-resolver.js.map +1 -0
- package/dist-server/service/reference/connection-portability.d.ts +138 -0
- package/dist-server/service/reference/connection-portability.js +230 -0
- package/dist-server/service/reference/connection-portability.js.map +1 -0
- package/dist-server/service/reference/fill-cadence.d.ts +17 -0
- package/dist-server/service/reference/fill-cadence.js +31 -0
- package/dist-server/service/reference/fill-cadence.js.map +1 -0
- package/dist-server/service/reference/fill-dedupe.d.ts +16 -0
- package/dist-server/service/reference/fill-dedupe.js +63 -0
- package/dist-server/service/reference/fill-dedupe.js.map +1 -0
- package/dist-server/service/reference/fill-loop.d.ts +35 -0
- package/dist-server/service/reference/fill-loop.js +187 -0
- package/dist-server/service/reference/fill-loop.js.map +1 -0
- package/dist-server/service/reference/fill-span.d.ts +10 -0
- package/dist-server/service/reference/fill-span.js +37 -0
- package/dist-server/service/reference/fill-span.js.map +1 -0
- package/dist-server/service/reference/hook-contract.d.ts +149 -22
- package/dist-server/service/reference/hook-contract.js +236 -23
- package/dist-server/service/reference/hook-contract.js.map +1 -1
- package/dist-server/service/reference/hook-rejected.d.ts +25 -0
- package/dist-server/service/reference/hook-rejected.js +48 -0
- package/dist-server/service/reference/hook-rejected.js.map +1 -0
- package/dist-server/service/reference/hook-store.d.ts +3 -0
- package/dist-server/service/reference/hook-store.js +28 -0
- package/dist-server/service/reference/hook-store.js.map +1 -0
- package/dist-server/service/reference/index.d.ts +4 -1
- package/dist-server/service/reference/index.js +5 -1
- package/dist-server/service/reference/index.js.map +1 -1
- package/dist-server/service/reference/live-cadence.d.ts +68 -0
- package/dist-server/service/reference/live-cadence.js +44 -0
- package/dist-server/service/reference/live-cadence.js.map +1 -0
- package/dist-server/service/reference/live-feed-lease.d.ts +15 -0
- package/dist-server/service/reference/live-feed-lease.js +56 -0
- package/dist-server/service/reference/live-feed-lease.js.map +1 -0
- package/dist-server/service/reference/live-ingest.d.ts +21 -0
- package/dist-server/service/reference/live-ingest.js +66 -0
- package/dist-server/service/reference/live-ingest.js.map +1 -0
- package/dist-server/service/reference/reference-adapter.d.ts +355 -2
- package/dist-server/service/reference/reference-adapter.js +19 -1
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-fill-run.d.ts +50 -0
- package/dist-server/service/reference/reference-fill-run.js +142 -0
- package/dist-server/service/reference/reference-fill-run.js.map +1 -0
- package/dist-server/service/reference/reference-fill.d.ts +90 -0
- package/dist-server/service/reference/reference-fill.js +141 -0
- package/dist-server/service/reference/reference-fill.js.map +1 -0
- package/dist-server/service/reference/reference-hook.d.ts +64 -6
- package/dist-server/service/reference/reference-hook.js +265 -27
- package/dist-server/service/reference/reference-hook.js.map +1 -1
- package/dist-server/service/reference/reference-link-groups.d.ts +10 -0
- package/dist-server/service/reference/reference-link-groups.js +15 -0
- package/dist-server/service/reference/reference-link-groups.js.map +1 -0
- package/dist-server/service/reference/reference-links.d.ts +14 -0
- package/dist-server/service/reference/reference-links.js +73 -0
- package/dist-server/service/reference/reference-links.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +1 -0
- package/dist-server/service/reference/reference-live.js +32 -6
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +56 -2
- package/dist-server/service/reference/reference-master.js +33 -3
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.d.ts +27 -0
- package/dist-server/service/reference/reference-resolver.js +79 -1
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +31 -3
- package/dist-server/service/twin-event/twin-event-keys.js +36 -4
- package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
- package/dist-server/service/twin-event/twin-event.d.ts +1 -0
- package/dist-server/service/twin-event/twin-event.js +11 -2
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-model/choose-recipe.d.ts +15 -0
- package/dist-server/service/twin-model/choose-recipe.js +33 -0
- package/dist-server/service/twin-model/choose-recipe.js.map +1 -0
- package/dist-server/service/twin-model/external-resolver.d.ts +76 -0
- package/dist-server/service/twin-model/external-resolver.js +109 -0
- package/dist-server/service/twin-model/external-resolver.js.map +1 -0
- package/dist-server/service/twin-model/project-structure.js +16 -3
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +17 -0
- package/dist-server/service/twin-model/twin-equipment.js +10 -0
- package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
- package/dist-server/service/twin-model/twin-lineage-query.js +75 -1
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.js +94 -5
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-space/twin-space.d.ts +29 -0
- package/dist-server/service/twin-space/twin-space.js +13 -0
- package/dist-server/service/twin-space/twin-space.js.map +1 -1
- package/dist-server/service/twin-subject/event-subjects.d.ts +3 -1
- package/dist-server/service/twin-subject/event-subjects.js +8 -1
- package/dist-server/service/twin-subject/event-subjects.js.map +1 -1
- package/dist-shared/entity-delta.js +1 -1
- package/dist-shared/entity-delta.js.map +1 -1
- package/package.json +7 -7
- package/server/engine/canonical-ingest.ts +119 -33
- package/server/engine/event-time.ts +96 -0
- package/server/engine/index.ts +20 -0
- package/server/engine/ingest-dedupe.ts +203 -27
- package/server/engine/ingest-health.ts +91 -6
- package/server/engine/kpi-fold.ts +24 -1
- package/server/engine/kpi-query.ts +23 -4
- package/server/engine/oee-accumulator.ts +80 -8
- package/server/engine/twin-engine.ts +119 -5
- package/server/index.ts +23 -0
- package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +66 -0
- package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +82 -0
- package/server/migrations/index.ts +5 -1
- package/server/routes.ts +19 -20
- package/server/service/actuation/actuation-advisor.ts +124 -0
- package/server/service/actuation/actuation-outcome.ts +97 -0
- package/server/service/actuation/actuation-rule-resolver.ts +147 -0
- package/server/service/actuation/actuation-rule.ts +139 -0
- package/server/service/actuation/approval-gateway.ts +44 -0
- package/server/service/actuation/catch-up-effects.ts +152 -0
- package/server/service/actuation/command-dispatcher.ts +511 -0
- package/server/service/actuation/command-store.ts +236 -0
- package/server/service/actuation/dispatch-after-approval.ts +71 -0
- package/server/service/actuation/effect-match.ts +124 -0
- package/server/service/actuation/index.ts +27 -0
- package/server/service/actuation/retry-plan.ts +145 -0
- package/server/service/actuation/rule-evaluate.ts +352 -0
- package/server/service/actuation/rule-loop.ts +160 -0
- package/server/service/actuation/rule-runner.ts +216 -0
- package/server/service/actuation/rule-wiring.ts +84 -0
- package/server/service/actuation/settle-effects.ts +115 -0
- package/server/service/actuation/sweep-dispatch.ts +179 -0
- package/server/service/actuation/twin-command-resolver.ts +387 -0
- package/server/service/actuation/twin-command.ts +232 -0
- package/server/service/actuation/twin-now.ts +97 -0
- package/server/service/index.ts +11 -0
- package/server/service/reference/actuation-routing.ts +165 -0
- package/server/service/reference/actuation-target.ts +163 -0
- package/server/service/reference/connection-portability-resolver.ts +171 -0
- package/server/service/reference/connection-portability.ts +285 -0
- package/server/service/reference/fill-cadence.ts +29 -0
- package/server/service/reference/fill-dedupe.ts +66 -0
- package/server/service/reference/fill-loop.ts +153 -0
- package/server/service/reference/fill-span.ts +31 -0
- package/server/service/reference/hook-contract.ts +280 -22
- package/server/service/reference/hook-rejected.ts +53 -0
- package/server/service/reference/hook-store.ts +28 -0
- package/server/service/reference/index.ts +5 -1
- package/server/service/reference/live-cadence.ts +129 -0
- package/server/service/reference/live-feed-lease.ts +56 -0
- package/server/service/reference/live-ingest.ts +94 -0
- package/server/service/reference/reference-adapter.ts +392 -5
- package/server/service/reference/reference-fill-run.ts +165 -0
- package/server/service/reference/reference-fill.ts +223 -0
- package/server/service/reference/reference-hook.ts +355 -32
- package/server/service/reference/reference-link-groups.ts +21 -0
- package/server/service/reference/reference-links.ts +77 -0
- package/server/service/reference/reference-live.ts +30 -5
- package/server/service/reference/reference-master.ts +90 -5
- package/server/service/reference/reference-resolver.ts +77 -2
- package/server/service/twin-event/twin-event-keys.ts +37 -4
- package/server/service/twin-event/twin-event.ts +18 -1
- package/server/service/twin-model/choose-recipe.ts +31 -0
- package/server/service/twin-model/external-resolver.ts +161 -0
- package/server/service/twin-model/project-structure.ts +16 -3
- package/server/service/twin-model/twin-equipment.ts +22 -0
- package/server/service/twin-model/twin-lineage-query.ts +82 -1
- package/server/service/twin-model/twin-model-item-query.ts +95 -4
- package/server/service/twin-model/twin-model-tree-query.ts +1 -1
- package/server/service/twin-space/twin-space.ts +39 -0
- package/server/service/twin-subject/event-subjects.ts +8 -1
- package/shared/entity-delta.ts +1 -1
- package/test/ack-shape-alignment.test.ts +97 -0
- package/test/actuation-approval-door.test.ts +421 -0
- package/test/actuation-dispatch.test.ts +209 -0
- package/test/actuation-effect.test.ts +162 -0
- package/test/actuation-outcome.test.ts +152 -0
- package/test/actuation-rule-runner.test.ts +281 -0
- package/test/actuation-rule.test.ts +266 -0
- package/test/actuation-seam.test.ts +249 -0
- package/test/actuation-settle.test.ts +164 -0
- package/test/actuation-target.test.ts +145 -0
- package/test/canonical-ingest-vocabularies.test.ts +49 -2
- package/test/capability-mapping.test.ts +1 -1
- package/test/choose-recipe.test.ts +117 -0
- package/test/command-store-writes-columns.test.ts +126 -0
- package/test/connection-portability-doors.test.ts +87 -0
- package/test/connector-capability-declaration.test.ts +54 -4
- package/test/declaration-reaches-model.test.ts +43 -0
- package/test/dedupe-transformation.test.ts +112 -0
- package/test/entity-delta.test.ts +1 -1
- package/test/event-subjects.test.ts +2 -1
- package/test/external-resolver.test.ts +171 -0
- package/test/fill-dedupe.test.ts +59 -0
- package/test/fill-loop.test.ts +35 -0
- package/test/first-envelope.test.ts +153 -0
- package/test/fold-shift-dst.test.ts +110 -0
- package/test/home-in-area.test.ts +90 -0
- package/test/hook-rejected-shape.test.ts +86 -0
- package/test/hook-response-sum.test.ts +193 -0
- package/test/hook-sequence.test.ts +333 -0
- package/test/ingest-dedupe.test.ts +56 -0
- package/test/ingest-expected-quiet.test.ts +111 -0
- package/test/ingest-idempotent.test.ts +79 -0
- package/test/ingest-reconcile-four-ways.test.ts +97 -0
- package/test/ingest-rules-header.test.ts +100 -0
- package/test/ingest-window-rolls-unobserved.test.ts +72 -0
- package/test/intake-mapping-parity.test.ts +175 -0
- package/test/live-cadence.test.ts +170 -0
- package/test/live-feed-lease.test.ts +63 -0
- package/test/live-mirror-parity.test.ts +1 -1
- package/test/oee-accumulator.test.ts +3 -3
- package/test/oee-site-calendar.test.ts +146 -0
- package/test/order-and-transaction-split.test.ts +107 -0
- package/test/reference-fill.test.ts +235 -0
- package/test/reference-hook.test.ts +114 -23
- package/test/reference-links.test.ts +56 -0
- package/test/retry-plan.test.ts +139 -0
- package/test/sweep-dispatch.test.ts +191 -0
- package/test/twin-event-keys.test.ts +20 -6
- package/test/twin-model-item-db.test.ts +6 -6
- package/test/twin-model-tree-db.test.ts +6 -6
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* ๋์์ด๋ ์๊ฐ์ ์ ์ ์์ผ๋ฉด **์ ์ฒด๋ฅผ ๋ง๋ค์ง ์๋๋ค**(`undefined`). ๊ทธ๋๋ ๊ฑฐ๋ฅด์ง ์๊ณ ํต๊ณผ์ํจ๋ค โ
|
|
5
|
-
* ๋ชจ๋ฅด๋ ๊ฒ์ ๊ฐ๋ค๊ณ ํ๋จํ๋ฉด ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด ํ๋๋ก ํฉ์ณ์ง๋ค. ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋ค.
|
|
6
|
-
*/
|
|
1
|
+
/** ์ง๊ธ๊น์ง ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ๊ฒ โ ์ข
๋ฅ๋ณ. ์ฝ๊ณ ๋น์ด๋ค. */
|
|
2
|
+
export declare function takeUnidentified(): Record<string, number>;
|
|
7
3
|
export declare function factIdentity(envelope: any): string | undefined;
|
|
8
4
|
/**
|
|
9
5
|
* ์ต๊ทผ์ ๋ณธ ์ ์ฒด๋ฅผ ๊ธฐ์ตํ๋ค โ **ํฌ๊ธฐ์ ์ํ์ ๋๋ค.**
|
|
@@ -21,6 +17,22 @@ export declare class FactDeduper {
|
|
|
21
17
|
static WINDOW: number;
|
|
22
18
|
private seen;
|
|
23
19
|
private order;
|
|
20
|
+
/**
|
|
21
|
+
* ์ด๋ฏธ ์๋ ๊ฒ์ผ๋ก **๋ฏธ๋ฆฌ ๊ธฐ์ตํ๋ค** โ ์ ๋์์ ์ฝ์ด ์ฑ์ธ ๋.
|
|
22
|
+
*
|
|
23
|
+
* โโ ์ ํ์ํ๊ฐ (2026-09-06 ์ธก์ ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
24
|
+
* ์ด ๊ธฐ์ต์ ํ๋ก์ธ์ค ์์๋ง ์๋ค. ์ฌ๊ธฐ๋ํ๋ฉด ๋น์์ง๊ณ , ๊ทธ ๋ค backfill ์ ๋๋ฆฌ๋ฉด **์ด๋ฏธ ์ ๋์
|
|
25
|
+
* ์๋ ์ฌ์ค๋ ใ์ฒ์ ๋ณธ ๊ฒใ**์ด ๋๋ค.
|
|
26
|
+
*
|
|
27
|
+
* ์ค์ ๋ก ๊ทธ๋ฌ๋ค. `mes-line-a` ๋ฅผ ์ฌ๊ธฐ๋ ๋ค backfill ํ๋ 39๊ฑด์ด ์ ๋ถ ๋ค์ ์์ ์ ๋์ด
|
|
28
|
+
* 44 โ 83๊ฑด์ด ๋๊ณ 44๊ฐ์ง๊ฐ ์ค๋ณต์ด ๋๋ค.
|
|
29
|
+
*
|
|
30
|
+
* push ๊ฒฝ๋ก์์๋ ์ ๋ณด์ธ๋ค. ์ฌ์ ์ก์ด ๋ช ๋ถ ์์ ์ค๋ฏ๋ก ์ฐฝ ์์์ ๊ฑธ๋ฆฐ๋ค. **backfill ์ด ๊ทธ ์ ์ ๋ฅผ
|
|
31
|
+
* ๊นฌ๋ค** โ ๋ช ๋ฌ ์ ์ฌ์ค์ ์ง๊ธ ๋ฐ์ผ๋ ์ฌ๊ธฐ๋ ํ ๋ฒ์ด๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ํต์งธ๋ก ๋ค์ ์๋๋ค.
|
|
32
|
+
*
|
|
33
|
+
* ๊ทธ๋์ backfill ์ด ๋ถ๋ฅด๊ธฐ ์ ์ ๊ทธ ๊ตฌ๊ฐ์ ์ ์ฒด๋ฅผ ์ ๋์์ ์ฝ์ด ์ฌ๊ธฐ ๋ฃ๋๋ค.
|
|
34
|
+
*/
|
|
35
|
+
remember(identities: readonly string[]): number;
|
|
24
36
|
/** ์ด ์ฌ์ค์ ๋ณธ ์ ์ด ์๋ โ ์์ผ๋ฉด ๊ธฐ์ตํ๊ณ `false`. */
|
|
25
37
|
private known;
|
|
26
38
|
/**
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
*/
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.FactDeduper = void 0;
|
|
40
|
+
exports.takeUnidentified = takeUnidentified;
|
|
40
41
|
exports.factIdentity = factIdentity;
|
|
41
42
|
/** ์๊ฐ์ ๋ฐ๋ฆฌ์ด๋ก โ ์ฐ๊ฒฐ๋ ์์คํ
์ด ์ค ์๊ฐ์ด ๋จผ์ , ์์ผ๋ฉด ๋ดํฌ์ ์๊ฐ. */
|
|
42
43
|
function timeOf(envelope) {
|
|
@@ -48,22 +49,158 @@ function timeOf(envelope) {
|
|
|
48
49
|
return undefined;
|
|
49
50
|
}
|
|
50
51
|
/**
|
|
51
|
-
* ์ด ๋ดํฌ๊ฐ ๋งํ๋
|
|
52
|
+
* ์ด ๋ดํฌ๊ฐ ๋งํ๋ ๊ฒ์ **๊ฐ๋ฅด๋ ๊ฐ๋ค** โ ํ๋๋ผ๋ ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ์ฌ์ค์ด๋ค.
|
|
52
53
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
54
|
+
* โโ ์์ ์๋ ํ๋๋ง ๊ณจ๋๋ค (2026-09-05 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
55
|
+
* ์๋ ์ด๋ฆ์ ์์๋๋ก ๋ณด๊ณ **๋จผ์ ๊ฑธ๋ฆฌ๋ ํ๋**๋ฅผ ๋์์ผ๋ก ์ผ์๋ค. ใ์ฃผ์ฒด๋ฅผ ๋จผ์ ๋ณธ๋คใ๋ ํ๋จ
|
|
56
|
+
* ์์ฒด๋ ์ณ๋ค โ ์ค๋น ์ฌ์ค์ ใ์ง๊ธ ๋ถ์ด ์๋ ์์
ใ์ ์ฐธ์กฐ๋ก ์ฃ๋๋ค. ๊ทธ๋ฐ๋ฐ **๊ณ ๋ฅด๊ณ ๋๋จธ์ง๋ฅผ
|
|
57
|
+
* ๋ฒ๋ฆฐ ๊ฒ**์ด ๊ฒฐํจ์ด์๋ค.
|
|
58
|
+
*
|
|
59
|
+
* ์ค์ ๋ก ๋ ์ผ: plant ์ด ์ค์ ๋์ ๋ณด๋๋๋ฐ ํ ๊ฑด์ด ์ ๋์ ์ ๋จ์๋ค.
|
|
60
|
+
*
|
|
61
|
+
* seq 36 quality.output moverId EQ-CT-MWELD-01 ยท taskId PR-CT-WIRE-01 ยท goodCount 12
|
|
62
|
+
* seq 41 quality.output moverId EQ-CT-MWELD-01 ยท taskId PR-CT-WIRE-02 ยท goodCount 9
|
|
63
|
+
*
|
|
64
|
+
* ๋ ์ค์ ์ ์๊ฐ์ด ๊ฐ์๊ณ (์๋ณธ์ด ๋์๊ฐ์ ๋ณต์ฌ) `moverId` ๊ฐ `taskId` ๋ณด๋ค ๋จผ์ ๋ผ **๋์ด ํ ์ฌ์ค์ด
|
|
65
|
+
* ๋๋ค.** ๊ฑฐ๋ถ๊ฐ ์๋๋ผ ๋ํ์ด๋ก ์ธ์ด์ก๋ค โ `offered 5 ยท rejected 0 ยท journaled 3`.
|
|
66
|
+
*
|
|
67
|
+
* **๊ตฌ๋ณํ ๊ฐ์ด ์ด๋ฏธ ๋ดํฌ ์์ ์์๋๋ฐ ํ์ ์ด ๊ทธ๊ฒ์ ์ ๋ดค๋ค.**
|
|
68
|
+
*
|
|
69
|
+
* โโ ๊ทธ๋ฆฌ๊ณ EPCIS ๋ ๊ฐ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
70
|
+
* ์ ๋ 246๋ง ๊ฑด์ ํ์ฌ ๊ท์น์ ๋ค์ ๊ฑธ์ด ๋ณด๋ ๊ฒน์น๋ ๋ฌถ์์ด ์ฌ์ฏ์ด์๊ณ , ์ ๋ถ ์ด ๋ชจ์์ด๋ค.
|
|
71
|
+
*
|
|
72
|
+
* ๊ฐ์ EPC ยท ๊ฐ์ ๋ฐ๋ฆฌ์ด
|
|
73
|
+
* โ bizStep receiving action ADD disposition sellable_accessible
|
|
74
|
+
* โก bizStep commissioning action OBSERVE disposition reserved
|
|
75
|
+
*
|
|
76
|
+
* **ํ ๊ฐ์ฒด์ ์๋ก ๋ค๋ฅธ ๊ด์ธก**์ด๋ค. EPCIS ์์ ์ด์ํ ์ผ์ด ์๋๋ฐ ๊ท์น์ด ๊ทธ ์
์ ์ ๋ดค๋ค.
|
|
77
|
+
*
|
|
78
|
+
* โโ ์ ๋ํ๋ ์ชฝ์ด ๋ง๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
79
|
+
* ์ด ํ์ผ์ด ์ค์ค๋ก ์ ์ด ๋ ๊ฐ์ด ๊ทธ๊ฒ์ด๋ค โ ใ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋คใ.
|
|
80
|
+
* ์ง๊ธ ๊ฑฐ๋์ **์๋ฆฌ์ง ์๊ณ ์๋ ์ชฝ**์ด์๋ค.
|
|
81
|
+
*
|
|
82
|
+
* ๋ํ๋ ๋ํ์ด๋ ๊ทธ๋๋ก ๊ฑธ๋ฆฐ๋ค: ๊ฐ์ ๋ดํฌ๋ฅผ ๋ค์ ๋ณด๋ด๋ฉด **์ด ๊ฐ๋ค์ด ์ ๋ถ ๊ฐ๋ค.** ๋ํ๋ ๊ฒ์
|
|
83
|
+
* ใ๋ค๋ฅธ ์ฌ์ค์ ํฉ์น์ง ์๋๋คใ๋ง ๊ฐํด์ง๊ณ ใ๋ํ์ด๋ฅผ ์ก๋๋คใ๋ ์ ์ฝํด์ง๋ค.
|
|
55
84
|
*/
|
|
56
|
-
function
|
|
85
|
+
function discriminatorsOf(envelope) {
|
|
57
86
|
const d = envelope?.data ?? {};
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
return undefined;
|
|
87
|
+
const out = [];
|
|
88
|
+
const put = (name, v) => {
|
|
89
|
+
const t = String(v ?? '').trim();
|
|
90
|
+
if (t)
|
|
91
|
+
out.push(`${name}=${t}`);
|
|
65
92
|
};
|
|
66
|
-
|
|
93
|
+
/*
|
|
94
|
+
* ์ฃผ์ฒดยท์ฐธ์กฐ๋ฅผ **๋ค ์ ๋๋ค.** ์์๋ ๊ฐ์ด ์๋๋ผ ์ด๋ฆ์ผ๋ก ๊ณ ์ ๋๋ฏ๋ก ๋ดํฌ๋ง๋ค ํ๋ค๋ฆฌ์ง ์๋๋ค.
|
|
95
|
+
*
|
|
96
|
+
* โ **์ด ๋ชฉ๋ก์ ๊ณ์ฝ์ `identity` ์ ์ธ์ ์์ผ๋ก ์ฎ๊ธด ๊ฒ์ด๋ค.** ๊ณ์ฝ์ด kind ๋ง๋ค ๋ฌด์์ด ๊ทธ ์ฌ์ค์
|
|
97
|
+
* ๊ฐ๋ฆฌํค๋์ง ์ด๋ฏธ ์ ์ธํ๋๋ฐ(`operational-ingest.ts` ์ `SPECS[kind].identity`), ๊ทธ๊ฒ์ ๋ด๋ณด๋ด์ง
|
|
98
|
+
* ์์์ ์ฌ๊ธฐ๊ฐ ๋ฐ๋ก ๋ค๊ณ ์๋ค.
|
|
99
|
+
*
|
|
100
|
+
* ๊ทธ๋์ ์ kind ๊ฐ ์๊ธฐ๋ฉด ์ฌ๊ธฐ๊ฐ ์กฐ์ฉํ ๋ค์ฒ์ง๋ค. ์ค์ ๋ก ๋ ๋ฒ ๊ทธ๋ฌ๋ค โ `subjectId`(์ฒ๋ถ)์
|
|
101
|
+
* `testableObjectId`(์ํ)๊ฐ ๋น ์ ธ ์์๊ณ , ๊ทธ๋์ ๊ทธ ๋ ์ข
๋ฅ๋ ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค๊ฑฐ๋ ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด
|
|
102
|
+
* ๋ญ์น ์ ์์๋ค.
|
|
103
|
+
*
|
|
104
|
+
* ๊ณ์ฝ์ด `operationalIdentityField(kind)` ๋ฅผ ๋ด๋ณด๋ด๋ฉด ์ด ๋ชฉ๋ก์ ์ง์ด๋ค. ๊ทธ ๋ฌธ์ ์ด์ด ๋์๊ณ
|
|
105
|
+
* ๋ฐฐํฌ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค.
|
|
106
|
+
*/
|
|
107
|
+
put('meter', d.meterId);
|
|
108
|
+
put('equipment', d.equipmentId);
|
|
109
|
+
put('mover', d.moverId); // vocabulary-guard: allow โ ๋ดํฌ์ ์ ์ธ๋ ํ๋ ์ด๋ฆ(์ ์ฅ๋ ๊ณ์ฝ)
|
|
110
|
+
put('task', d.taskId);
|
|
111
|
+
put('order', d.orderId);
|
|
112
|
+
put('person', d.personId);
|
|
113
|
+
put('asset', d.assetId);
|
|
114
|
+
put('location', d.locationId); // vocabulary-guard: allow โ ๊ฐ์
|
|
115
|
+
put('epc', d.epcList?.[0]);
|
|
116
|
+
put('parent', d.parentID);
|
|
117
|
+
put('class', d.quantityList?.[0]?.epcClass);
|
|
118
|
+
put('transformation', d.transformationID);
|
|
119
|
+
/*
|
|
120
|
+
* โโ ์ฃผ์ฒด๊ฐ `subjectId` ์ธ ์ฌ์ค์ด ์๋ค (2026-09-06 ์ธก์ ) โโโโโโโโโโโโโโโโโโโโโโ
|
|
121
|
+
* ๋ถ์ ํฉ ์ฒ๋ถ๊ณผ ์ํ ๊ฒฐ๊ณผ๋ **ํ์ค `TestableObjectID` ์ ๊ฐ์ ์๋ฆฌ**๋ฅผ ์ด๋ค(๋กํธ ยท ์ค๋น ยท ์๋ฆฌ์
|
|
122
|
+
* ๋๋ฃจ ์ฐ๋ ํ๋์ ์ด๋ฆ). ๊ทธ ์ด๋ฆ์ด ์ฌ๊ธฐ ์์ด์ ๋ ์ข
๋ฅ๊ฐ **์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค์๋ค** โ
|
|
123
|
+
* `parts` ๊ฐ ๋น๋ฉด `factIdentity` ๊ฐ `undefined` ๋ฅผ ๋ด๊ณ , ๊ทธ๋ฌ๋ฉด dedupe ๋ฐ์ด๋ค.
|
|
124
|
+
*
|
|
125
|
+
* ์ค์ ๋ก ๊ทธ๋ฌ๋ค. `fillTwinScope` ๋ฅผ ๋ ๋ฒ ๋๋ฆด ๋๋ง๋ค ๊ทธ ๋์ด 7๊ฑด์ฉ ๋ค์ ์์๋ค(์ฒ๋ถ 4 ยท ์ํ 3).
|
|
126
|
+
* ๋๋จธ์ง 34๊ฑด์ ๊ฑธ๋ฌ์ก๋๋ฐ ์ด ๋๋ง ๊ณ์ ๋์๋ค.
|
|
127
|
+
*/
|
|
128
|
+
put('subject', d.subjectId);
|
|
129
|
+
put('spec', d.specId);
|
|
130
|
+
/*
|
|
131
|
+
* ์ํ ๊ฒฐ๊ณผ์ ์ฃผ์ฒด๋ `testableObjectId` ๋ค โ ํ์ค `TestableObjectID` ์ ์ด๋ฆ์ ๊ทธ๋๋ก ์ด๋ค.
|
|
132
|
+
*
|
|
133
|
+
* ์ด ์ด๋ฆ์ด ์์ด์ **๊ฐ์ ๋ช
์ธ๋ก ๊ฐ์ ์๊ฐ์ ์ฐ ์๋ก ๋ค๋ฅธ ๋กํธ๊ฐ ํ ์ฌ์ค๋ก ๋ญ์ณค๋ค.** ์ค๋ณต์ด ์๊ธฐ๋
|
|
134
|
+
* ๊ฒ๋ณด๋ค ๋์๋ค โ ๋ ๋กํธ์ ์ํ ๊ฒฐ๊ณผ ์ค ํ๋๊ฐ ์ฌ๋ผ์ง๋ค.
|
|
135
|
+
*
|
|
136
|
+
* ์ค์ ๋ก `mes-miratek` ์ ๊ฐ์ ์ํ ๊ฒฐ๊ณผ๊ฐ 10๊ฑด ์์๋ค(2026-09-06 ํ์ธ). ๊ทธ๊ฒ์ ๋ญ์น ๊ฒ์ด ์๋๋ผ
|
|
137
|
+
* ๋ฐ๋๋ก dedupe ๋ฅผ ๋ชป ์ง๋ ๊ฒ์ธ๋ฐ, ๊ฐ์ ์๋ฆฌ์์ ๋ญ์น๋ ์ชฝ๋ ์ด๋ ค ์์๋ค.
|
|
138
|
+
*/
|
|
139
|
+
put('object', d.testableObjectId);
|
|
140
|
+
/* ์๋ฃ ์ ์ธ์ ์ฃผ์ฒด โ ใ์ด ์ถ์ ์ฌ๊ธฐ๊น์ง๊ฐ ์ ๋ถ๋คใ๋ฅผ ๋งํ๋ ์ถ ์ด๋ฆ. */
|
|
141
|
+
put('axis', d.completeAxis);
|
|
142
|
+
/*
|
|
143
|
+
* EPCIS ๋ ใ๋ฌด์์ ๋งํ๋ ๊ด์ธก์ธ๊ฐใ๊ฐ ์ด ์
์ผ๋ก ๊ฐ๋ฆฐ๋ค. ํ ๊ฐ์ฒด๊ฐ ํ ์๊ฐ์ ๋ ๊ด์ธก์ ๊ฐ๋
|
|
144
|
+
* ๊ฒ์ ํ์ค์์ ์ ์์ด๊ณ , ์ด๊ฒ์ ์ ๋ณด๋ฉด ๋ค์ฃ๊ฒ์ด ์ฌ๋ผ์ง๋ค.
|
|
145
|
+
*/
|
|
146
|
+
put('bizStep', d.bizStep);
|
|
147
|
+
put('action', d.action);
|
|
148
|
+
put('disposition', d.disposition);
|
|
149
|
+
/*
|
|
150
|
+
* โโ ๋ณํ์ **๋ฌด์์ด ๋ฌด์์ผ๋ก ๋์๋**๋ก ๊ฐ๋ฆฐ๋ค (2026-09-07 ์ธก์ ) โโโโโโโโโโโโโ
|
|
151
|
+
* ์ด ์๋ฆฌ๊ฐ ์์ด์ **์ฌ์ค ํ๋๊ฐ ์์ด์ก์ต๋๋ค.** ๊ฑฐ์ ์ด ์๋๋ผ ๋ํ์ด๋ก ์ธ์ด์ ธ์ ๊ฒฝ๊ณ ๋ ์์์ต๋๋ค.
|
|
152
|
+
*
|
|
153
|
+
* ```
|
|
154
|
+
* plant outbox seq 37 in LOT-CT-SIDE-001 24๊ฐ โ out LOT-CT-MAIN-003 12๊ฐ
|
|
155
|
+
* plant outbox seq 42 in LOT-CT-SIDE-001 18๊ฐ โ out LOT-CT-MAIN-004 9๊ฐ
|
|
156
|
+
* transformationID ยท bizStep ยท ์ด๊น์ง ์ ๋ถ ๊ฐ๋ค
|
|
157
|
+
* ์ ๋์ ๋จ์ ๊ฒ LOT-CT-MAIN-003 ํ๋
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* `LOT-CT-MAIN-004` ๋ฅผ ์ด๋ ํจ๋๋ก ๋ง๋ค์๋์ง ํธ์์ด ๋ตํ์ง ๋ชปํ๋ ์ํ์์ต๋๋ค.
|
|
161
|
+
*
|
|
162
|
+
* ๊ทธ๋ฆฌ๊ณ **๊ตฌ๋ณํ ๊ฐ์ด ๋ดํฌ ์์ ์ด๋ฏธ ์์์ต๋๋ค** โ `outputQuantityList[0].epcClass` ๊ฐ ์๋ก
|
|
163
|
+
* ๋ค๋ฆ
๋๋ค. ์ด ํ์ผ ๋จธ๋ฆฌ๋ง์ด ์ ์ด ๋ ๊ทธ ๋ชจ์ ๊ทธ๋๋ก์
๋๋ค: ํ์ ์ด ๊ทธ๊ฒ์ ์ ๋ดค์ต๋๋ค.
|
|
164
|
+
*
|
|
165
|
+
* ์ฐ์ถ๋ง ๋ณด์ง ์๊ณ **์
๋ ฅ๋ ๋ด
๋๋ค.** ๊ฐ์ ๋กํธ๋ฅผ ๊ฐ์ ์ด์ ๋ ๋ฒ ์๋นํ๋ฉด์ ์ฐ์ถ ์ด๋ฆ์ด ๊ฐ์
|
|
166
|
+
* ๊ฒฝ์ฐ(์๋๋ง ๋ค๋ฅธ ๋ถํ )๊ฐ ๋จ๊ณ , ๊ทธ๋ ์
๋ ฅ ์๋์ด ์ ์ผํ ์ฐจ์ด์
๋๋ค. ์๋๊น์ง ๋ฃ๋ ์ด์ ๊ฐ ๊ทธ๊ฒ์
๋๋ค.
|
|
167
|
+
*/
|
|
168
|
+
put('inClass', classOf(d.inputQuantityList));
|
|
169
|
+
put('inEpc', d.inputEPCList?.[0]);
|
|
170
|
+
put('inQty', qtyOf(d.inputQuantityList));
|
|
171
|
+
put('outClass', classOf(d.outputQuantityList));
|
|
172
|
+
put('outEpc', d.outputEPCList?.[0]);
|
|
173
|
+
put('outQty', qtyOf(d.outputQuantityList));
|
|
174
|
+
/*
|
|
175
|
+
* ๋ด๊น์ ์์๋ ๊ฐ์ ์ด์ ๋ก ๋ณธ๋ค โ ํ ํ๋ ํธ์ ์๋ก ๋ค๋ฅธ ๋ฌถ์์ ๊ฐ์ ์ด์ ๋ ๋ฒ ์ค์ผ๋ฉด ๋ค์ฃ๊ฒ์ด
|
|
176
|
+
* ์ฌ๋ผ์ง๋ค. ์ ๋ณํ์์ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ์์์ผ๋ ์ฌ๊ธฐ๋ ํจ๊ป ๋ง๋๋ค(ํ ์ข
๋ฅ๋ง ๊ณ ์น๋ฉด ๋๋จธ์ง์ ๋จ๋๋ค).
|
|
177
|
+
*/
|
|
178
|
+
put('childEpc', d.childEPCs?.[0]);
|
|
179
|
+
put('childClass', classOf(d.childQuantityList));
|
|
180
|
+
put('childQty', qtyOf(d.childQuantityList));
|
|
181
|
+
/*
|
|
182
|
+
* ์ด๋ ์ค๋์ ์ฌ์ค์ธ๊ฐ๋ ์ ์ฒด์ ์ผ๋ถ๋ค. ๊ฐ์ ๊ณต์ ์ ๊ฐ์ ์ด์ ๋ ์ค๋๋ก ๋๋ฆฌ๋ ๊ฒ์ ์ ์์ด๊ณ ,
|
|
183
|
+
* ์ด๊ฒ์ ์ ๋ณด๋ฉด ๋ค์ฃ๊ฒ์ด ์ฌ๋ผ์ง๋ค.
|
|
184
|
+
*/
|
|
185
|
+
put('tx', d.bizTransactionList?.[0]?.bizTransaction);
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
/** ์๋ ๋ชฉ๋ก์ ์ฒซ ์ข
๋ฅ โ ๋ชฉ๋ก์ด ๋น๋ฉด `undefined`(๋น ๋ฌธ์์ด์ ๋ฃ์ง ์๋๋ค). */
|
|
189
|
+
function classOf(list) {
|
|
190
|
+
const first = Array.isArray(list) ? list[0] : undefined;
|
|
191
|
+
const v = first?.epcClass;
|
|
192
|
+
return typeof v === 'string' && v.trim() ? v : undefined;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* ์๋ ๋ชฉ๋ก์ ์๊น์ง ์ ๋๋ค โ ์ข
๋ฅ๊ฐ ๊ฐ๊ณ ์๋๋ง ๋ค๋ฅธ ์ฌ์ค์ ๊ฐ๋ฅธ๋ค.
|
|
196
|
+
*
|
|
197
|
+
* ๋ชฉ๋ก ์ ์ฒด๋ฅผ ์ ๋๋ค. ์ฒซ ์์๋ง ๋ณด๋ฉด ใ๊ฐ์ ๊ฒ ๋ + ๋ค๋ฅธ ๊ฒ ํ๋ใ๊ฐ ์ฒซ ์์๋ก๋ ๊ตฌ๋ณ๋์ง ์๋๋ค.
|
|
198
|
+
*/
|
|
199
|
+
function qtyOf(list) {
|
|
200
|
+
if (!Array.isArray(list) || !list.length)
|
|
201
|
+
return undefined;
|
|
202
|
+
const parts = list.map((x) => `${x?.epcClass ?? ''}:${x?.quantity ?? ''}${x?.uom ? '/' + x.uom : ''}`);
|
|
203
|
+
return parts.join('|');
|
|
67
204
|
}
|
|
68
205
|
/**
|
|
69
206
|
* ์ด ๋ดํฌ๊ฐ ๋งํ๋ ์ฌ์ค์ ์ ์ฒด โ ๊ฐ์ผ๋ฉด ๊ฐ์ ์ฌ์ค์ด๋ค.
|
|
@@ -71,17 +208,42 @@ function targetOf(envelope) {
|
|
|
71
208
|
* ๋์์ด๋ ์๊ฐ์ ์ ์ ์์ผ๋ฉด **์ ์ฒด๋ฅผ ๋ง๋ค์ง ์๋๋ค**(`undefined`). ๊ทธ๋๋ ๊ฑฐ๋ฅด์ง ์๊ณ ํต๊ณผ์ํจ๋ค โ
|
|
72
209
|
* ๋ชจ๋ฅด๋ ๊ฒ์ ๊ฐ๋ค๊ณ ํ๋จํ๋ฉด ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด ํ๋๋ก ํฉ์ณ์ง๋ค. ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋ค.
|
|
73
210
|
*/
|
|
211
|
+
/**
|
|
212
|
+
* ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ์ฌ์ค์ **์ข
๋ฅ๋ณ๋ก** ์ผ๋ค โ dedupe ๋ฐ์ผ๋ก ๋๊ฐ ๊ฒ๋ค.
|
|
213
|
+
*
|
|
214
|
+
* ์ด ์๊ฐ 0์ด ์๋๋ฉด ๊ทธ ์ข
๋ฅ๋ ๋ค์ ๋ฐ์ ๋๋ง๋ค ์ ๋์ ๋ค์ ์๋๋ค. ๊ทธ ์ข
๋ฅ์ ์ฃผ์ฒด ์ด๋ฆ์
|
|
215
|
+
* `discriminatorsOf` ์ ๋ํด์ผ ํ๋ค.
|
|
216
|
+
*/
|
|
217
|
+
const unidentified = {};
|
|
218
|
+
/** ์ง๊ธ๊น์ง ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ๊ฒ โ ์ข
๋ฅ๋ณ. ์ฝ๊ณ ๋น์ด๋ค. */
|
|
219
|
+
function takeUnidentified() {
|
|
220
|
+
const out = { ...unidentified };
|
|
221
|
+
for (const k of Object.keys(unidentified))
|
|
222
|
+
delete unidentified[k];
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
74
225
|
function factIdentity(envelope) {
|
|
75
226
|
const type = String(envelope?.eventType ?? '').trim();
|
|
76
227
|
if (!type)
|
|
77
228
|
return undefined;
|
|
78
|
-
const
|
|
79
|
-
|
|
229
|
+
const parts = discriminatorsOf(envelope);
|
|
230
|
+
/*
|
|
231
|
+
* **์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค๋ฉด dedupe ๋ฐ์ด๋ค** โ ๊ทธ ์ฌ์ค์ ๋ค์ ๋ฐ์ ๋๋ง๋ค ์๋ก ์๋๋ค.
|
|
232
|
+
*
|
|
233
|
+
* ์ค๋ ๊ทธ๊ฒ์ผ๋ก ์ ๋์ด ๋ถํ์๋ค(์ฒ๋ถยท์ํ์ด `subjectId` ๋ฅผ ์ฃผ์ฒด๋ก ์ฐ๋๋ฐ ๊ทธ ์ด๋ฆ์ด ์ ๋ชฉ๋ก์
|
|
234
|
+
* ์์๋ค). ์กฐ์ฉํ `undefined` ๋ฅผ ๋ด๋ฉด ๋ค์ ์ข
๋ฅ์์ ๋ ๋๊ณ ๊ทธ๋๋ ์๋ฌด ํ์ ์ด ์๋ค.
|
|
235
|
+
*
|
|
236
|
+
* ๊ทธ๋์ ๋ฌด์์ด ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค์๋์ง ์ผ๋ค(`unidentified`). ์ธ๋ ๊ฒ์ด์ง ๋ง๋ ๊ฒ์ด ์๋๋ค โ
|
|
237
|
+
* ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ๋ค๊ณ ์ฌ์ค์ ๋ฒ๋ฆฌ๋ฉด ๊ทธ๊ฒ์ด ๋ ๋์๋ค.
|
|
238
|
+
*/
|
|
239
|
+
if (!parts.length) {
|
|
240
|
+
unidentified[type] = (unidentified[type] ?? 0) + 1;
|
|
80
241
|
return undefined;
|
|
242
|
+
}
|
|
81
243
|
const at = timeOf(envelope);
|
|
82
244
|
if (at === undefined)
|
|
83
245
|
return undefined;
|
|
84
|
-
return `${type}|${
|
|
246
|
+
return `${type}|${parts.join('&')}|${at}`;
|
|
85
247
|
}
|
|
86
248
|
/**
|
|
87
249
|
* ์ต๊ทผ์ ๋ณธ ์ ์ฒด๋ฅผ ๊ธฐ์ตํ๋ค โ **ํฌ๊ธฐ์ ์ํ์ ๋๋ค.**
|
|
@@ -101,6 +263,30 @@ class FactDeduper {
|
|
|
101
263
|
}
|
|
102
264
|
/** ๊ธฐ์ตํ๋ ์ ์ฒด์ ์ โ ์ฐฝ. */
|
|
103
265
|
static { this.WINDOW = 20_000; }
|
|
266
|
+
/**
|
|
267
|
+
* ์ด๋ฏธ ์๋ ๊ฒ์ผ๋ก **๋ฏธ๋ฆฌ ๊ธฐ์ตํ๋ค** โ ์ ๋์์ ์ฝ์ด ์ฑ์ธ ๋.
|
|
268
|
+
*
|
|
269
|
+
* โโ ์ ํ์ํ๊ฐ (2026-09-06 ์ธก์ ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
270
|
+
* ์ด ๊ธฐ์ต์ ํ๋ก์ธ์ค ์์๋ง ์๋ค. ์ฌ๊ธฐ๋ํ๋ฉด ๋น์์ง๊ณ , ๊ทธ ๋ค backfill ์ ๋๋ฆฌ๋ฉด **์ด๋ฏธ ์ ๋์
|
|
271
|
+
* ์๋ ์ฌ์ค๋ ใ์ฒ์ ๋ณธ ๊ฒใ**์ด ๋๋ค.
|
|
272
|
+
*
|
|
273
|
+
* ์ค์ ๋ก ๊ทธ๋ฌ๋ค. `mes-line-a` ๋ฅผ ์ฌ๊ธฐ๋ ๋ค backfill ํ๋ 39๊ฑด์ด ์ ๋ถ ๋ค์ ์์ ์ ๋์ด
|
|
274
|
+
* 44 โ 83๊ฑด์ด ๋๊ณ 44๊ฐ์ง๊ฐ ์ค๋ณต์ด ๋๋ค.
|
|
275
|
+
*
|
|
276
|
+
* push ๊ฒฝ๋ก์์๋ ์ ๋ณด์ธ๋ค. ์ฌ์ ์ก์ด ๋ช ๋ถ ์์ ์ค๋ฏ๋ก ์ฐฝ ์์์ ๊ฑธ๋ฆฐ๋ค. **backfill ์ด ๊ทธ ์ ์ ๋ฅผ
|
|
277
|
+
* ๊นฌ๋ค** โ ๋ช ๋ฌ ์ ์ฌ์ค์ ์ง๊ธ ๋ฐ์ผ๋ ์ฌ๊ธฐ๋ ํ ๋ฒ์ด๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ํต์งธ๋ก ๋ค์ ์๋๋ค.
|
|
278
|
+
*
|
|
279
|
+
* ๊ทธ๋์ backfill ์ด ๋ถ๋ฅด๊ธฐ ์ ์ ๊ทธ ๊ตฌ๊ฐ์ ์ ์ฒด๋ฅผ ์ ๋์์ ์ฝ์ด ์ฌ๊ธฐ ๋ฃ๋๋ค.
|
|
280
|
+
*/
|
|
281
|
+
remember(identities) {
|
|
282
|
+
let added = 0;
|
|
283
|
+
for (const id of identities)
|
|
284
|
+
if (id && !this.seen.has(id)) {
|
|
285
|
+
this.known(id);
|
|
286
|
+
added++;
|
|
287
|
+
}
|
|
288
|
+
return added;
|
|
289
|
+
}
|
|
104
290
|
/** ์ด ์ฌ์ค์ ๋ณธ ์ ์ด ์๋ โ ์์ผ๋ฉด ๊ธฐ์ตํ๊ณ `false`. */
|
|
105
291
|
known(identity) {
|
|
106
292
|
if (this.seen.has(identity))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest-dedupe.js","sourceRoot":"","sources":["../../server/engine/ingest-dedupe.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * ๊ฐ์ ์ฌ์ค์ ๋ ๋ฒ ๋ฐ์ผ๋ฉด ํ ๋ฒ๋ง ๋ฐ์ํ๋ค โ **์ ์
๊ฒฝ๊ณ ํ ๊ณณ์์.**\n *\n * โโ ์ ํ์ํ๊ฐ (2026-08-26) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ง๊ธ ์ค๋ณต์ ๋ง๋ ๊ฒ์ ์ปค๋ฅํฐ๋ง๋ค ๊ฐ์ ํ๊ณ ์๋ค. ๊ทธ๋์ ์ปค๋ฅํฐ๊ฐ ๊ทธ๊ฒ์ ์์ผ๋ฉด ํธ์์ด ๊ทธ๋๋ก ๋ ๋ฒ\n * ์ผ๋ค. ์ค์ ๋ก ๊ทธ๋ฌ๋ค: ํ์๊ด ์ปค๋ฅํฐ๊ฐ 10์ด๋ง๋ค ๋ฌผ์ผ๋ฉด์ 10๋ถ๋ง๋ค ๋ฐ๋๋ ๊ฐ์ ๋งค๋ฒ ๋ค์ ๋ณด๋๊ณ ,\n * ํ ์ฃผ๊ธฐ์ 76๊ฑด์ด ๋ํ์ด๋๋ค(์ปค๋ฅํฐ์์ ๊ณ ์ณ์ 2๊ฑด์ด ๋๋ค).\n *\n * ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์นํ
์ผ๋ก ๋ฐ์ ๋ ๋ ์์ฃผ ๋๋ค. ๋ฐ์ด ์ฃผ๋ ๋ฐฉ์์ ์ฌ์ ์ก์ด ์ ์์ด๋ค โ ๊ทธ์ชฝ์ด ์๋ต์\n * ๋ชป ๋ฐ์ผ๋ฉด ๊ฐ์ ๊ฒ์ ๋ค์ ๋ณด๋ธ๋ค.\n *\n * โโ ๋ฌด์์ด ๋ ๋ฒ ์ธ์ด์ง๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋๊ฐ์ผ๋ก ๋งํ๋ ์ฌ์ค์ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํด๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ค(์๋ ยท ์ํ ยท ์ ์ฐ ยท ์๊ฐ kW). ๊ทธ๋ฐ๋ฐ ์ธ๋\n * ๊ฐ์ ๊ทธ๋ ์ง ์๋ค.\n *\n * ๊ตฌ๊ฐ์ ํ๋ณธ ์ ยท ํ๊ท ๋ถํ(ํ๋ณธ ์๋ก ๋๋๋ค) ยท OEE ์นด์ดํฐ ยท ์ ์
๊ณ์\n * ๊ทธ๋ฆฌ๊ณ ์ง๋ ๊ธฐ๋ก์ ๊ฐ์ ์ฌ์ค์ด ๋ ์ค๋ก ๋จ๋๋ค โ ๋์ค์ ๊ทธ ๊ธฐ๋ก์ผ๋ก ๋ค์ ๊ณ์ฐํ๋ฉด ๋ ๋ ๋ฒ ์ผ๋ค\n *\n * โโ ์ ์ฒด๋ฅผ ๋ฌด์์ผ๋ก ๋ณด๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ดํฌ์ `eventId` ๋ก๋ ํ๋จํ ์ ์๋ค. ๋ณด๋ธ ์ชฝ์ด ๋งค๋ฒ ์๋ก ๋ง๋๋ ์๋ฒ์ด๊ณ (`โฆ-energy-1` ์ฒ๋ผ ํธ์ถ๋ง๋ค\n * 1๋ถํฐ ๋ค์ ์์ํ๋ค), ๊ฐ์ ์ฌ์ค์ ๋ ๋ฒ ๋ณด๋ด๋ฉด ๋ค๋ฅธ ๋ฒํธ๊ฐ ๋ถ๋๋ค. ๋ค๋ฅธ ์ฌ์ค์ ๊ฐ์ ๋ฒํธ๊ฐ ๋ถ๋ ์ผ๋\n * ์๊ธด๋ค.\n *\n * ๊ทธ๋์ **์ฌ์ค ์์ฒด๋ก** ํ๋จํ๋ค.\n *\n * ๋ฌด์์ ๋ํ ๊ฒ์ธ๊ฐ ์ค๋น ยท ๊ณ๋ ์ง์ ยท ๋ฌผํ ยท ์์
ยท ์ค๋ ยท ์๋ฆฌ\n * ์ด๋ค ์ข
๋ฅ์ธ๊ฐ ์ฌ๊ฑด ์ข
๋ฅ(eventType)\n * ์ธ์ ์ฐ ๊ฒ์ธ๊ฐ ์ฐ๊ฒฐ๋ ์์คํ
์ด ์ค ์๊ฐ\n *\n * ์ด ์
์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ์ฌ์ค์ด๋ค. ํ์๊ด ์ปค๋ฅํฐ๊ฐ `collectedAt` ์ผ๋ก ํ๋จํ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ด๊ณ , ๊ทธ๊ฒ์\n * ์ปค๋ฅํฐ๋ง๋ค ํ์ง ์๋๋ก ์ฌ๊ธฐ๋ก ์ฌ๋ฆฐ๋ค.\n *\n * โโ ์ ํํ ๊ฐ์ ๊ฒ๋ง ๋ฒ๋ฆฐ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ฆ๊ฒ ๋์ฐฉํ ์ ์ฌ์ค์ ๋ฒ๋ฆฌ์ง ์๋๋ค. ๊ทธ๊ฒ์ด ์๋ค๋ ๊ฒ ์์ฒด๊ฐ ์ฌ์ค์ด๊ณ , ์ํ์ ๋ฐ์๋์ง ์๋ ๊ฒ์\n * ์ปค๋์ ์์ ํ๋จ์ด ์ด๋ฏธ ๋งก๋๋ค. ์ฌ๊ธฐ์ ๋ฒ๋ฆฌ๋ ๊ฒ์ **์ ์ฒด๊ฐ ์์ ํ ๊ฐ์ ๊ฒ**๋ฟ์ด๋ค.\n */\n\n/** ์๊ฐ์ ๋ฐ๋ฆฌ์ด๋ก โ ์ฐ๊ฒฐ๋ ์์คํ
์ด ์ค ์๊ฐ์ด ๋จผ์ , ์์ผ๋ฉด ๋ดํฌ์ ์๊ฐ. */\nfunction timeOf(envelope: any): number | undefined {\n for (const v of [envelope?.data?.at, envelope?.data?.eventTime, envelope?.eventTime]) {\n const t = Date.parse(String(v ?? ''))\n if (Number.isFinite(t)) return t\n }\n return undefined\n}\n\n/**\n * ์ด ๋ดํฌ๊ฐ ๋งํ๋ ๋์ โ ์ดํ๋ง๋ค ์ด๋ฆ์ด ๋ค๋ฅด๋ฏ๋ก ์๋ ์ด๋ฆ์ ๋ชจ๋ ๋ณธ๋ค.\n *\n * ์์๊ฐ ๋ป์ ๊ฐ๋๋ค: ์ฃผ์ฒด๋ฅผ ๋จผ์ ๋ณธ๋ค. ์ค๋น ์ฌ์ค์ ใ์ง๊ธ ๋ถ์ด ์๋ ์์
ใ์ ํจ๊ป ์ฃ๊ณ , ์์
์ฌ์ค์\n * ใ์์ ์ค๋ใ๋ฅผ ํจ๊ป ์ฃ๋๋ค. ์๋ฌด ์ด๋ฆ์ด๋ ๋จผ์ ๋ณด๋ฉด ์ฐธ์กฐ๋ฅผ ์ฃผ์ฒด๋ก ์ฝ๋๋ค(์น๊ฒฉ ํค์์ ๊ฒช์ ๊ฒ๊ณผ ๊ฐ๋ค).\n */\nfunction targetOf(envelope: any): string | undefined {\n const d = envelope?.data ?? {}\n const first = (...vals: unknown[]) => {\n for (const v of vals) {\n const s = String(v ?? '').trim()\n if (s) return s\n }\n return undefined\n }\n return first(\n d.meterId,\n d.equipmentId,\n d.moverId,\n d.taskId,\n d.orderId,\n d.personId,\n d.assetId,\n d.locationId,\n d.epcList?.[0],\n d.parentID,\n d.quantityList?.[0]?.epcClass,\n d.transformationID\n )\n}\n\n/**\n * ์ด ๋ดํฌ๊ฐ ๋งํ๋ ์ฌ์ค์ ์ ์ฒด โ ๊ฐ์ผ๋ฉด ๊ฐ์ ์ฌ์ค์ด๋ค.\n *\n * ๋์์ด๋ ์๊ฐ์ ์ ์ ์์ผ๋ฉด **์ ์ฒด๋ฅผ ๋ง๋ค์ง ์๋๋ค**(`undefined`). ๊ทธ๋๋ ๊ฑฐ๋ฅด์ง ์๊ณ ํต๊ณผ์ํจ๋ค โ\n * ๋ชจ๋ฅด๋ ๊ฒ์ ๊ฐ๋ค๊ณ ํ๋จํ๋ฉด ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด ํ๋๋ก ํฉ์ณ์ง๋ค. ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋ค.\n */\nexport function factIdentity(envelope: any): string | undefined {\n const type = String(envelope?.eventType ?? '').trim()\n if (!type) return undefined\n const target = targetOf(envelope)\n if (!target) return undefined\n const at = timeOf(envelope)\n if (at === undefined) return undefined\n return `${type}|${target}|${at}`\n}\n\n/**\n * ์ต๊ทผ์ ๋ณธ ์ ์ฒด๋ฅผ ๊ธฐ์ตํ๋ค โ **ํฌ๊ธฐ์ ์ํ์ ๋๋ค.**\n *\n * ์ ๋ถ ๊ธฐ์ตํ ์๋ ์๋ค(ํธ์ ํ๋๊ฐ ์์ฒ๋ง ์ฌ๊ฑด์ ๊ฐ๋๋ค). ์ฐฝ์ ๋์ผ๋ฉด ์ค๋๋ ๊ฒ๋ถํฐ ์๋๋ค. ์ฐฝ ๋ฐ์\n * ์ฌ์ ์ก์ ๋ค์ ํต๊ณผํ๋๋ฐ, ๊ทธ๊ฒ์ ์ ๋๊ฐ ์ฌ์ค์ด๋ผ ์ํ์ ํด๊ฐ ์๊ณ ์ง๋ ๊ธฐ๋ก์ ํ ์ค ๋ ๋จ๋๋ค.\n * ์ฐฝ์ ํฌ๊ฒ ์ก์ผ๋ฉด ๊ทธ๋งํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ด๋ค โ ๊ทธ ๊ฐ์ ์ฌ๊ธฐ์ ์ด๋ฆ์ผ๋ก ๋ชป ๋ฐ๋๋ค.\n *\n * **์ฌ๊ธฐ๋์ ๊ฑด๋์ง ๋ชปํ๋ค.** ํ๋ก์ธ์ค๊ฐ ์๋ก ๋จ๋ฉด ๊ธฐ์ต์ด ๋น์ด ์์ผ๋ฏ๋ก, ์ฌ๊ธฐ๋ ์งํ ์ฒซ ์ฃผ๊ธฐ๊ฐ ๊ฐ์\n * ๊ฐ์ ๋ค์ ๋ณด๋ด๋ฉด ๊ฑธ๋ฌ์ง์ง ์๋๋ค. ๊ทธ๊ฒ์ ๋ง์ผ๋ ค๋ฉด ์ด ๊ธฐ์ต์ด ์ ์ฅ๋ผ์ผ ํ๊ณ , ๊ทธ๊ฒ์ ๋ค์ ๊ฑธ์์ด๋ค.\n * ์ง๊ธ์ ๊ทธ ์ฌ์ค์ ์ฌ๊ธฐ ์ ์ด ๋๋ค โ ์ ์ด ๋์ง ์์ผ๋ฉด ใ์ค๋ณต์ ์ด์ ์๋คใ๋ก ์ฝํ๋ค.\n */\nexport class FactDeduper {\n /** ๊ธฐ์ตํ๋ ์ ์ฒด์ ์ โ ์ฐฝ. */\n static WINDOW = 20_000\n\n private seen = new Set<string>()\n private order: string[] = []\n\n /** ์ด ์ฌ์ค์ ๋ณธ ์ ์ด ์๋ โ ์์ผ๋ฉด ๊ธฐ์ตํ๊ณ `false`. */\n private known(identity: string): boolean {\n if (this.seen.has(identity)) return true\n this.seen.add(identity)\n this.order.push(identity)\n if (this.order.length > FactDeduper.WINDOW) {\n const gone = this.order.splice(0, this.order.length - FactDeduper.WINDOW)\n for (const g of gone) this.seen.delete(g)\n }\n return false\n }\n\n /**\n * ์ฒ์ ๋ณด๋ ๊ฒ๋ง ๋๋ ค์ค๋ค โ ๊ทธ๋ฆฌ๊ณ ๋ช ๊ฐ๋ฅผ ๋ฒ๋ ธ๋์ง ํจ๊ป ๋ธ๋ค.\n *\n * ๋ฒ๋ฆฐ ์๋ฅผ ํจ๊ป ๋ด๋ ์ด์ : ์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ๋ฉด ใ๋ณด๋ธ ์ใ์ ใ๋ฐ์๋ ์ใ๊ฐ ์ด๊ธ๋๋๋ฐ ์๋ฌด๋ ๊ทธ\n * ์ด์ ๋ฅผ ๋ชจ๋ฅธ๋ค. ๊ทธ ์๊ฐ ํฌ๋ฉด ๋ณด๋ด๋ ์ชฝ์ด ๋ํ์ด ๋ณด๋ด๊ณ ์๋ค๋ ๋ป์ด๊ณ , ๊ทธ๊ฒ์ ๊ณ ์น ์ผ์ด๋ค.\n */\n filter<T>(envelopes: readonly T[]): { fresh: T[]; duplicates: number } {\n const fresh: T[] = []\n let duplicates = 0\n for (const e of envelopes) {\n const id = factIdentity(e)\n if (id === undefined) {\n fresh.push(e)\n continue\n }\n if (this.known(id)) duplicates++\n else fresh.push(e)\n }\n return { fresh, duplicates }\n }\n\n /** ๊ธฐ์ตํ๊ณ ์๋ ์ ์ฒด์ ์ โ ๊ณ๊ธฐ๊ฐ ์ฝ๋๋ค. */\n size(): number {\n return this.seen.size\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ingest-dedupe.js","sourceRoot":"","sources":["../../server/engine/ingest-dedupe.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;;;AAyLH,4CAIC;AAED,oCAoBC;AAjND,gDAAgD;AAChD,SAAS,MAAM,CAAC,QAAa;IAC3B,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QACrF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,SAAS,gBAAgB,CAAC,QAAa;IACrC,MAAM,CAAC,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAA;IAC9B,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,CAAU,EAAE,EAAE;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAChC,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACjC,CAAC,CAAA;IAED;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;IACvB,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;IAC/B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA,CAAC,mDAAmD;IAC3E,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACrB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;IACvB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;IACzB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;IACvB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAA,CAAC,+BAA+B;IAC7D,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1B,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;IACzB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC3C,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACzC;;;;;;;;OAQG;IACH,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAA;IAC3B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACrB;;;;;;;;OAQG;IACH,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACjC,6CAA6C;IAC7C,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;IAE3B;;;OAGG;IACH,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;IACzB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACvB,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;IAEjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAC5C,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACxC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC9C,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACnC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC1C;;;OAGG;IACH,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAC/C,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAC3C;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAA;IAEpD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,uDAAuD;AACvD,SAAS,OAAO,CAAC,IAAa;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAS,CAAC,CAAC,CAAC,SAAS,CAAA;IAChE,MAAM,CAAC,GAAG,KAAK,EAAE,QAAQ,CAAA;IACzB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1D,CAAC;AAED;;;;GAIG;AACH,SAAS,KAAK,CAAC,IAAa;IAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC3G,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED;;;;;GAKG;AACH;;;;;GAKG;AACH,MAAM,YAAY,GAA2B,EAAE,CAAA;AAE/C,qCAAqC;AACrC,SAAgB,gBAAgB;IAC9B,MAAM,GAAG,GAAG,EAAE,GAAG,YAAY,EAAE,CAAA;IAC/B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;QAAE,OAAO,YAAY,CAAC,CAAC,CAAC,CAAA;IACjE,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAgB,YAAY,CAAC,QAAa;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACrD,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACxC;;;;;;;;OAQG;IACH,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QAClD,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC3B,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACtC,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;AAC3C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAa,WAAW;IAAxB;QAIU,SAAI,GAAG,IAAI,GAAG,EAAU,CAAA;QACxB,UAAK,GAAa,EAAE,CAAA;IA4D9B,CAAC;IAhEC,sBAAsB;aACf,WAAM,GAAG,MAAM,AAAT,CAAS;IAKtB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,UAA6B;QACpC,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,KAAK,MAAM,EAAE,IAAI,UAAU;YAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAAC,KAAK,EAAE,CAAA;YAAC,CAAC;QACtF,OAAO,KAAK,CAAA;IACd,CAAC;IAED,wCAAwC;IAChC,KAAK,CAAC,QAAgB;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;QACxC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;YACzE,KAAK,MAAM,CAAC,IAAI,IAAI;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAI,SAAuB;QAC/B,MAAM,KAAK,GAAQ,EAAE,CAAA;QACrB,IAAI,UAAU,GAAG,CAAC,CAAA;QAClB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAA;YAC1B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACb,SAAQ;YACV,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAAE,UAAU,EAAE,CAAA;;gBAC3B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;IAC9B,CAAC;IAED,+BAA+B;IAC/B,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;IACvB,CAAC;;AAhEH,kCAiEC","sourcesContent":["/*\n * ๊ฐ์ ์ฌ์ค์ ๋ ๋ฒ ๋ฐ์ผ๋ฉด ํ ๋ฒ๋ง ๋ฐ์ํ๋ค โ **์ ์
๊ฒฝ๊ณ ํ ๊ณณ์์.**\n *\n * โโ ์ ํ์ํ๊ฐ (2026-08-26) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ง๊ธ ์ค๋ณต์ ๋ง๋ ๊ฒ์ ์ปค๋ฅํฐ๋ง๋ค ๊ฐ์ ํ๊ณ ์๋ค. ๊ทธ๋์ ์ปค๋ฅํฐ๊ฐ ๊ทธ๊ฒ์ ์์ผ๋ฉด ํธ์์ด ๊ทธ๋๋ก ๋ ๋ฒ\n * ์ผ๋ค. ์ค์ ๋ก ๊ทธ๋ฌ๋ค: ํ์๊ด ์ปค๋ฅํฐ๊ฐ 10์ด๋ง๋ค ๋ฌผ์ผ๋ฉด์ 10๋ถ๋ง๋ค ๋ฐ๋๋ ๊ฐ์ ๋งค๋ฒ ๋ค์ ๋ณด๋๊ณ ,\n * ํ ์ฃผ๊ธฐ์ 76๊ฑด์ด ๋ํ์ด๋๋ค(์ปค๋ฅํฐ์์ ๊ณ ์ณ์ 2๊ฑด์ด ๋๋ค).\n *\n * ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์นํ
์ผ๋ก ๋ฐ์ ๋ ๋ ์์ฃผ ๋๋ค. ๋ฐ์ด ์ฃผ๋ ๋ฐฉ์์ ์ฌ์ ์ก์ด ์ ์์ด๋ค โ ๊ทธ์ชฝ์ด ์๋ต์\n * ๋ชป ๋ฐ์ผ๋ฉด ๊ฐ์ ๊ฒ์ ๋ค์ ๋ณด๋ธ๋ค.\n *\n * โโ ๋ฌด์์ด ๋ ๋ฒ ์ธ์ด์ง๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋๊ฐ์ผ๋ก ๋งํ๋ ์ฌ์ค์ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํด๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ค(์๋ ยท ์ํ ยท ์ ์ฐ ยท ์๊ฐ kW). ๊ทธ๋ฐ๋ฐ ์ธ๋\n * ๊ฐ์ ๊ทธ๋ ์ง ์๋ค.\n *\n * ๊ตฌ๊ฐ์ ํ๋ณธ ์ ยท ํ๊ท ๋ถํ(ํ๋ณธ ์๋ก ๋๋๋ค) ยท OEE ์นด์ดํฐ ยท ์ ์
๊ณ์\n * ๊ทธ๋ฆฌ๊ณ ์ง๋ ๊ธฐ๋ก์ ๊ฐ์ ์ฌ์ค์ด ๋ ์ค๋ก ๋จ๋๋ค โ ๋์ค์ ๊ทธ ๊ธฐ๋ก์ผ๋ก ๋ค์ ๊ณ์ฐํ๋ฉด ๋ ๋ ๋ฒ ์ผ๋ค\n *\n * โโ ์ ์ฒด๋ฅผ ๋ฌด์์ผ๋ก ๋ณด๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ดํฌ์ `eventId` ๋ก๋ ํ๋จํ ์ ์๋ค. ๋ณด๋ธ ์ชฝ์ด ๋งค๋ฒ ์๋ก ๋ง๋๋ ์๋ฒ์ด๊ณ (`โฆ-energy-1` ์ฒ๋ผ ํธ์ถ๋ง๋ค\n * 1๋ถํฐ ๋ค์ ์์ํ๋ค), ๊ฐ์ ์ฌ์ค์ ๋ ๋ฒ ๋ณด๋ด๋ฉด ๋ค๋ฅธ ๋ฒํธ๊ฐ ๋ถ๋๋ค. ๋ค๋ฅธ ์ฌ์ค์ ๊ฐ์ ๋ฒํธ๊ฐ ๋ถ๋ ์ผ๋\n * ์๊ธด๋ค.\n *\n * ๊ทธ๋์ **์ฌ์ค ์์ฒด๋ก** ํ๋จํ๋ค.\n *\n * ๋ฌด์์ ๋ํ ๊ฒ์ธ๊ฐ ์ค๋น ยท ๊ณ๋ ์ง์ ยท ๋ฌผํ ยท ์์
ยท ์ค๋ ยท ์๋ฆฌ\n * ์ด๋ค ์ข
๋ฅ์ธ๊ฐ ์ฌ๊ฑด ์ข
๋ฅ(eventType)\n * ์ธ์ ์ฐ ๊ฒ์ธ๊ฐ ์ฐ๊ฒฐ๋ ์์คํ
์ด ์ค ์๊ฐ\n *\n * ์ด ์
์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ์ฌ์ค์ด๋ค. ํ์๊ด ์ปค๋ฅํฐ๊ฐ `collectedAt` ์ผ๋ก ํ๋จํ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ด๊ณ , ๊ทธ๊ฒ์\n * ์ปค๋ฅํฐ๋ง๋ค ํ์ง ์๋๋ก ์ฌ๊ธฐ๋ก ์ฌ๋ฆฐ๋ค.\n *\n * โโ ์ ํํ ๊ฐ์ ๊ฒ๋ง ๋ฒ๋ฆฐ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๋ฆ๊ฒ ๋์ฐฉํ ์ ์ฌ์ค์ ๋ฒ๋ฆฌ์ง ์๋๋ค. ๊ทธ๊ฒ์ด ์๋ค๋ ๊ฒ ์์ฒด๊ฐ ์ฌ์ค์ด๊ณ , ์ํ์ ๋ฐ์๋์ง ์๋ ๊ฒ์\n * ์ปค๋์ ์์ ํ๋จ์ด ์ด๋ฏธ ๋งก๋๋ค. ์ฌ๊ธฐ์ ๋ฒ๋ฆฌ๋ ๊ฒ์ **์ ์ฒด๊ฐ ์์ ํ ๊ฐ์ ๊ฒ**๋ฟ์ด๋ค.\n */\n\n/** ์๊ฐ์ ๋ฐ๋ฆฌ์ด๋ก โ ์ฐ๊ฒฐ๋ ์์คํ
์ด ์ค ์๊ฐ์ด ๋จผ์ , ์์ผ๋ฉด ๋ดํฌ์ ์๊ฐ. */\nfunction timeOf(envelope: any): number | undefined {\n for (const v of [envelope?.data?.at, envelope?.data?.eventTime, envelope?.eventTime]) {\n const t = Date.parse(String(v ?? ''))\n if (Number.isFinite(t)) return t\n }\n return undefined\n}\n\n/**\n * ์ด ๋ดํฌ๊ฐ ๋งํ๋ ๊ฒ์ **๊ฐ๋ฅด๋ ๊ฐ๋ค** โ ํ๋๋ผ๋ ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ์ฌ์ค์ด๋ค.\n *\n * โโ ์์ ์๋ ํ๋๋ง ๊ณจ๋๋ค (2026-09-05 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์๋ ์ด๋ฆ์ ์์๋๋ก ๋ณด๊ณ **๋จผ์ ๊ฑธ๋ฆฌ๋ ํ๋**๋ฅผ ๋์์ผ๋ก ์ผ์๋ค. ใ์ฃผ์ฒด๋ฅผ ๋จผ์ ๋ณธ๋คใ๋ ํ๋จ\n * ์์ฒด๋ ์ณ๋ค โ ์ค๋น ์ฌ์ค์ ใ์ง๊ธ ๋ถ์ด ์๋ ์์
ใ์ ์ฐธ์กฐ๋ก ์ฃ๋๋ค. ๊ทธ๋ฐ๋ฐ **๊ณ ๋ฅด๊ณ ๋๋จธ์ง๋ฅผ\n * ๋ฒ๋ฆฐ ๊ฒ**์ด ๊ฒฐํจ์ด์๋ค.\n *\n * ์ค์ ๋ก ๋ ์ผ: plant ์ด ์ค์ ๋์ ๋ณด๋๋๋ฐ ํ ๊ฑด์ด ์ ๋์ ์ ๋จ์๋ค.\n *\n * seq 36 quality.output moverId EQ-CT-MWELD-01 ยท taskId PR-CT-WIRE-01 ยท goodCount 12\n * seq 41 quality.output moverId EQ-CT-MWELD-01 ยท taskId PR-CT-WIRE-02 ยท goodCount 9\n *\n * ๋ ์ค์ ์ ์๊ฐ์ด ๊ฐ์๊ณ (์๋ณธ์ด ๋์๊ฐ์ ๋ณต์ฌ) `moverId` ๊ฐ `taskId` ๋ณด๋ค ๋จผ์ ๋ผ **๋์ด ํ ์ฌ์ค์ด\n * ๋๋ค.** ๊ฑฐ๋ถ๊ฐ ์๋๋ผ ๋ํ์ด๋ก ์ธ์ด์ก๋ค โ `offered 5 ยท rejected 0 ยท journaled 3`.\n *\n * **๊ตฌ๋ณํ ๊ฐ์ด ์ด๋ฏธ ๋ดํฌ ์์ ์์๋๋ฐ ํ์ ์ด ๊ทธ๊ฒ์ ์ ๋ดค๋ค.**\n *\n * โโ ๊ทธ๋ฆฌ๊ณ EPCIS ๋ ๊ฐ์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ๋ 246๋ง ๊ฑด์ ํ์ฌ ๊ท์น์ ๋ค์ ๊ฑธ์ด ๋ณด๋ ๊ฒน์น๋ ๋ฌถ์์ด ์ฌ์ฏ์ด์๊ณ , ์ ๋ถ ์ด ๋ชจ์์ด๋ค.\n *\n * ๊ฐ์ EPC ยท ๊ฐ์ ๋ฐ๋ฆฌ์ด\n * โ bizStep receiving action ADD disposition sellable_accessible\n * โก bizStep commissioning action OBSERVE disposition reserved\n *\n * **ํ ๊ฐ์ฒด์ ์๋ก ๋ค๋ฅธ ๊ด์ธก**์ด๋ค. EPCIS ์์ ์ด์ํ ์ผ์ด ์๋๋ฐ ๊ท์น์ด ๊ทธ ์
์ ์ ๋ดค๋ค.\n *\n * โโ ์ ๋ํ๋ ์ชฝ์ด ๋ง๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ์ผ์ด ์ค์ค๋ก ์ ์ด ๋ ๊ฐ์ด ๊ทธ๊ฒ์ด๋ค โ ใ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋คใ.\n * ์ง๊ธ ๊ฑฐ๋์ **์๋ฆฌ์ง ์๊ณ ์๋ ์ชฝ**์ด์๋ค.\n *\n * ๋ํ๋ ๋ํ์ด๋ ๊ทธ๋๋ก ๊ฑธ๋ฆฐ๋ค: ๊ฐ์ ๋ดํฌ๋ฅผ ๋ค์ ๋ณด๋ด๋ฉด **์ด ๊ฐ๋ค์ด ์ ๋ถ ๊ฐ๋ค.** ๋ํ๋ ๊ฒ์\n * ใ๋ค๋ฅธ ์ฌ์ค์ ํฉ์น์ง ์๋๋คใ๋ง ๊ฐํด์ง๊ณ ใ๋ํ์ด๋ฅผ ์ก๋๋คใ๋ ์ ์ฝํด์ง๋ค.\n */\nfunction discriminatorsOf(envelope: any): string[] {\n const d = envelope?.data ?? {}\n const out: string[] = []\n const put = (name: string, v: unknown) => {\n const t = String(v ?? '').trim()\n if (t) out.push(`${name}=${t}`)\n }\n\n /*\n * ์ฃผ์ฒดยท์ฐธ์กฐ๋ฅผ **๋ค ์ ๋๋ค.** ์์๋ ๊ฐ์ด ์๋๋ผ ์ด๋ฆ์ผ๋ก ๊ณ ์ ๋๋ฏ๋ก ๋ดํฌ๋ง๋ค ํ๋ค๋ฆฌ์ง ์๋๋ค.\n *\n * โ **์ด ๋ชฉ๋ก์ ๊ณ์ฝ์ `identity` ์ ์ธ์ ์์ผ๋ก ์ฎ๊ธด ๊ฒ์ด๋ค.** ๊ณ์ฝ์ด kind ๋ง๋ค ๋ฌด์์ด ๊ทธ ์ฌ์ค์\n * ๊ฐ๋ฆฌํค๋์ง ์ด๋ฏธ ์ ์ธํ๋๋ฐ(`operational-ingest.ts` ์ `SPECS[kind].identity`), ๊ทธ๊ฒ์ ๋ด๋ณด๋ด์ง\n * ์์์ ์ฌ๊ธฐ๊ฐ ๋ฐ๋ก ๋ค๊ณ ์๋ค.\n *\n * ๊ทธ๋์ ์ kind ๊ฐ ์๊ธฐ๋ฉด ์ฌ๊ธฐ๊ฐ ์กฐ์ฉํ ๋ค์ฒ์ง๋ค. ์ค์ ๋ก ๋ ๋ฒ ๊ทธ๋ฌ๋ค โ `subjectId`(์ฒ๋ถ)์\n * `testableObjectId`(์ํ)๊ฐ ๋น ์ ธ ์์๊ณ , ๊ทธ๋์ ๊ทธ ๋ ์ข
๋ฅ๋ ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค๊ฑฐ๋ ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด\n * ๋ญ์น ์ ์์๋ค.\n *\n * ๊ณ์ฝ์ด `operationalIdentityField(kind)` ๋ฅผ ๋ด๋ณด๋ด๋ฉด ์ด ๋ชฉ๋ก์ ์ง์ด๋ค. ๊ทธ ๋ฌธ์ ์ด์ด ๋์๊ณ \n * ๋ฐฐํฌ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค.\n */\n put('meter', d.meterId)\n put('equipment', d.equipmentId)\n put('mover', d.moverId) // vocabulary-guard: allow โ ๋ดํฌ์ ์ ์ธ๋ ํ๋ ์ด๋ฆ(์ ์ฅ๋ ๊ณ์ฝ)\n put('task', d.taskId)\n put('order', d.orderId)\n put('person', d.personId)\n put('asset', d.assetId)\n put('location', d.locationId) // vocabulary-guard: allow โ ๊ฐ์\n put('epc', d.epcList?.[0])\n put('parent', d.parentID)\n put('class', d.quantityList?.[0]?.epcClass)\n put('transformation', d.transformationID)\n /*\n * โโ ์ฃผ์ฒด๊ฐ `subjectId` ์ธ ์ฌ์ค์ด ์๋ค (2026-09-06 ์ธก์ ) โโโโโโโโโโโโโโโโโโโโโโ\n * ๋ถ์ ํฉ ์ฒ๋ถ๊ณผ ์ํ ๊ฒฐ๊ณผ๋ **ํ์ค `TestableObjectID` ์ ๊ฐ์ ์๋ฆฌ**๋ฅผ ์ด๋ค(๋กํธ ยท ์ค๋น ยท ์๋ฆฌ์\n * ๋๋ฃจ ์ฐ๋ ํ๋์ ์ด๋ฆ). ๊ทธ ์ด๋ฆ์ด ์ฌ๊ธฐ ์์ด์ ๋ ์ข
๋ฅ๊ฐ **์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค์๋ค** โ\n * `parts` ๊ฐ ๋น๋ฉด `factIdentity` ๊ฐ `undefined` ๋ฅผ ๋ด๊ณ , ๊ทธ๋ฌ๋ฉด dedupe ๋ฐ์ด๋ค.\n *\n * ์ค์ ๋ก ๊ทธ๋ฌ๋ค. `fillTwinScope` ๋ฅผ ๋ ๋ฒ ๋๋ฆด ๋๋ง๋ค ๊ทธ ๋์ด 7๊ฑด์ฉ ๋ค์ ์์๋ค(์ฒ๋ถ 4 ยท ์ํ 3).\n * ๋๋จธ์ง 34๊ฑด์ ๊ฑธ๋ฌ์ก๋๋ฐ ์ด ๋๋ง ๊ณ์ ๋์๋ค.\n */\n put('subject', d.subjectId)\n put('spec', d.specId)\n /*\n * ์ํ ๊ฒฐ๊ณผ์ ์ฃผ์ฒด๋ `testableObjectId` ๋ค โ ํ์ค `TestableObjectID` ์ ์ด๋ฆ์ ๊ทธ๋๋ก ์ด๋ค.\n *\n * ์ด ์ด๋ฆ์ด ์์ด์ **๊ฐ์ ๋ช
์ธ๋ก ๊ฐ์ ์๊ฐ์ ์ฐ ์๋ก ๋ค๋ฅธ ๋กํธ๊ฐ ํ ์ฌ์ค๋ก ๋ญ์ณค๋ค.** ์ค๋ณต์ด ์๊ธฐ๋\n * ๊ฒ๋ณด๋ค ๋์๋ค โ ๋ ๋กํธ์ ์ํ ๊ฒฐ๊ณผ ์ค ํ๋๊ฐ ์ฌ๋ผ์ง๋ค.\n *\n * ์ค์ ๋ก `mes-miratek` ์ ๊ฐ์ ์ํ ๊ฒฐ๊ณผ๊ฐ 10๊ฑด ์์๋ค(2026-09-06 ํ์ธ). ๊ทธ๊ฒ์ ๋ญ์น ๊ฒ์ด ์๋๋ผ\n * ๋ฐ๋๋ก dedupe ๋ฅผ ๋ชป ์ง๋ ๊ฒ์ธ๋ฐ, ๊ฐ์ ์๋ฆฌ์์ ๋ญ์น๋ ์ชฝ๋ ์ด๋ ค ์์๋ค.\n */\n put('object', d.testableObjectId)\n /* ์๋ฃ ์ ์ธ์ ์ฃผ์ฒด โ ใ์ด ์ถ์ ์ฌ๊ธฐ๊น์ง๊ฐ ์ ๋ถ๋คใ๋ฅผ ๋งํ๋ ์ถ ์ด๋ฆ. */\n put('axis', d.completeAxis)\n\n /*\n * EPCIS ๋ ใ๋ฌด์์ ๋งํ๋ ๊ด์ธก์ธ๊ฐใ๊ฐ ์ด ์
์ผ๋ก ๊ฐ๋ฆฐ๋ค. ํ ๊ฐ์ฒด๊ฐ ํ ์๊ฐ์ ๋ ๊ด์ธก์ ๊ฐ๋\n * ๊ฒ์ ํ์ค์์ ์ ์์ด๊ณ , ์ด๊ฒ์ ์ ๋ณด๋ฉด ๋ค์ฃ๊ฒ์ด ์ฌ๋ผ์ง๋ค.\n */\n put('bizStep', d.bizStep)\n put('action', d.action)\n put('disposition', d.disposition)\n\n /*\n * โโ ๋ณํ์ **๋ฌด์์ด ๋ฌด์์ผ๋ก ๋์๋**๋ก ๊ฐ๋ฆฐ๋ค (2026-09-07 ์ธก์ ) โโโโโโโโโโโโโ\n * ์ด ์๋ฆฌ๊ฐ ์์ด์ **์ฌ์ค ํ๋๊ฐ ์์ด์ก์ต๋๋ค.** ๊ฑฐ์ ์ด ์๋๋ผ ๋ํ์ด๋ก ์ธ์ด์ ธ์ ๊ฒฝ๊ณ ๋ ์์์ต๋๋ค.\n *\n * ```\n * plant outbox seq 37 in LOT-CT-SIDE-001 24๊ฐ โ out LOT-CT-MAIN-003 12๊ฐ\n * plant outbox seq 42 in LOT-CT-SIDE-001 18๊ฐ โ out LOT-CT-MAIN-004 9๊ฐ\n * transformationID ยท bizStep ยท ์ด๊น์ง ์ ๋ถ ๊ฐ๋ค\n * ์ ๋์ ๋จ์ ๊ฒ LOT-CT-MAIN-003 ํ๋\n * ```\n *\n * `LOT-CT-MAIN-004` ๋ฅผ ์ด๋ ํจ๋๋ก ๋ง๋ค์๋์ง ํธ์์ด ๋ตํ์ง ๋ชปํ๋ ์ํ์์ต๋๋ค.\n *\n * ๊ทธ๋ฆฌ๊ณ **๊ตฌ๋ณํ ๊ฐ์ด ๋ดํฌ ์์ ์ด๋ฏธ ์์์ต๋๋ค** โ `outputQuantityList[0].epcClass` ๊ฐ ์๋ก\n * ๋ค๋ฆ
๋๋ค. ์ด ํ์ผ ๋จธ๋ฆฌ๋ง์ด ์ ์ด ๋ ๊ทธ ๋ชจ์ ๊ทธ๋๋ก์
๋๋ค: ํ์ ์ด ๊ทธ๊ฒ์ ์ ๋ดค์ต๋๋ค.\n *\n * ์ฐ์ถ๋ง ๋ณด์ง ์๊ณ **์
๋ ฅ๋ ๋ด
๋๋ค.** ๊ฐ์ ๋กํธ๋ฅผ ๊ฐ์ ์ด์ ๋ ๋ฒ ์๋นํ๋ฉด์ ์ฐ์ถ ์ด๋ฆ์ด ๊ฐ์\n * ๊ฒฝ์ฐ(์๋๋ง ๋ค๋ฅธ ๋ถํ )๊ฐ ๋จ๊ณ , ๊ทธ๋ ์
๋ ฅ ์๋์ด ์ ์ผํ ์ฐจ์ด์
๋๋ค. ์๋๊น์ง ๋ฃ๋ ์ด์ ๊ฐ ๊ทธ๊ฒ์
๋๋ค.\n */\n put('inClass', classOf(d.inputQuantityList))\n put('inEpc', d.inputEPCList?.[0])\n put('inQty', qtyOf(d.inputQuantityList))\n put('outClass', classOf(d.outputQuantityList))\n put('outEpc', d.outputEPCList?.[0])\n put('outQty', qtyOf(d.outputQuantityList))\n /*\n * ๋ด๊น์ ์์๋ ๊ฐ์ ์ด์ ๋ก ๋ณธ๋ค โ ํ ํ๋ ํธ์ ์๋ก ๋ค๋ฅธ ๋ฌถ์์ ๊ฐ์ ์ด์ ๋ ๋ฒ ์ค์ผ๋ฉด ๋ค์ฃ๊ฒ์ด\n * ์ฌ๋ผ์ง๋ค. ์ ๋ณํ์์ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ์์์ผ๋ ์ฌ๊ธฐ๋ ํจ๊ป ๋ง๋๋ค(ํ ์ข
๋ฅ๋ง ๊ณ ์น๋ฉด ๋๋จธ์ง์ ๋จ๋๋ค).\n */\n put('childEpc', d.childEPCs?.[0])\n put('childClass', classOf(d.childQuantityList))\n put('childQty', qtyOf(d.childQuantityList))\n /*\n * ์ด๋ ์ค๋์ ์ฌ์ค์ธ๊ฐ๋ ์ ์ฒด์ ์ผ๋ถ๋ค. ๊ฐ์ ๊ณต์ ์ ๊ฐ์ ์ด์ ๋ ์ค๋๋ก ๋๋ฆฌ๋ ๊ฒ์ ์ ์์ด๊ณ ,\n * ์ด๊ฒ์ ์ ๋ณด๋ฉด ๋ค์ฃ๊ฒ์ด ์ฌ๋ผ์ง๋ค.\n */\n put('tx', d.bizTransactionList?.[0]?.bizTransaction)\n\n return out\n}\n\n/** ์๋ ๋ชฉ๋ก์ ์ฒซ ์ข
๋ฅ โ ๋ชฉ๋ก์ด ๋น๋ฉด `undefined`(๋น ๋ฌธ์์ด์ ๋ฃ์ง ์๋๋ค). */\nfunction classOf(list: unknown): string | undefined {\n const first = Array.isArray(list) ? (list[0] as any) : undefined\n const v = first?.epcClass\n return typeof v === 'string' && v.trim() ? v : undefined\n}\n\n/**\n * ์๋ ๋ชฉ๋ก์ ์๊น์ง ์ ๋๋ค โ ์ข
๋ฅ๊ฐ ๊ฐ๊ณ ์๋๋ง ๋ค๋ฅธ ์ฌ์ค์ ๊ฐ๋ฅธ๋ค.\n *\n * ๋ชฉ๋ก ์ ์ฒด๋ฅผ ์ ๋๋ค. ์ฒซ ์์๋ง ๋ณด๋ฉด ใ๊ฐ์ ๊ฒ ๋ + ๋ค๋ฅธ ๊ฒ ํ๋ใ๊ฐ ์ฒซ ์์๋ก๋ ๊ตฌ๋ณ๋์ง ์๋๋ค.\n */\nfunction qtyOf(list: unknown): string | undefined {\n if (!Array.isArray(list) || !list.length) return undefined\n const parts = list.map((x: any) => `${x?.epcClass ?? ''}:${x?.quantity ?? ''}${x?.uom ? '/' + x.uom : ''}`)\n return parts.join('|')\n}\n\n/**\n * ์ด ๋ดํฌ๊ฐ ๋งํ๋ ์ฌ์ค์ ์ ์ฒด โ ๊ฐ์ผ๋ฉด ๊ฐ์ ์ฌ์ค์ด๋ค.\n *\n * ๋์์ด๋ ์๊ฐ์ ์ ์ ์์ผ๋ฉด **์ ์ฒด๋ฅผ ๋ง๋ค์ง ์๋๋ค**(`undefined`). ๊ทธ๋๋ ๊ฑฐ๋ฅด์ง ์๊ณ ํต๊ณผ์ํจ๋ค โ\n * ๋ชจ๋ฅด๋ ๊ฒ์ ๊ฐ๋ค๊ณ ํ๋จํ๋ฉด ์๋ก ๋ค๋ฅธ ์ฌ์ค์ด ํ๋๋ก ํฉ์ณ์ง๋ค. ์๋ฆฌ์ง ์๊ณ ์๋ ๊ฒ๋ณด๋ค ๋ ๋ฒ ์ธ๋ ๊ฒ์ด ๋ซ๋ค.\n */\n/**\n * ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ์ฌ์ค์ **์ข
๋ฅ๋ณ๋ก** ์ผ๋ค โ dedupe ๋ฐ์ผ๋ก ๋๊ฐ ๊ฒ๋ค.\n *\n * ์ด ์๊ฐ 0์ด ์๋๋ฉด ๊ทธ ์ข
๋ฅ๋ ๋ค์ ๋ฐ์ ๋๋ง๋ค ์ ๋์ ๋ค์ ์๋๋ค. ๊ทธ ์ข
๋ฅ์ ์ฃผ์ฒด ์ด๋ฆ์\n * `discriminatorsOf` ์ ๋ํด์ผ ํ๋ค.\n */\nconst unidentified: Record<string, number> = {}\n\n/** ์ง๊ธ๊น์ง ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ๊ฒ โ ์ข
๋ฅ๋ณ. ์ฝ๊ณ ๋น์ด๋ค. */\nexport function takeUnidentified(): Record<string, number> {\n const out = { ...unidentified }\n for (const k of Object.keys(unidentified)) delete unidentified[k]\n return out\n}\n\nexport function factIdentity(envelope: any): string | undefined {\n const type = String(envelope?.eventType ?? '').trim()\n if (!type) return undefined\n const parts = discriminatorsOf(envelope)\n /*\n * **์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค๋ฉด dedupe ๋ฐ์ด๋ค** โ ๊ทธ ์ฌ์ค์ ๋ค์ ๋ฐ์ ๋๋ง๋ค ์๋ก ์๋๋ค.\n *\n * ์ค๋ ๊ทธ๊ฒ์ผ๋ก ์ ๋์ด ๋ถํ์๋ค(์ฒ๋ถยท์ํ์ด `subjectId` ๋ฅผ ์ฃผ์ฒด๋ก ์ฐ๋๋ฐ ๊ทธ ์ด๋ฆ์ด ์ ๋ชฉ๋ก์\n * ์์๋ค). ์กฐ์ฉํ `undefined` ๋ฅผ ๋ด๋ฉด ๋ค์ ์ข
๋ฅ์์ ๋ ๋๊ณ ๊ทธ๋๋ ์๋ฌด ํ์ ์ด ์๋ค.\n *\n * ๊ทธ๋์ ๋ฌด์์ด ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ค์๋์ง ์ผ๋ค(`unidentified`). ์ธ๋ ๊ฒ์ด์ง ๋ง๋ ๊ฒ์ด ์๋๋ค โ\n * ์ ์ฒด๋ฅผ ๋ชป ๋ง๋ ๋ค๊ณ ์ฌ์ค์ ๋ฒ๋ฆฌ๋ฉด ๊ทธ๊ฒ์ด ๋ ๋์๋ค.\n */\n if (!parts.length) {\n unidentified[type] = (unidentified[type] ?? 0) + 1\n return undefined\n }\n const at = timeOf(envelope)\n if (at === undefined) return undefined\n return `${type}|${parts.join('&')}|${at}`\n}\n\n/**\n * ์ต๊ทผ์ ๋ณธ ์ ์ฒด๋ฅผ ๊ธฐ์ตํ๋ค โ **ํฌ๊ธฐ์ ์ํ์ ๋๋ค.**\n *\n * ์ ๋ถ ๊ธฐ์ตํ ์๋ ์๋ค(ํธ์ ํ๋๊ฐ ์์ฒ๋ง ์ฌ๊ฑด์ ๊ฐ๋๋ค). ์ฐฝ์ ๋์ผ๋ฉด ์ค๋๋ ๊ฒ๋ถํฐ ์๋๋ค. ์ฐฝ ๋ฐ์\n * ์ฌ์ ์ก์ ๋ค์ ํต๊ณผํ๋๋ฐ, ๊ทธ๊ฒ์ ์ ๋๊ฐ ์ฌ์ค์ด๋ผ ์ํ์ ํด๊ฐ ์๊ณ ์ง๋ ๊ธฐ๋ก์ ํ ์ค ๋ ๋จ๋๋ค.\n * ์ฐฝ์ ํฌ๊ฒ ์ก์ผ๋ฉด ๊ทธ๋งํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ด๋ค โ ๊ทธ ๊ฐ์ ์ฌ๊ธฐ์ ์ด๋ฆ์ผ๋ก ๋ชป ๋ฐ๋๋ค.\n *\n * **์ฌ๊ธฐ๋์ ๊ฑด๋์ง ๋ชปํ๋ค.** ํ๋ก์ธ์ค๊ฐ ์๋ก ๋จ๋ฉด ๊ธฐ์ต์ด ๋น์ด ์์ผ๋ฏ๋ก, ์ฌ๊ธฐ๋ ์งํ ์ฒซ ์ฃผ๊ธฐ๊ฐ ๊ฐ์\n * ๊ฐ์ ๋ค์ ๋ณด๋ด๋ฉด ๊ฑธ๋ฌ์ง์ง ์๋๋ค. ๊ทธ๊ฒ์ ๋ง์ผ๋ ค๋ฉด ์ด ๊ธฐ์ต์ด ์ ์ฅ๋ผ์ผ ํ๊ณ , ๊ทธ๊ฒ์ ๋ค์ ๊ฑธ์์ด๋ค.\n * ์ง๊ธ์ ๊ทธ ์ฌ์ค์ ์ฌ๊ธฐ ์ ์ด ๋๋ค โ ์ ์ด ๋์ง ์์ผ๋ฉด ใ์ค๋ณต์ ์ด์ ์๋คใ๋ก ์ฝํ๋ค.\n */\nexport class FactDeduper {\n /** ๊ธฐ์ตํ๋ ์ ์ฒด์ ์ โ ์ฐฝ. */\n static WINDOW = 20_000\n\n private seen = new Set<string>()\n private order: string[] = []\n\n /**\n * ์ด๋ฏธ ์๋ ๊ฒ์ผ๋ก **๋ฏธ๋ฆฌ ๊ธฐ์ตํ๋ค** โ ์ ๋์์ ์ฝ์ด ์ฑ์ธ ๋.\n *\n * โโ ์ ํ์ํ๊ฐ (2026-09-06 ์ธก์ ) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ๊ธฐ์ต์ ํ๋ก์ธ์ค ์์๋ง ์๋ค. ์ฌ๊ธฐ๋ํ๋ฉด ๋น์์ง๊ณ , ๊ทธ ๋ค backfill ์ ๋๋ฆฌ๋ฉด **์ด๋ฏธ ์ ๋์\n * ์๋ ์ฌ์ค๋ ใ์ฒ์ ๋ณธ ๊ฒใ**์ด ๋๋ค.\n *\n * ์ค์ ๋ก ๊ทธ๋ฌ๋ค. `mes-line-a` ๋ฅผ ์ฌ๊ธฐ๋ ๋ค backfill ํ๋ 39๊ฑด์ด ์ ๋ถ ๋ค์ ์์ ์ ๋์ด\n * 44 โ 83๊ฑด์ด ๋๊ณ 44๊ฐ์ง๊ฐ ์ค๋ณต์ด ๋๋ค.\n *\n * push ๊ฒฝ๋ก์์๋ ์ ๋ณด์ธ๋ค. ์ฌ์ ์ก์ด ๋ช ๋ถ ์์ ์ค๋ฏ๋ก ์ฐฝ ์์์ ๊ฑธ๋ฆฐ๋ค. **backfill ์ด ๊ทธ ์ ์ ๋ฅผ\n * ๊นฌ๋ค** โ ๋ช ๋ฌ ์ ์ฌ์ค์ ์ง๊ธ ๋ฐ์ผ๋ ์ฌ๊ธฐ๋ ํ ๋ฒ์ด๋ฉด ๊ทธ ๊ตฌ๊ฐ์ด ํต์งธ๋ก ๋ค์ ์๋๋ค.\n *\n * ๊ทธ๋์ backfill ์ด ๋ถ๋ฅด๊ธฐ ์ ์ ๊ทธ ๊ตฌ๊ฐ์ ์ ์ฒด๋ฅผ ์ ๋์์ ์ฝ์ด ์ฌ๊ธฐ ๋ฃ๋๋ค.\n */\n remember(identities: readonly string[]): number {\n let added = 0\n for (const id of identities) if (id && !this.seen.has(id)) { this.known(id); added++ }\n return added\n }\n\n /** ์ด ์ฌ์ค์ ๋ณธ ์ ์ด ์๋ โ ์์ผ๋ฉด ๊ธฐ์ตํ๊ณ `false`. */\n private known(identity: string): boolean {\n if (this.seen.has(identity)) return true\n this.seen.add(identity)\n this.order.push(identity)\n if (this.order.length > FactDeduper.WINDOW) {\n const gone = this.order.splice(0, this.order.length - FactDeduper.WINDOW)\n for (const g of gone) this.seen.delete(g)\n }\n return false\n }\n\n /**\n * ์ฒ์ ๋ณด๋ ๊ฒ๋ง ๋๋ ค์ค๋ค โ ๊ทธ๋ฆฌ๊ณ ๋ช ๊ฐ๋ฅผ ๋ฒ๋ ธ๋์ง ํจ๊ป ๋ธ๋ค.\n *\n * ๋ฒ๋ฆฐ ์๋ฅผ ํจ๊ป ๋ด๋ ์ด์ : ์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ๋ฉด ใ๋ณด๋ธ ์ใ์ ใ๋ฐ์๋ ์ใ๊ฐ ์ด๊ธ๋๋๋ฐ ์๋ฌด๋ ๊ทธ\n * ์ด์ ๋ฅผ ๋ชจ๋ฅธ๋ค. ๊ทธ ์๊ฐ ํฌ๋ฉด ๋ณด๋ด๋ ์ชฝ์ด ๋ํ์ด ๋ณด๋ด๊ณ ์๋ค๋ ๋ป์ด๊ณ , ๊ทธ๊ฒ์ ๊ณ ์น ์ผ์ด๋ค.\n */\n filter<T>(envelopes: readonly T[]): { fresh: T[]; duplicates: number } {\n const fresh: T[] = []\n let duplicates = 0\n for (const e of envelopes) {\n const id = factIdentity(e)\n if (id === undefined) {\n fresh.push(e)\n continue\n }\n if (this.known(id)) duplicates++\n else fresh.push(e)\n }\n return { fresh, duplicates }\n }\n\n /** ๊ธฐ์ตํ๊ณ ์๋ ์ ์ฒด์ ์ โ ๊ณ๊ธฐ๊ฐ ์ฝ๋๋ค. */\n size(): number {\n return this.seen.size\n }\n}\n"]}
|
|
@@ -34,6 +34,8 @@ export interface IngestWindow {
|
|
|
34
34
|
* ์ธ๋ฉด ๊ทธ ๊ฐ์ ๋, ๋๋์๊ฐ๋ ๊ฒ๋ ๋ณด์ด์ง ์๋๋ค.
|
|
35
35
|
*/
|
|
36
36
|
flushes: number;
|
|
37
|
+
/** ์ด ์ฐฝ์์ ์ ๋์ ์ ๊ฐ ์ดํ ์์์ ์ โ ์ฌ๋ผ์ง ๊ฒ์ด ์๋๋ผ ์ ๋๋ก ๊ฐ์ง ์๋ ๊ฒ์ด๋ค. */
|
|
38
|
+
vocabulary: number;
|
|
37
39
|
}
|
|
38
40
|
/** ๊ฑฐ๋ถ ํ๋ณธ ํ๋ โ ๋งคํ์ ๊ณ ์น๋ ค๋ฉด ์ค์ ๋ชจ์์ ๋ด์ผ ํ๋ค. */
|
|
39
41
|
export interface RejectSample {
|
|
@@ -54,6 +56,17 @@ export interface IngestLedger {
|
|
|
54
56
|
/** ๋์ ์ ์ยท๊ฑฐ๋ถยท๋ฏธ์ ๋ฌ. */
|
|
55
57
|
offered: number;
|
|
56
58
|
rejected: number;
|
|
59
|
+
/**
|
|
60
|
+
* **์ ๋์ ์ ๊ฐ๋ ์ดํ ์์์ ์** โ ๋กํธ ๋ฒํธยท์๋น๊ธฐํ์ฒ๋ผ ์๊ฐ์ถ์ด ์๋ ๊ฐ.
|
|
61
|
+
*
|
|
62
|
+
* โโ ์ ์ธ๋ (2026-09-05, ์ธํฐ๊ทธ๋ ์ด์
๋ ์ธ์ด ์
์ผ๋ก ์ฐพ์) โโโโโโโโโโโโโโโโโ
|
|
63
|
+
* ์ดํ๋ ์ผ๋ถ๋ฌ ์ ๋๋ก ์ ๊ฐ๋ค(ยง`canonical-ingest`) โ ๊ทธ๊ฒ์ด ์ณ๋ค. ๊ทธ๋ฐ๋ฐ **๊ทธ ์๋ฅผ ๋นผ ์ฃผ๋
|
|
64
|
+
* ์๋ฆฌ๊ฐ ์์ด์** ใ๋ณด๋ธ ๊ฒ โ ์์ ๊ฒใ์ด ์ ๋ง๊ณ , ๊ทธ ์ฐจ์ด๋ฅผ ใ์ฌ๋ผ์ก๋คใ๋ก ์ฝ๊ฒ ๋๋ค.
|
|
65
|
+
*
|
|
66
|
+
* ์ค์ ๋ก ๊ทธ๋ฌ๋ค: ์ปค์ 20 ยท ์ ๋ 17 ยท ์ดํ 1 โ ์ฌ๋์ด ์์ผ๋ก ์ธ์ ใ๋์ด ๋น๋คใ๋ฅผ ์ฐพ์๋ค. ๊ทธ
|
|
67
|
+
* ๋บ์
์ ์ฝ๋๊ฐ ํ๋ ค๋ฉด ์ด ํญ์ด ์์ด์ผ ํ๋ค.
|
|
68
|
+
*/
|
|
69
|
+
vocabulary: number;
|
|
57
70
|
undelivered: number;
|
|
58
71
|
/** ๋์ โ ์ ํ ํ๊ณผ ๋๋๋ฆฐ ํ์. */
|
|
59
72
|
rows: number;
|
|
@@ -265,6 +278,16 @@ export declare function recordCursorStall(ledger: IngestLedger, reason: string,
|
|
|
265
278
|
*/
|
|
266
279
|
export declare function recordIngestSource(ledger: IngestLedger, source: string, count: number, nowMs: number): void;
|
|
267
280
|
/** ๊ฐ์ ์ฌ์ค์ด ๋ ๋ฒ ์์ ๋ฒ๋ฆฐ ์ โ ์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค. */
|
|
281
|
+
/**
|
|
282
|
+
* **์ ๋์ ์ ๊ฐ ์ดํ ์์๋ฅผ ์ผ๋ค** โ ์์ด์ง ๊ฒ์ด ์๋๋ผ ์ ๋๋ก ๊ฐ์ง ์๋ ๊ฒ์ด๋ค.
|
|
283
|
+
*
|
|
284
|
+
* ์ดํ(๋กํธ ๋ฒํธยท์๋น๊ธฐํ ๋ฑ)๋ ์๊ฐ์ถ์ด ์์ด ์ผ๋ถ๋ฌ ์ ๋๋ก ์ ๊ฐ๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ์๋ฅผ ๋นผ ์ฃผ๋ ์๋ฆฌ๊ฐ
|
|
285
|
+
* ์์ผ๋ฉด ใ๋ณด๋ธ ๊ฒ โ ์์ ๊ฒใ์ด ์ ๋ง๊ณ , ๊ทธ ์ฐจ์ด๋ฅผ **์ฌ๋ผ์ง ๊ฒ์ผ๋ก ์ฝ๊ฒ ๋๋ค.**
|
|
286
|
+
*
|
|
287
|
+
* ์ฐฝ์ ๊ตด๋ฆฌ์ง ์๋๋ค โ ๋ถ๋ฅด๋ ์ชฝ(`recordIngest`)์ด ์ด๋ฏธ ๊ตด๋ฆฐ ๋ค์ ๋ถ๋ฅธ๋ค. ์ฌ๊ธฐ์ ๋ ๊ตด๋ฆฌ๋ฉด ํ
|
|
288
|
+
* ์ ์
์ด ๋ ์ฐฝ์ ๊ฑธ์น๋ค.
|
|
289
|
+
*/
|
|
290
|
+
export declare function recordVocabulary(ledger: IngestLedger, count: number): void;
|
|
268
291
|
export declare function recordDuplicates(ledger: IngestLedger, count: number, nowMs: number): void;
|
|
269
292
|
export declare function recordWithheld(ledger: IngestLedger, reason: string, count: number, nowMs: number): void;
|
|
270
293
|
/** ์ฐฝ์ ๋๊ฒผ์ผ๋ฉด ์ง์ด๋ค โ ํ๋ฆฐ ์ ์ฒด๊ฐ ํ๋ฉด์ ๋จ์ ์์ผ๋ฉด ๊ทธ๊ฒ๋ ๊ฑฐ์ง์ด๋ค. */
|
|
@@ -371,7 +394,22 @@ export type SyncVerdict = 'syncing' /** ์ ์
์ด ์๊ณ ํต๊ณผ์จ์ด ๋ฌธํฑ ์ด
|
|
|
371
394
|
* ๊ทธ๋์ **ํ๋ฉด ๋ฌธ๊ตฌ๋ ๊ด์ธก ๊ทธ๋๋ก** ์ ๋๋ค(ใํธ์์ ๋ฟ์ง ์๊ณ ๋ฒ๋ ค์ง๋ ์คใ). ์ด ํค ์ด๋ฆ์ ์๋ฒยทํ๋ฉดยท
|
|
372
395
|
* ์ํ์ ๊ฑธ์น ๊ณ์ฝ ๋ฌธ์์ด์ด๋ผ ๊ทธ๋๋ก ๋์ง๋ง, ์ด๋ฆ์ ์์ธ์ผ๋ก ์ฝ์ง ์๋๋ค.
|
|
373
396
|
*/
|
|
374
|
-
| 'twin-not-running' | 'no-traffic' /** ํผ๋๋ ๋ถ์๋๋ฐ ์ ์๊ฐ 0 โ ์์ฒยท๋ง์ ๋ณธ๋ค */ | 'not-connected' /** ํผ๋ ์์ฒด๊ฐ ์๋ค โ ๊ฒฐ์ ํ๋ค */ | 'not-applicable' /** ์๋ณธ์ด ๋จน์ด์ง ์๋ ํธ์(์๋ฎฌ)ยท๋ฉ์ถ ํธ์ โ ๋ฌผ์ ๋์์ด ์๋๋ค */
|
|
397
|
+
| 'twin-not-running' | 'no-traffic' /** ํผ๋๋ ๋ถ์๋๋ฐ ์ ์๊ฐ 0 โ ์์ฒยท๋ง์ ๋ณธ๋ค */ | 'not-connected' /** ํผ๋ ์์ฒด๊ฐ ์๋ค โ ๊ฒฐ์ ํ๋ค */ | 'not-applicable' /** ์๋ณธ์ด ๋จน์ด์ง ์๋ ํธ์(์๋ฎฌ)ยท๋ฉ์ถ ํธ์ โ ๋ฌผ์ ๋์์ด ์๋๋ค */
|
|
398
|
+
/**
|
|
399
|
+
* **์ง๊ธ์ ์กฐ์ฉํ ๊ฒ์ด ์ ์์ด๋ค** โ ์์ฒ์ด ์ง๊ธ ์๊ฐ์ ๋ด๋์ง ์๋๋ค.
|
|
400
|
+
*
|
|
401
|
+
* โโ ์ ์ด๋ก๋ ๋นจ๊ฐ๋ ์๋๊ฐ (2026-09-04) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
402
|
+
* ํ์๊ด์ ๋ฐค์ ๋ฐ์ ํ์ง ์๊ณ , ์
๋ฌด์๊ฐ๋ง ๋๋ ์์ฒ์ ์ ๋
์ ์๋ฌด๊ฒ๋ ๋ด์ง ์๋๋ค. ๊ทธ ์นจ๋ฌต์
|
|
403
|
+
* `no-traffic` ์ผ๋ก ๋ถ๋ฅด๋ฉด **์ ์์ธ ๋ฐค๋ง๋ค ์ ๋ฐ์ด ๋นจ๊ฐ๊ฒ ๋๋ค.** ๊ฑฐ์ง ๋นจ๊ฐ์ด ์์ด๋ฉด ์ง์ง ๋นจ๊ฐ๋
|
|
404
|
+
* ๊ฐ์ด ์ ์ฝํ๋ค โ ์ค๋ UX ๋ ์ธ์ด ใ๋ ์ฐธ์ธ ๊ฒฝ๊ณ ๋ ๋ฒฝ์ง๊ฐ ๋๋คใ๊ณ ํ ๊ฒ๊ณผ ๊ฐ์ ๋ถ๋ฅ๋ค.
|
|
405
|
+
*
|
|
406
|
+
* ๊ทธ๋ ๋ค๊ณ `syncing` ๋ ์๋๋ค. ์ง๊ธ ๋ฐ๊ณ ์๋ ๊ฒ์ด ์๋๊ณ , ์ด๋ก์ผ๋ก ์น ํ๋ฉด **๋ฐค์ ์ ๋ง ๋๊ธด
|
|
407
|
+
* ์์ฒ**์ ์์นจ๊น์ง ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.
|
|
408
|
+
*
|
|
409
|
+
* ๊ทธ๋์ ์
์งธ ๊ฐ์ด๋ค: ใ์ง๊ธ์ ์ ์ค๋ ๊ฒ์ด ๋ง๋คใ. ํ๋ฉด์ ์ด๊ฒ์ ํ์์ผ๋ก ๊ทธ๋ฆฌ๊ณ , ๋ค์์ ์ฌ
|
|
410
|
+
* ์๊ฐ์ ํจ๊ป ๋งํ ์ ์๋ค.
|
|
411
|
+
*/
|
|
412
|
+
| 'expected-quiet' | 'unknown'; /** ํ ๋ฒ๋ ๋ฐ์ง ์์๊ฑฐ๋ ์ฐฝ์ด ์์ง ๋ซํ์ง ์์๋ค โ ๊ธฐ๋ค๋ฆฐ๋ค */
|
|
375
413
|
export declare function syncVerdictOf(args: {
|
|
376
414
|
/** `live-feed-registry.liveFeedStateOf` ์ ๋ต์ ๊ทธ๋๋ก ๋ฐ๋๋ค โ ํ์ ์ดํ๋ฅผ ๋ ๋ฒ ๋ง๋ค์ง ์๋๋ค. */
|
|
377
415
|
feedState: 'attached' | 'detached' | 'not-applicable';
|
|
@@ -386,6 +424,27 @@ export declare function syncVerdictOf(args: {
|
|
|
386
424
|
nowMs?: number;
|
|
387
425
|
/** ๋ง์ง๋ง์ผ๋ก **๋ฒ๋ ค์ง** ์๊ฐ. ํ ๋ฒ๋ ์์ผ๋ฉด `-1`. */
|
|
388
426
|
lastUndeliveredAtMs?: number;
|
|
427
|
+
/**
|
|
428
|
+
* **์ด ์์ฒ์ ์ด๋งํผ ์กฐ์ฉํด๋ ์ ์์ด๋ค** โ ๊ธท๋ ์ฃผ๊ธฐ๋ฅผ ์์ฒ ์ชฝ์ด ์ ์ธํ ๊ฐ.
|
|
429
|
+
*
|
|
430
|
+
* ์์ผ๋ฉด ์ฐฝ ํ๋(`STALE_AFTER_MS`)๋ก ๊ฒฌ์ค๋ค(์ง๊ธ๊น์ง์ ๊ฑฐ๋). 15๋ถ๋ง๋ค ๊ธท๋ ์์ฒ์ ๊ทธ ๊ฐ์
|
|
431
|
+
* ์ ์ธํด์ผ ํ๊ณ , ์ ํ๋ฉด ๊ธท๋ ์ฌ์ด๋ง๋ค ใ์ ์
์์ใ์ผ๋ก ๋ณด์ธ๋ค โ ์ด ํ์ผ์ด ์๋์์ ๊ทธ ํ๊ณ๋ฅผ
|
|
432
|
+
* ์ค์ค๋ก ์ ์ด ๋๊ณ ์์๋ค.
|
|
433
|
+
*
|
|
434
|
+
* ์ฅ๋ถ๋ ์์ฒ์ ์ฃผ๊ธฐ๋ฅผ ์ ์ ์๋ค. **์ ์ธ๋ง์ด ๊ทธ๊ฒ์ ์๋ ์ ์ผํ ๊ธธ์ด๋ค.**
|
|
435
|
+
*/
|
|
436
|
+
expectedSilenceMs?: number;
|
|
437
|
+
/**
|
|
438
|
+
* **์ง๊ธ์ด ๊ทธ ์์ฒ์ ์กฐ์ฉํ ์๊ฐ์ธ๊ฐ** โ ๊ทผ๋ฌด ๋ฌ๋ ฅ ํ์ ์ ๊ฒฐ๊ณผ๋ง ๋ฐ๋๋ค.
|
|
439
|
+
*
|
|
440
|
+
* ๋ฌ๋ ฅ ์์ฒด๋ฅผ ์ฌ๊ธฐ์ ๋ณด์ง ์๋๋ค: ์ด ํจ์๋ ์์ํ๊ณ , ๋ฌ๋ ฅยท์๊ฐ๋ยท์๊ฐ ํด์์ ๊ณ์ฝ์ด ์ด๋ฏธ
|
|
441
|
+
* ํ ์๋ฆฌ์์ ํ๋ค(`inWorkCalendar`ยท`offCalendarAt`). ๋ถ๋ฅด๋ ์ชฝ์ด ๊ทธ๊ฒ์ ๋ถ๋ฌ ์ฐธยท๊ฑฐ์ง๋ง ์ค๋ค โ
|
|
442
|
+
* `capabilityOf` ๊ฐ `requiredTests` ๋ฅผ ๋ฐ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ท์จ์ด๋ค.
|
|
443
|
+
*
|
|
444
|
+
* **๋ชจ๋ฅด๋ฉด ์ฃผ์ง ์๋๋ค.** `false` ๋ก ์ฑ์ฐ๋ฉด ใ์ง๊ธ์ ํ๋ ์๊ฐ์ด๋คใ๋ฅผ ๋จ์ธํ๋ ๊ฒ์ด ๋๊ณ , ๋ฌ๋ ฅ์
|
|
445
|
+
* ์ ์ธํ์ง ์์ ์์ฒ์ด ์ ๋ถ ๊ทธ๋ ๊ฒ ์ฝํ๋ค.
|
|
446
|
+
*/
|
|
447
|
+
quietNow?: boolean;
|
|
389
448
|
/**
|
|
390
449
|
* ์ง๊ธ๊น์ง ์ ์๋ ๋์ ์ โ **ใ๋ฐ๊ณ ์๋ ์คใ๊ณผ ใ์ค๋ ๊ฒ์ด ์๋คใ๋ฅผ ๊ฐ๋ฅด๋ ์ฌ์ค**์ด๋ค.
|
|
391
450
|
*
|
|
@@ -34,6 +34,7 @@ exports.recordRecovered = recordRecovered;
|
|
|
34
34
|
exports.clearReadFailure = clearReadFailure;
|
|
35
35
|
exports.recordCursorStall = recordCursorStall;
|
|
36
36
|
exports.recordIngestSource = recordIngestSource;
|
|
37
|
+
exports.recordVocabulary = recordVocabulary;
|
|
37
38
|
exports.recordDuplicates = recordDuplicates;
|
|
38
39
|
exports.recordWithheld = recordWithheld;
|
|
39
40
|
exports.clearCursorStall = clearCursorStall;
|
|
@@ -134,6 +135,21 @@ function recordIngestSource(ledger, source, count, nowMs) {
|
|
|
134
135
|
cur.lastAtMs = nowMs;
|
|
135
136
|
}
|
|
136
137
|
/** ๊ฐ์ ์ฌ์ค์ด ๋ ๋ฒ ์์ ๋ฒ๋ฆฐ ์ โ ์๋ฆฌ์ง ์๊ณ ๋ฒ๋ฆฌ์ง ์๋๋ค. */
|
|
138
|
+
/**
|
|
139
|
+
* **์ ๋์ ์ ๊ฐ ์ดํ ์์๋ฅผ ์ผ๋ค** โ ์์ด์ง ๊ฒ์ด ์๋๋ผ ์ ๋๋ก ๊ฐ์ง ์๋ ๊ฒ์ด๋ค.
|
|
140
|
+
*
|
|
141
|
+
* ์ดํ(๋กํธ ๋ฒํธยท์๋น๊ธฐํ ๋ฑ)๋ ์๊ฐ์ถ์ด ์์ด ์ผ๋ถ๋ฌ ์ ๋๋ก ์ ๊ฐ๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ์๋ฅผ ๋นผ ์ฃผ๋ ์๋ฆฌ๊ฐ
|
|
142
|
+
* ์์ผ๋ฉด ใ๋ณด๋ธ ๊ฒ โ ์์ ๊ฒใ์ด ์ ๋ง๊ณ , ๊ทธ ์ฐจ์ด๋ฅผ **์ฌ๋ผ์ง ๊ฒ์ผ๋ก ์ฝ๊ฒ ๋๋ค.**
|
|
143
|
+
*
|
|
144
|
+
* ์ฐฝ์ ๊ตด๋ฆฌ์ง ์๋๋ค โ ๋ถ๋ฅด๋ ์ชฝ(`recordIngest`)์ด ์ด๋ฏธ ๊ตด๋ฆฐ ๋ค์ ๋ถ๋ฅธ๋ค. ์ฌ๊ธฐ์ ๋ ๊ตด๋ฆฌ๋ฉด ํ
|
|
145
|
+
* ์ ์
์ด ๋ ์ฐฝ์ ๊ฑธ์น๋ค.
|
|
146
|
+
*/
|
|
147
|
+
function recordVocabulary(ledger, count) {
|
|
148
|
+
if (!Number.isFinite(count) || count <= 0)
|
|
149
|
+
return;
|
|
150
|
+
ledger.vocabulary += count;
|
|
151
|
+
ledger.window.vocabulary += count;
|
|
152
|
+
}
|
|
137
153
|
function recordDuplicates(ledger, count, nowMs) {
|
|
138
154
|
if (count <= 0)
|
|
139
155
|
return;
|
|
@@ -201,7 +217,7 @@ exports.RECORD_MAX = 2000;
|
|
|
201
217
|
exports.HEALTHY_ACCEPTED_RATIO = 0.95;
|
|
202
218
|
function newIngestLedger() {
|
|
203
219
|
return {
|
|
204
|
-
window: { startMs: -1, endMs: -1, offered: 0, rejected: 0, undelivered: 0, rows: 0, flushes: 0 },
|
|
220
|
+
window: { startMs: -1, endMs: -1, offered: 0, rejected: 0, vocabulary: 0, undelivered: 0, rows: 0, flushes: 0 },
|
|
205
221
|
trend: [],
|
|
206
222
|
trendDropped: 0,
|
|
207
223
|
offered: 0,
|
|
@@ -213,6 +229,7 @@ function newIngestLedger() {
|
|
|
213
229
|
lastUndeliveredAtMs: -1,
|
|
214
230
|
bySource: {},
|
|
215
231
|
duplicates: 0,
|
|
232
|
+
vocabulary: 0,
|
|
216
233
|
lastDuplicateAtMs: -1,
|
|
217
234
|
byReason: {},
|
|
218
235
|
reasonsCapped: false,
|
|
@@ -244,7 +261,7 @@ function rollIngestWindow(ledger, nowMs, windowMs = exports.INGEST_WINDOW_MS, on
|
|
|
244
261
|
return;
|
|
245
262
|
const closed = { ...ledger.window, endMs: nowMs };
|
|
246
263
|
ledger.trend.push(closed);
|
|
247
|
-
ledger.window = { startMs: nowMs, endMs: -1, offered: 0, rejected: 0, undelivered: 0, rows: 0, flushes: 0 };
|
|
264
|
+
ledger.window = { startMs: nowMs, endMs: -1, offered: 0, rejected: 0, vocabulary: 0, undelivered: 0, rows: 0, flushes: 0 };
|
|
248
265
|
if (ledger.trend.length > exports.TREND_LIMIT) {
|
|
249
266
|
const drop = ledger.trend.length - exports.TREND_LIMIT;
|
|
250
267
|
ledger.trend.splice(0, drop);
|
|
@@ -397,11 +414,27 @@ function syncVerdictOf(args) {
|
|
|
397
414
|
* ํ๊ณ โ ํ ์ฐฝ(10๋ถ)๋ณด๋ค **๋๋ฆฌ๊ฒ ๊ธท๋ ์์ฒ**์ ๊ธท๋ ์ฌ์ด์ ใ์ ์
์์ใ์ผ๋ก ๋ณด์ธ๋ค. ์ฅ๋ถ๋ ์์ฒ์
|
|
398
415
|
* ์ฃผ๊ธฐ๋ฅผ ๋ชจ๋ฅด๋ฏ๋ก ์ด๋ณด๋ค ์ ํํ ๋ตํ ์ ์๋ค. ์ฃผ๊ธฐ๋ฅผ ์๊ฒ ๋๋ฉด ๊ทธ ๊ฐ์ผ๋ก ๊ฒฌ์ฃผ๋ ๊ฒ์ด ๋ง๋ค.
|
|
399
416
|
*/
|
|
417
|
+
/*
|
|
418
|
+
* ๊ฒฌ์ค ๊ธธ์ด๋ **์์ฒ์ด ์ ์ธํ ๊ฐ์ด ์์ผ๋ฉด ๊ทธ๊ฒ**์ด๋ค(ยง`expectedSilenceMs`). ์์ผ๋ฉด ์ฐฝ ํ๋ โ
|
|
419
|
+
* ์ ํ๊ณ ๋ฌธ๋จ์ด ๋งํ๋ ๊ทธ๋๋ก๋ค.
|
|
420
|
+
*/
|
|
421
|
+
const silenceLimitMs = typeof args.expectedSilenceMs === 'number' && args.expectedSilenceMs > 0
|
|
422
|
+
? args.expectedSilenceMs
|
|
423
|
+
: exports.STALE_AFTER_MS;
|
|
400
424
|
if (typeof args.lastAtMs === 'number' && typeof args.nowMs === 'number') {
|
|
401
|
-
if (args.lastAtMs < 0)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
425
|
+
if (args.lastAtMs < 0) {
|
|
426
|
+
/* ํ ๋ฒ๋ ๋ฐ์ง ์์๋๋ฐ ์ง๊ธ์ด ์กฐ์ฉํ ์๊ฐ์ด๋ฉด ใ๊ธฐ๋ค๋ฆฐ๋คใ๊ฐ ์๋๋ผ ใ์ง๊ธ์ ๋ง๋คใ๋ค. */
|
|
427
|
+
return args.quietNow === true ? 'expected-quiet' : 'unknown';
|
|
428
|
+
}
|
|
429
|
+
if (args.nowMs - args.lastAtMs > silenceLimitMs) {
|
|
430
|
+
/*
|
|
431
|
+
* ์ค๋ ์กฐ์ฉํ๋ค. **์ง๊ธ์ด ๊ทธ ์์ฒ์ ์กฐ์ฉํ ์๊ฐ์ด๋ฉด ๊ทธ๊ฒ์ด ์ ์์ด๋ค.**
|
|
432
|
+
*
|
|
433
|
+
* ์ด ๊ฐ๋๋ฅผ ์์ชฝ(๋ฒ๋ ค์ง๋ ์คยทํผ๋ ์์)๋ณด๋ค ๋ค์ ๋๋ ์ด์ : ์ฌ์ค์ด ์ฌ๋ผ์ง๊ณ ์๊ฑฐ๋ ๊ฒฐ์ ์ด
|
|
434
|
+
* ์๋ ๊ฒ์ **๋ช ์๋ ๋ฌธ์ **๋ค. ๋ฐค์ด๋ผ๊ณ ๋ฎ์ผ๋ฉด ๋ฐค์ ์๋ ๊ฒ์ ์์นจ์ ์๋ค.
|
|
435
|
+
*/
|
|
436
|
+
return args.quietNow === true ? 'expected-quiet' : 'no-traffic';
|
|
437
|
+
}
|
|
405
438
|
}
|
|
406
439
|
/*
|
|
407
440
|
* โโ **๋ฟ์๋๋ฐ ์ค๋ ๊ฒ์ด ์๋ค** ๋ฅผ ใ๋ชจ๋ฅธ๋คใ๋ก ๋ตํ์ง ์๋๋ค (2026-08-28) โโโโ
|
|
@@ -424,10 +457,12 @@ function syncVerdictOf(args) {
|
|
|
424
457
|
if (!args.recent) {
|
|
425
458
|
const touched = typeof args.lastAtMs === 'number' && args.lastAtMs >= 0;
|
|
426
459
|
const nothingOffered = (args.offeredTotal ?? 0) <= 0;
|
|
427
|
-
|
|
460
|
+
if (touched && nothingOffered)
|
|
461
|
+
return args.quietNow === true ? 'expected-quiet' : 'no-traffic';
|
|
462
|
+
return 'unknown';
|
|
428
463
|
}
|
|
429
464
|
if (args.recent.offered <= 0)
|
|
430
|
-
return 'no-traffic';
|
|
465
|
+
return args.quietNow === true ? 'expected-quiet' : 'no-traffic';
|
|
431
466
|
const ratio = (args.recent.offered - args.recent.rejected) / args.recent.offered;
|
|
432
467
|
return ratio >= (args.threshold ?? exports.HEALTHY_ACCEPTED_RATIO) ? 'syncing' : 'mapping-blocked';
|
|
433
468
|
}
|