@things-factory/headless-twin 10.1.278 → 10.1.280

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.
Files changed (614) hide show
  1. package/package.json +21 -7
  2. package/dist-server/engine/attention-digest.js.map +0 -1
  3. package/dist-server/engine/canonical-ingest.js.map +0 -1
  4. package/dist-server/engine/checkpoint-fold.js.map +0 -1
  5. package/dist-server/engine/command-routing.js.map +0 -1
  6. package/dist-server/engine/declared-stimulus.js.map +0 -1
  7. package/dist-server/engine/energy-topology.js.map +0 -1
  8. package/dist-server/engine/event-time.js.map +0 -1
  9. package/dist-server/engine/index.js.map +0 -1
  10. package/dist-server/engine/ingest-dedupe.js.map +0 -1
  11. package/dist-server/engine/ingest-health.js.map +0 -1
  12. package/dist-server/engine/integration-coverage.js.map +0 -1
  13. package/dist-server/engine/integration-probes.js.map +0 -1
  14. package/dist-server/engine/integration-runner.js.map +0 -1
  15. package/dist-server/engine/integration-target-profile.js.map +0 -1
  16. package/dist-server/engine/kpi-baseline.js.map +0 -1
  17. package/dist-server/engine/kpi-fold.js.map +0 -1
  18. package/dist-server/engine/kpi-query.js.map +0 -1
  19. package/dist-server/engine/kpi-target.js.map +0 -1
  20. package/dist-server/engine/live-attentions.js.map +0 -1
  21. package/dist-server/engine/live-feed-registry.js.map +0 -1
  22. package/dist-server/engine/load-meter.js.map +0 -1
  23. package/dist-server/engine/local-declarations.js.map +0 -1
  24. package/dist-server/engine/log.js.map +0 -1
  25. package/dist-server/engine/loop-lag.js.map +0 -1
  26. package/dist-server/engine/measured-estimator.js.map +0 -1
  27. package/dist-server/engine/measured-yield.js.map +0 -1
  28. package/dist-server/engine/model-basis.js.map +0 -1
  29. package/dist-server/engine/model-gap.js.map +0 -1
  30. package/dist-server/engine/model-refusal.js.map +0 -1
  31. package/dist-server/engine/model-vocabulary.js.map +0 -1
  32. package/dist-server/engine/oee-accumulator.js.map +0 -1
  33. package/dist-server/engine/operation-basis.js.map +0 -1
  34. package/dist-server/engine/producer-guard.js.map +0 -1
  35. package/dist-server/engine/property-effects.js.map +0 -1
  36. package/dist-server/engine/read-time.js.map +0 -1
  37. package/dist-server/engine/restart-policy.js.map +0 -1
  38. package/dist-server/engine/runtime-key.js.map +0 -1
  39. package/dist-server/engine/spec-coverage.js.map +0 -1
  40. package/dist-server/engine/stage-path.js.map +0 -1
  41. package/dist-server/engine/state-axes.js.map +0 -1
  42. package/dist-server/engine/structure-diff.js.map +0 -1
  43. package/dist-server/engine/travel-estimator.js.map +0 -1
  44. package/dist-server/engine/twin-engine.js.map +0 -1
  45. package/dist-server/engine/twin-state-channel.js.map +0 -1
  46. package/dist-server/engine/warm-start.js.map +0 -1
  47. package/dist-server/index.js.map +0 -1
  48. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +0 -1
  49. package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +0 -1
  50. package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +0 -1
  51. package/dist-server/migrations/1786300000000-IndexEventTypeByTime.js.map +0 -1
  52. package/dist-server/migrations/1786400000000-IndexEventCreatedAt.js.map +0 -1
  53. package/dist-server/migrations/1786500000000-CreateTwinSubjectEvents.js.map +0 -1
  54. package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +0 -1
  55. package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +0 -1
  56. package/dist-server/migrations/1786800000000-CreateTwinReferenceReconciliations.js.map +0 -1
  57. package/dist-server/migrations/index.js.map +0 -1
  58. package/dist-server/routes.js.map +0 -1
  59. package/dist-server/service/actuation/actuation-advisor.js.map +0 -1
  60. package/dist-server/service/actuation/actuation-outcome.js.map +0 -1
  61. package/dist-server/service/actuation/actuation-rule-resolver.js.map +0 -1
  62. package/dist-server/service/actuation/actuation-rule.js.map +0 -1
  63. package/dist-server/service/actuation/approval-gateway.js.map +0 -1
  64. package/dist-server/service/actuation/catch-up-effects.js.map +0 -1
  65. package/dist-server/service/actuation/command-dispatcher.js.map +0 -1
  66. package/dist-server/service/actuation/command-store.js.map +0 -1
  67. package/dist-server/service/actuation/dispatch-after-approval.js.map +0 -1
  68. package/dist-server/service/actuation/effect-match.js.map +0 -1
  69. package/dist-server/service/actuation/index.js.map +0 -1
  70. package/dist-server/service/actuation/retry-plan.js.map +0 -1
  71. package/dist-server/service/actuation/rule-evaluate.js.map +0 -1
  72. package/dist-server/service/actuation/rule-loop.js.map +0 -1
  73. package/dist-server/service/actuation/rule-runner.js.map +0 -1
  74. package/dist-server/service/actuation/rule-wiring.js.map +0 -1
  75. package/dist-server/service/actuation/settle-effects.js.map +0 -1
  76. package/dist-server/service/actuation/sweep-dispatch.js.map +0 -1
  77. package/dist-server/service/actuation/twin-command-resolver.js.map +0 -1
  78. package/dist-server/service/actuation/twin-command.js.map +0 -1
  79. package/dist-server/service/actuation/twin-now.js.map +0 -1
  80. package/dist-server/service/index.js.map +0 -1
  81. package/dist-server/service/reference/actuation-routing.js.map +0 -1
  82. package/dist-server/service/reference/actuation-target.js.map +0 -1
  83. package/dist-server/service/reference/actuation-verification.js.map +0 -1
  84. package/dist-server/service/reference/attention-lane.js.map +0 -1
  85. package/dist-server/service/reference/connection-portability-resolver.js.map +0 -1
  86. package/dist-server/service/reference/connection-portability.js.map +0 -1
  87. package/dist-server/service/reference/control-routing.js.map +0 -1
  88. package/dist-server/service/reference/discovery-result.js.map +0 -1
  89. package/dist-server/service/reference/fill-cadence.js.map +0 -1
  90. package/dist-server/service/reference/fill-dedupe.js.map +0 -1
  91. package/dist-server/service/reference/fill-loop.js.map +0 -1
  92. package/dist-server/service/reference/fill-span.js.map +0 -1
  93. package/dist-server/service/reference/hook-contract.js.map +0 -1
  94. package/dist-server/service/reference/hook-rejected.js.map +0 -1
  95. package/dist-server/service/reference/hook-store.js.map +0 -1
  96. package/dist-server/service/reference/index.js.map +0 -1
  97. package/dist-server/service/reference/ingest-space.js.map +0 -1
  98. package/dist-server/service/reference/knob-defaults.js.map +0 -1
  99. package/dist-server/service/reference/live-cadence.js.map +0 -1
  100. package/dist-server/service/reference/live-feed-lease.js.map +0 -1
  101. package/dist-server/service/reference/live-ingest.js.map +0 -1
  102. package/dist-server/service/reference/reference-adapter.js.map +0 -1
  103. package/dist-server/service/reference/reference-assessment.js.map +0 -1
  104. package/dist-server/service/reference/reference-fill-run.js.map +0 -1
  105. package/dist-server/service/reference/reference-fill.js.map +0 -1
  106. package/dist-server/service/reference/reference-hook.js.map +0 -1
  107. package/dist-server/service/reference/reference-link-groups.js.map +0 -1
  108. package/dist-server/service/reference/reference-links.js.map +0 -1
  109. package/dist-server/service/reference/reference-live.js.map +0 -1
  110. package/dist-server/service/reference/reference-master.js.map +0 -1
  111. package/dist-server/service/reference/reference-probe.js.map +0 -1
  112. package/dist-server/service/reference/reference-progress-channel.js.map +0 -1
  113. package/dist-server/service/reference/reference-progress-subscription.js.map +0 -1
  114. package/dist-server/service/reference/reference-progress.js.map +0 -1
  115. package/dist-server/service/reference/reference-reconciliation-query.js.map +0 -1
  116. package/dist-server/service/reference/reference-reconciliation-writer.js.map +0 -1
  117. package/dist-server/service/reference/reference-reconciliation.js.map +0 -1
  118. package/dist-server/service/reference/reference-registry.js.map +0 -1
  119. package/dist-server/service/reference/reference-resolver.js.map +0 -1
  120. package/dist-server/service/reference/template-registry.js.map +0 -1
  121. package/dist-server/service/reference/twin-reference-reconciliation.js.map +0 -1
  122. package/dist-server/service/reference/twin-reference.js.map +0 -1
  123. package/dist-server/service/twin-attention/index.js.map +0 -1
  124. package/dist-server/service/twin-attention/twin-attention-query.js.map +0 -1
  125. package/dist-server/service/twin-audit/command-audit.js.map +0 -1
  126. package/dist-server/service/twin-audit/index.js.map +0 -1
  127. package/dist-server/service/twin-audit/twin-audit-event.js.map +0 -1
  128. package/dist-server/service/twin-audit/twin-audit-query.js.map +0 -1
  129. package/dist-server/service/twin-backfill/backfill-period-facts.js.map +0 -1
  130. package/dist-server/service/twin-backfill/backfill-shape.js.map +0 -1
  131. package/dist-server/service/twin-backfill/index.js.map +0 -1
  132. package/dist-server/service/twin-backfill/twin-backfill-resolver.js.map +0 -1
  133. package/dist-server/service/twin-control/index.js.map +0 -1
  134. package/dist-server/service/twin-control/twin-control-mutation.js.map +0 -1
  135. package/dist-server/service/twin-event/index.js.map +0 -1
  136. package/dist-server/service/twin-event/journal-count.js.map +0 -1
  137. package/dist-server/service/twin-event/twin-event-keys.js.map +0 -1
  138. package/dist-server/service/twin-event/twin-event-type.js.map +0 -1
  139. package/dist-server/service/twin-event/twin-event.js.map +0 -1
  140. package/dist-server/service/twin-forecast/forecast-metrics.js.map +0 -1
  141. package/dist-server/service/twin-forecast/forecast-tuning.js.map +0 -1
  142. package/dist-server/service/twin-forecast/gap-analytics.js.map +0 -1
  143. package/dist-server/service/twin-forecast/index.js.map +0 -1
  144. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +0 -1
  145. package/dist-server/service/twin-ingest-window/index.js.map +0 -1
  146. package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +0 -1
  147. package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +0 -1
  148. package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +0 -1
  149. package/dist-server/service/twin-instance/index.js.map +0 -1
  150. package/dist-server/service/twin-instance/twin-instance.js.map +0 -1
  151. package/dist-server/service/twin-journal/event-type-split-shape.js.map +0 -1
  152. package/dist-server/service/twin-journal/event-type-split.js.map +0 -1
  153. package/dist-server/service/twin-journal/index.js.map +0 -1
  154. package/dist-server/service/twin-journal/journal-order.js.map +0 -1
  155. package/dist-server/service/twin-journal/twin-journal-query.js.map +0 -1
  156. package/dist-server/service/twin-lifecycle/domain-catalog.js.map +0 -1
  157. package/dist-server/service/twin-lifecycle/index.js.map +0 -1
  158. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +0 -1
  159. package/dist-server/service/twin-metrics/index.js.map +0 -1
  160. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +0 -1
  161. package/dist-server/service/twin-model/axis-journal-evidence.js.map +0 -1
  162. package/dist-server/service/twin-model/choose-recipe.js.map +0 -1
  163. package/dist-server/service/twin-model/epcis-coverage.js.map +0 -1
  164. package/dist-server/service/twin-model/external-resolver.js.map +0 -1
  165. package/dist-server/service/twin-model/iec61850-coverage.js.map +0 -1
  166. package/dist-server/service/twin-model/index.js.map +0 -1
  167. package/dist-server/service/twin-model/isa95-coverage.js.map +0 -1
  168. package/dist-server/service/twin-model/item-ref.js.map +0 -1
  169. package/dist-server/service/twin-model/name-index.js.map +0 -1
  170. package/dist-server/service/twin-model/project-structure.js.map +0 -1
  171. package/dist-server/service/twin-model/standard-coverage.js.map +0 -1
  172. package/dist-server/service/twin-model/status-tally.js.map +0 -1
  173. package/dist-server/service/twin-model/twin-equipment.js.map +0 -1
  174. package/dist-server/service/twin-model/twin-lineage-query.js.map +0 -1
  175. package/dist-server/service/twin-model/twin-location.js.map +0 -1
  176. package/dist-server/service/twin-model/twin-model-item-query.js.map +0 -1
  177. package/dist-server/service/twin-model/twin-model-mutation.js.map +0 -1
  178. package/dist-server/service/twin-model/twin-model-query.js.map +0 -1
  179. package/dist-server/service/twin-model/twin-model-tree-query.js.map +0 -1
  180. package/dist-server/service/twin-model/twin-operation.js.map +0 -1
  181. package/dist-server/service/twin-readiness/index.js.map +0 -1
  182. package/dist-server/service/twin-readiness/twin-readiness-query.js.map +0 -1
  183. package/dist-server/service/twin-space/area-resolver.js.map +0 -1
  184. package/dist-server/service/twin-space/index.js.map +0 -1
  185. package/dist-server/service/twin-space/move-space.js.map +0 -1
  186. package/dist-server/service/twin-space/representation-role.js.map +0 -1
  187. package/dist-server/service/twin-space/space-integrity.js.map +0 -1
  188. package/dist-server/service/twin-space/twin-area.js.map +0 -1
  189. package/dist-server/service/twin-space/twin-space-area.js.map +0 -1
  190. package/dist-server/service/twin-space/twin-space-representation.js.map +0 -1
  191. package/dist-server/service/twin-space/twin-space-resolver.js.map +0 -1
  192. package/dist-server/service/twin-space/twin-space.js.map +0 -1
  193. package/dist-server/service/twin-state/index.js.map +0 -1
  194. package/dist-server/service/twin-state/twin-state-subscription.js.map +0 -1
  195. package/dist-server/service/twin-structure/index.js.map +0 -1
  196. package/dist-server/service/twin-structure/twin-structure.js.map +0 -1
  197. package/dist-server/service/twin-subject/event-subjects.js.map +0 -1
  198. package/dist-server/service/twin-subject/index.js.map +0 -1
  199. package/dist-server/service/twin-subject/item-resolver.js.map +0 -1
  200. package/dist-server/service/twin-subject/subject-query-shape.js.map +0 -1
  201. package/dist-server/service/twin-subject/twin-subject-backfill.js.map +0 -1
  202. package/dist-server/service/twin-subject/twin-subject-event.js.map +0 -1
  203. package/dist-server/service/twin-subject/twin-subject-fast-path.js.map +0 -1
  204. package/dist-server/service/twin-subject/twin-subject-query.js.map +0 -1
  205. package/dist-server/service/twin-subject/twin-subject-writer.js.map +0 -1
  206. package/dist-server/service/twin-target/index.js.map +0 -1
  207. package/dist-server/service/twin-target/twin-target-resolver.js.map +0 -1
  208. package/dist-server/service/twin-target/twin-target.js.map +0 -1
  209. package/dist-shared/axis-read.js.map +0 -1
  210. package/dist-shared/entity-delta.js.map +0 -1
  211. package/dist-shared/kpi-broadcast.js.map +0 -1
  212. package/dist-shared/touched-items.js.map +0 -1
  213. package/dist-shared/twin-level.js.map +0 -1
  214. package/server/engine/attention-digest.ts +0 -102
  215. package/server/engine/canonical-ingest.ts +0 -511
  216. package/server/engine/checkpoint-fold.ts +0 -12
  217. package/server/engine/command-routing.ts +0 -67
  218. package/server/engine/declared-stimulus.ts +0 -66
  219. package/server/engine/energy-topology.ts +0 -189
  220. package/server/engine/event-time.ts +0 -96
  221. package/server/engine/index.ts +0 -51
  222. package/server/engine/ingest-dedupe.ts +0 -24
  223. package/server/engine/ingest-health.ts +0 -24
  224. package/server/engine/integration-coverage.ts +0 -147
  225. package/server/engine/integration-probes.ts +0 -144
  226. package/server/engine/integration-runner.ts +0 -95
  227. package/server/engine/integration-target-profile.ts +0 -103
  228. package/server/engine/kpi-baseline.ts +0 -202
  229. package/server/engine/kpi-fold.ts +0 -1516
  230. package/server/engine/kpi-query.ts +0 -1210
  231. package/server/engine/kpi-target.ts +0 -248
  232. package/server/engine/live-attentions.ts +0 -30
  233. package/server/engine/live-feed-registry.ts +0 -59
  234. package/server/engine/load-meter.ts +0 -393
  235. package/server/engine/local-declarations.ts +0 -779
  236. package/server/engine/log.ts +0 -72
  237. package/server/engine/loop-lag.ts +0 -120
  238. package/server/engine/measured-estimator.ts +0 -91
  239. package/server/engine/measured-yield.ts +0 -89
  240. package/server/engine/model-basis.ts +0 -162
  241. package/server/engine/model-gap.ts +0 -168
  242. package/server/engine/model-refusal.ts +0 -31
  243. package/server/engine/model-vocabulary.ts +0 -82
  244. package/server/engine/oee-accumulator.ts +0 -195
  245. package/server/engine/operation-basis.ts +0 -131
  246. package/server/engine/producer-guard.ts +0 -64
  247. package/server/engine/property-effects.ts +0 -216
  248. package/server/engine/read-time.ts +0 -77
  249. package/server/engine/restart-policy.ts +0 -55
  250. package/server/engine/runtime-key.ts +0 -58
  251. package/server/engine/spec-coverage.ts +0 -105
  252. package/server/engine/stage-path.ts +0 -172
  253. package/server/engine/state-axes.ts +0 -60
  254. package/server/engine/structure-diff.ts +0 -88
  255. package/server/engine/travel-estimator.ts +0 -138
  256. package/server/engine/twin-engine.ts +0 -4979
  257. package/server/engine/twin-state-channel.ts +0 -39
  258. package/server/engine/warm-start.ts +0 -265
  259. package/server/index.ts +0 -90
  260. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +0 -43
  261. package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +0 -54
  262. package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +0 -53
  263. package/server/migrations/1786300000000-IndexEventTypeByTime.ts +0 -48
  264. package/server/migrations/1786400000000-IndexEventCreatedAt.ts +0 -38
  265. package/server/migrations/1786500000000-CreateTwinSubjectEvents.ts +0 -93
  266. package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +0 -66
  267. package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +0 -82
  268. package/server/migrations/1786800000000-CreateTwinReferenceReconciliations.ts +0 -39
  269. package/server/migrations/index.ts +0 -25
  270. package/server/routes.ts +0 -75
  271. package/server/service/actuation/actuation-advisor.ts +0 -131
  272. package/server/service/actuation/actuation-outcome.ts +0 -97
  273. package/server/service/actuation/actuation-rule-resolver.ts +0 -147
  274. package/server/service/actuation/actuation-rule.ts +0 -139
  275. package/server/service/actuation/approval-gateway.ts +0 -44
  276. package/server/service/actuation/catch-up-effects.ts +0 -152
  277. package/server/service/actuation/command-dispatcher.ts +0 -474
  278. package/server/service/actuation/command-store.ts +0 -236
  279. package/server/service/actuation/dispatch-after-approval.ts +0 -71
  280. package/server/service/actuation/effect-match.ts +0 -124
  281. package/server/service/actuation/index.ts +0 -27
  282. package/server/service/actuation/retry-plan.ts +0 -145
  283. package/server/service/actuation/rule-evaluate.ts +0 -352
  284. package/server/service/actuation/rule-loop.ts +0 -160
  285. package/server/service/actuation/rule-runner.ts +0 -216
  286. package/server/service/actuation/rule-wiring.ts +0 -84
  287. package/server/service/actuation/settle-effects.ts +0 -115
  288. package/server/service/actuation/sweep-dispatch.ts +0 -179
  289. package/server/service/actuation/twin-command-resolver.ts +0 -387
  290. package/server/service/actuation/twin-command.ts +0 -232
  291. package/server/service/actuation/twin-now.ts +0 -97
  292. package/server/service/index.ts +0 -100
  293. package/server/service/reference/actuation-routing.ts +0 -192
  294. package/server/service/reference/actuation-target.ts +0 -163
  295. package/server/service/reference/actuation-verification.ts +0 -85
  296. package/server/service/reference/attention-lane.ts +0 -21
  297. package/server/service/reference/connection-portability-resolver.ts +0 -171
  298. package/server/service/reference/connection-portability.ts +0 -329
  299. package/server/service/reference/control-routing.ts +0 -62
  300. package/server/service/reference/discovery-result.ts +0 -95
  301. package/server/service/reference/fill-cadence.ts +0 -29
  302. package/server/service/reference/fill-dedupe.ts +0 -66
  303. package/server/service/reference/fill-loop.ts +0 -153
  304. package/server/service/reference/fill-span.ts +0 -31
  305. package/server/service/reference/hook-contract.ts +0 -364
  306. package/server/service/reference/hook-rejected.ts +0 -53
  307. package/server/service/reference/hook-store.ts +0 -28
  308. package/server/service/reference/index.ts +0 -18
  309. package/server/service/reference/ingest-space.ts +0 -104
  310. package/server/service/reference/knob-defaults.ts +0 -59
  311. package/server/service/reference/live-cadence.ts +0 -129
  312. package/server/service/reference/live-feed-lease.ts +0 -56
  313. package/server/service/reference/live-ingest.ts +0 -94
  314. package/server/service/reference/reference-adapter.ts +0 -985
  315. package/server/service/reference/reference-assessment.ts +0 -250
  316. package/server/service/reference/reference-fill-run.ts +0 -179
  317. package/server/service/reference/reference-fill.ts +0 -223
  318. package/server/service/reference/reference-hook.ts +0 -479
  319. package/server/service/reference/reference-link-groups.ts +0 -21
  320. package/server/service/reference/reference-links.ts +0 -77
  321. package/server/service/reference/reference-live.ts +0 -420
  322. package/server/service/reference/reference-master.ts +0 -999
  323. package/server/service/reference/reference-probe.ts +0 -264
  324. package/server/service/reference/reference-progress-channel.ts +0 -26
  325. package/server/service/reference/reference-progress-subscription.ts +0 -78
  326. package/server/service/reference/reference-progress.ts +0 -95
  327. package/server/service/reference/reference-reconciliation-query.ts +0 -28
  328. package/server/service/reference/reference-reconciliation-writer.ts +0 -38
  329. package/server/service/reference/reference-reconciliation.ts +0 -55
  330. package/server/service/reference/reference-registry.ts +0 -17
  331. package/server/service/reference/reference-resolver.ts +0 -969
  332. package/server/service/reference/template-registry.ts +0 -85
  333. package/server/service/reference/twin-reference-reconciliation.ts +0 -27
  334. package/server/service/reference/twin-reference.ts +0 -190
  335. package/server/service/twin-attention/index.ts +0 -3
  336. package/server/service/twin-attention/twin-attention-query.ts +0 -70
  337. package/server/service/twin-audit/command-audit.ts +0 -114
  338. package/server/service/twin-audit/index.ts +0 -5
  339. package/server/service/twin-audit/twin-audit-event.ts +0 -158
  340. package/server/service/twin-audit/twin-audit-query.ts +0 -72
  341. package/server/service/twin-backfill/backfill-period-facts.ts +0 -168
  342. package/server/service/twin-backfill/backfill-shape.ts +0 -86
  343. package/server/service/twin-backfill/index.ts +0 -3
  344. package/server/service/twin-backfill/twin-backfill-resolver.ts +0 -35
  345. package/server/service/twin-control/index.ts +0 -3
  346. package/server/service/twin-control/twin-control-mutation.ts +0 -150
  347. package/server/service/twin-event/index.ts +0 -3
  348. package/server/service/twin-event/journal-count.ts +0 -53
  349. package/server/service/twin-event/twin-event-keys.ts +0 -215
  350. package/server/service/twin-event/twin-event-type.ts +0 -68
  351. package/server/service/twin-event/twin-event.ts +0 -250
  352. package/server/service/twin-forecast/forecast-metrics.ts +0 -106
  353. package/server/service/twin-forecast/forecast-tuning.ts +0 -40
  354. package/server/service/twin-forecast/gap-analytics.ts +0 -139
  355. package/server/service/twin-forecast/index.ts +0 -3
  356. package/server/service/twin-forecast/twin-forecast-query.ts +0 -486
  357. package/server/service/twin-ingest-window/index.ts +0 -7
  358. package/server/service/twin-ingest-window/twin-ingest-window-query.ts +0 -125
  359. package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +0 -57
  360. package/server/service/twin-ingest-window/twin-ingest-window.ts +0 -113
  361. package/server/service/twin-instance/index.ts +0 -3
  362. package/server/service/twin-instance/twin-instance.ts +0 -199
  363. package/server/service/twin-journal/event-type-split-shape.ts +0 -112
  364. package/server/service/twin-journal/event-type-split.ts +0 -144
  365. package/server/service/twin-journal/index.ts +0 -3
  366. package/server/service/twin-journal/journal-order.ts +0 -20
  367. package/server/service/twin-journal/twin-journal-query.ts +0 -615
  368. package/server/service/twin-lifecycle/domain-catalog.ts +0 -51
  369. package/server/service/twin-lifecycle/index.ts +0 -3
  370. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +0 -285
  371. package/server/service/twin-metrics/index.ts +0 -3
  372. package/server/service/twin-metrics/twin-metrics-query.ts +0 -172
  373. package/server/service/twin-model/axis-journal-evidence.ts +0 -57
  374. package/server/service/twin-model/choose-recipe.ts +0 -31
  375. package/server/service/twin-model/epcis-coverage.ts +0 -251
  376. package/server/service/twin-model/external-resolver.ts +0 -173
  377. package/server/service/twin-model/iec61850-coverage.ts +0 -111
  378. package/server/service/twin-model/index.ts +0 -25
  379. package/server/service/twin-model/isa95-coverage.ts +0 -320
  380. package/server/service/twin-model/item-ref.ts +0 -80
  381. package/server/service/twin-model/name-index.ts +0 -94
  382. package/server/service/twin-model/project-structure.ts +0 -213
  383. package/server/service/twin-model/standard-coverage.ts +0 -35
  384. package/server/service/twin-model/status-tally.ts +0 -37
  385. package/server/service/twin-model/twin-equipment.ts +0 -191
  386. package/server/service/twin-model/twin-lineage-query.ts +0 -327
  387. package/server/service/twin-model/twin-location.ts +0 -147
  388. package/server/service/twin-model/twin-model-item-query.ts +0 -1029
  389. package/server/service/twin-model/twin-model-mutation.ts +0 -503
  390. package/server/service/twin-model/twin-model-query.ts +0 -792
  391. package/server/service/twin-model/twin-model-tree-query.ts +0 -211
  392. package/server/service/twin-model/twin-operation.ts +0 -157
  393. package/server/service/twin-readiness/index.ts +0 -3
  394. package/server/service/twin-readiness/twin-readiness-query.ts +0 -96
  395. package/server/service/twin-space/area-resolver.ts +0 -75
  396. package/server/service/twin-space/index.ts +0 -8
  397. package/server/service/twin-space/move-space.ts +0 -262
  398. package/server/service/twin-space/representation-role.ts +0 -15
  399. package/server/service/twin-space/space-integrity.ts +0 -293
  400. package/server/service/twin-space/twin-area.ts +0 -63
  401. package/server/service/twin-space/twin-space-area.ts +0 -66
  402. package/server/service/twin-space/twin-space-representation.ts +0 -99
  403. package/server/service/twin-space/twin-space-resolver.ts +0 -582
  404. package/server/service/twin-space/twin-space.ts +0 -148
  405. package/server/service/twin-state/index.ts +0 -3
  406. package/server/service/twin-state/twin-state-subscription.ts +0 -62
  407. package/server/service/twin-structure/index.ts +0 -3
  408. package/server/service/twin-structure/twin-structure.ts +0 -96
  409. package/server/service/twin-subject/event-subjects.ts +0 -162
  410. package/server/service/twin-subject/index.ts +0 -10
  411. package/server/service/twin-subject/item-resolver.ts +0 -92
  412. package/server/service/twin-subject/subject-query-shape.ts +0 -84
  413. package/server/service/twin-subject/twin-subject-backfill.ts +0 -196
  414. package/server/service/twin-subject/twin-subject-event.ts +0 -101
  415. package/server/service/twin-subject/twin-subject-fast-path.ts +0 -346
  416. package/server/service/twin-subject/twin-subject-query.ts +0 -210
  417. package/server/service/twin-subject/twin-subject-writer.ts +0 -189
  418. package/server/service/twin-target/index.ts +0 -5
  419. package/server/service/twin-target/twin-target-resolver.ts +0 -142
  420. package/server/service/twin-target/twin-target.ts +0 -97
  421. package/server/types/global.d.ts +0 -22
  422. package/shared/axis-read.ts +0 -28
  423. package/shared/entity-delta.ts +0 -335
  424. package/shared/kpi-broadcast.ts +0 -13
  425. package/shared/touched-items.ts +0 -73
  426. package/shared/twin-level.ts +0 -48
  427. package/test/ack-shape-alignment.test.ts +0 -97
  428. package/test/actuation-advisor.test.ts +0 -55
  429. package/test/actuation-approval-door.test.ts +0 -411
  430. package/test/actuation-dispatch.test.ts +0 -209
  431. package/test/actuation-effect.test.ts +0 -162
  432. package/test/actuation-outcome.test.ts +0 -152
  433. package/test/actuation-rule-runner.test.ts +0 -281
  434. package/test/actuation-rule.test.ts +0 -266
  435. package/test/actuation-seam.test.ts +0 -255
  436. package/test/actuation-settle.test.ts +0 -164
  437. package/test/actuation-target.test.ts +0 -145
  438. package/test/actuation-verification-state.test.ts +0 -139
  439. package/test/adopt-structure-live.test.ts +0 -133
  440. package/test/aggregate-not-findone.test.ts +0 -112
  441. package/test/area-resolver-db.test.ts +0 -110
  442. package/test/attention-digest.test.ts +0 -161
  443. package/test/axis-declaration-passthrough-db.test.ts +0 -152
  444. package/test/axis-journal-evidence.test.ts +0 -71
  445. package/test/axis-read.test.ts +0 -188
  446. package/test/backfill-shape.test.ts +0 -89
  447. package/test/boot-resume.test.ts +0 -287
  448. package/test/broadcast-cost-baseline.test.ts +0 -201
  449. package/test/broadcast-period.test.ts +0 -58
  450. package/test/broadcast-queue-overflow.test.ts +0 -244
  451. package/test/canonical-ingest-vocabularies.test.ts +0 -451
  452. package/test/canonical-quantity-door.test.ts +0 -61
  453. package/test/capability-mapping.test.ts +0 -89
  454. package/test/checkpoint-refuses-empty.test.ts +0 -103
  455. package/test/choose-recipe.test.ts +0 -117
  456. package/test/column-type-portability.test.ts +0 -122
  457. package/test/command-routing.test.ts +0 -61
  458. package/test/command-store-writes-columns.test.ts +0 -126
  459. package/test/connection-portability-doors.test.ts +0 -87
  460. package/test/connector-capability-declaration.test.ts +0 -195
  461. package/test/contract-layer-guard.test.ts +0 -48
  462. package/test/control-capability.test.ts +0 -98
  463. package/test/cursor-stall-not-read-failure.test.ts +0 -126
  464. package/test/declaration-reaches-model.test.ts +0 -226
  465. package/test/declared-location-types.test.ts +0 -89
  466. package/test/declared-stimulus.test.ts +0 -88
  467. package/test/dedupe-transformation.test.ts +0 -112
  468. package/test/discovery-result.test.ts +0 -75
  469. package/test/dispatch-after-approval-source.test.ts +0 -81
  470. package/test/duration-estimators.test.ts +0 -144
  471. package/test/energy-topology.test.ts +0 -113
  472. package/test/entity-delta.test.ts +0 -352
  473. package/test/equipment-identity-reaches.test.ts +0 -57
  474. package/test/event-subjects.test.ts +0 -148
  475. package/test/event-time-column.test.ts +0 -67
  476. package/test/event-type-split.test.ts +0 -178
  477. package/test/external-resolver.test.ts +0 -177
  478. package/test/fact-scope-wiring.test.ts +0 -96
  479. package/test/fill-dedupe.test.ts +0 -59
  480. package/test/fill-loop.test.ts +0 -35
  481. package/test/first-envelope.test.ts +0 -153
  482. package/test/fold-gap-speaks.test.ts +0 -53
  483. package/test/fold-shift-dst.test.ts +0 -110
  484. package/test/forecast-metrics.test.ts +0 -157
  485. package/test/forecast-tuning.test.ts +0 -42
  486. package/test/gap-analytics.test.ts +0 -113
  487. package/test/generated-not-counted.test.ts +0 -99
  488. package/test/guard-roots.ts +0 -76
  489. package/test/home-in-area.test.ts +0 -90
  490. package/test/hook-address.test.ts +0 -28
  491. package/test/hook-rejected-shape.test.ts +0 -86
  492. package/test/hook-response-sum.test.ts +0 -193
  493. package/test/hook-sequence.test.ts +0 -333
  494. package/test/ingest-bench.test.ts +0 -70
  495. package/test/ingest-dedupe.test.ts +0 -56
  496. package/test/ingest-expected-quiet.test.ts +0 -111
  497. package/test/ingest-health-engine.test.ts +0 -248
  498. package/test/ingest-health-wiring.test.ts +0 -120
  499. package/test/ingest-health.test.ts +0 -306
  500. package/test/ingest-history.test.ts +0 -247
  501. package/test/ingest-idempotent.test.ts +0 -211
  502. package/test/ingest-reconcile-four-ways.test.ts +0 -97
  503. package/test/ingest-rules-header.test.ts +0 -100
  504. package/test/ingest-running-guard.test.ts +0 -136
  505. package/test/ingest-space.test.ts +0 -78
  506. package/test/ingest-window-rolls-unobserved.test.ts +0 -72
  507. package/test/ingest-wiring-guard.test.ts +0 -197
  508. package/test/instance-cache-lifecycle.test.ts +0 -110
  509. package/test/intake-mapping-parity.test.ts +0 -175
  510. package/test/integration-probes.test.ts +0 -103
  511. package/test/integration-runner.test.ts +0 -95
  512. package/test/item-ref.test.ts +0 -78
  513. package/test/journal-order-axis.test.ts +0 -80
  514. package/test/journal-read-discipline.test.ts +0 -186
  515. package/test/journal-retention.test.ts +0 -275
  516. package/test/journal-sort-axis.test.ts +0 -142
  517. package/test/journal-write-door.test.ts +0 -110
  518. package/test/journal-write-trend.test.ts +0 -115
  519. package/test/kernel-kind-guard.test.ts +0 -98
  520. package/test/knob-defaults.test.ts +0 -72
  521. package/test/kpi-baseline-db.test.ts +0 -216
  522. package/test/kpi-baseline.test.ts +0 -196
  523. package/test/kpi-fold.test.ts +0 -1456
  524. package/test/kpi-query-bench.test.ts +0 -130
  525. package/test/lens-own-places.test.ts +0 -50
  526. package/test/lineage-survives-restart.test.ts +0 -234
  527. package/test/live-cadence.test.ts +0 -170
  528. package/test/live-cursor-wiring.test.ts +0 -87
  529. package/test/live-feed-lease.test.ts +0 -63
  530. package/test/live-feed-registry.test.ts +0 -75
  531. package/test/live-kernel-facts.test.ts +0 -161
  532. package/test/live-mirror-parity.test.ts +0 -286
  533. package/test/load-meter.test.ts +0 -328
  534. package/test/local-declarations.test.ts +0 -662
  535. package/test/log-stamp.test.ts +0 -59
  536. package/test/loop-lag.test.ts +0 -82
  537. package/test/master-to-twin.test.ts +0 -279
  538. package/test/measured-yield.test.ts +0 -90
  539. package/test/merge-streams.test.ts +0 -70
  540. package/test/mirror-resumes-from-checkpoint.test.ts +0 -192
  541. package/test/model-basis.test.ts +0 -141
  542. package/test/model-gap.test.ts +0 -153
  543. package/test/model-refusal.test.ts +0 -75
  544. package/test/model-vocabulary.test.ts +0 -114
  545. package/test/move-space.test.ts +0 -149
  546. package/test/mutation-gate.test.ts +0 -122
  547. package/test/oee-accumulator.test.ts +0 -204
  548. package/test/oee-site-calendar.test.ts +0 -146
  549. package/test/open-doors.test.ts +0 -197
  550. package/test/operation-basis.test.ts +0 -127
  551. package/test/operational-vocabulary.test.ts +0 -108
  552. package/test/operations-capability-db.test.ts +0 -165
  553. package/test/order-and-transaction-split.test.ts +0 -107
  554. package/test/order-fold-host.test.ts +0 -112
  555. package/test/producer-guard.test.ts +0 -66
  556. package/test/project-structure-db.test.ts +0 -226
  557. package/test/projection-reaches-screen.test.ts +0 -277
  558. package/test/projection-reads-declared.test.ts +0 -109
  559. package/test/property-effects.test.ts +0 -128
  560. package/test/provenance-promotion.test.ts +0 -99
  561. package/test/read-failure-ledger.test.ts +0 -106
  562. package/test/read-failure-visible.test.ts +0 -145
  563. package/test/read-time.test.ts +0 -118
  564. package/test/reference-fill.test.ts +0 -235
  565. package/test/reference-grounding.test.ts +0 -70
  566. package/test/reference-hook.test.ts +0 -177
  567. package/test/reference-links.test.ts +0 -56
  568. package/test/reference-reconciliation.test.ts +0 -39
  569. package/test/registry-key-guard.test.ts +0 -80
  570. package/test/rejection-carries-event-id.test.ts +0 -101
  571. package/test/rename-twin.test.ts +0 -89
  572. package/test/resolve-ts-siblings.mjs +0 -52
  573. package/test/restart-policy.test.ts +0 -111
  574. package/test/resync-origin-site.test.ts +0 -83
  575. package/test/retry-plan.test.ts +0 -139
  576. package/test/revision-axis.test.ts +0 -110
  577. package/test/runtime-key.test.ts +0 -66
  578. package/test/save-intake-collision.test.ts +0 -91
  579. package/test/scale-twin-bench.test.ts +0 -103
  580. package/test/secrets-at-rest.test.ts +0 -135
  581. package/test/snapshot-freshness.test.ts +0 -60
  582. package/test/source-outcome-audit.test.ts +0 -104
  583. package/test/space-integrity.test.ts +0 -223
  584. package/test/space-representation.test.ts +0 -66
  585. package/test/space-scope-includes-stopped.test.ts +0 -55
  586. package/test/spec-coverage.test.ts +0 -113
  587. package/test/stage-path.test.ts +0 -95
  588. package/test/standard-coverage.test.ts +0 -148
  589. package/test/state-axes.test.ts +0 -74
  590. package/test/status-tally.test.ts +0 -55
  591. package/test/streamline-e2e.test.ts +0 -76
  592. package/test/structure-revision-db.test.ts +0 -315
  593. package/test/subject-fast-path.test.ts +0 -148
  594. package/test/subject-read-model.test.ts +0 -175
  595. package/test/sweep-dispatch.test.ts +0 -191
  596. package/test/tenant-registry-db.test.ts +0 -149
  597. package/test/time-range.test.ts +0 -152
  598. package/test/touched-items.test.ts +0 -61
  599. package/test/twin-audit.test.ts +0 -83
  600. package/test/twin-event-keys.test.ts +0 -193
  601. package/test/twin-model-item-db.test.ts +0 -319
  602. package/test/twin-model-parent-relation-db.test.ts +0 -125
  603. package/test/twin-model-tree-db.test.ts +0 -209
  604. package/test/twin-origin-resync.test.ts +0 -133
  605. package/test/twin-state-channel.test.ts +0 -111
  606. package/test/vocabulary-guard.test.ts +0 -43
  607. package/test/warm-start-seam.test.ts +0 -162
  608. package/test/warm-start.test.ts +0 -297
  609. package/test/withheld-door.test.ts +0 -95
  610. package/test/yield-loop.test.ts +0 -199
  611. package/tsconfig.json +0 -15
  612. package/tsconfig.shared.json +0 -23
  613. package/tsconfig.shared.tsbuildinfo +0 -1
  614. package/tsconfig.tsbuildinfo +0 -1
@@ -1,201 +0,0 @@
1
- /*
2
- * **브로드캐스팅 한 번의 비용** — 200ms 마다 무엇을 만드는지 값으로 남긴다 (2026-08-21).
3
- *
4
- * ── 왜 재는가 ───────────────────────────────────────────────────────────────
5
- * `publishEntityData` 는 브로드캐스팅 주기마다 ① 상태를 통째로 투영하고(`getSnapshot`) ② 엔티티마다 payload 를
6
- * 만들고(`buildEntityDeltas`) ③ 그 payload 를 문자열로 만들어 이전 것과 비교한다. ③ 의 비교가 없던
7
- * 시절에는 바뀌지 않은 것까지 전송했고, 그 낭비는 2026-08-14 에 없앴다 — 그런데 없앤 것은 **전송**이고
8
- * ①②③ 의 **계산은 그대로** 남았다. 물품이 수천 개인 트윈에서는 하나만 움직여도 수천 개를 만들어
9
- * 문자열로 바꾼 뒤 「같다」를 확인하고 버린다.
10
- *
11
- * 고치기 전에 세 축의 몫을 값으로 남긴다. 짐작으로 고치면 무엇이 나아졌는지 말할 수 없다.
12
- *
13
- * ── 고친 뒤 (2026-08-21) ────────────────────────────────────────────────────
14
- * 이제 브로드캐스팅은 **건드린 물품만** 만든다(`buildEntityDeltas` 의 `scope.items`). 그래서 이 시험은 두
15
- * 창을 나란히 잰다: 범위를 모를 때(전부) 와 물품 하나를 건드렸을 때(좁힘).
16
- *
17
- * ── 게이트는 시간이 아니다 ──────────────────────────────────────────────────
18
- * 기계마다·스위트 병렬 실행마다 시간은 달라진다(같은 코드에서 3.2배와 14.8배가 나온 적이 있다). 그래서
19
- * 단정은 **시간과 무관한 사실**로 한다: 좁힌 창이 만든 물품 payload 가 말한 것 하나뿐인가. 시간은
20
- * 기준선으로 출력만 하고, 여러 번 재 그중 **가장 짧은 값**을 적는다(GC·JIT 잡음을 덜 타는 값).
21
- */
22
- import { test } from 'node:test'
23
- import assert from 'node:assert/strict'
24
-
25
- import { MesKernel } from '@operato/twin-kernel'
26
- import { type CanonicalEnvelope, type ProductionSpec, type ScenarioDef, type TwinModelDef } from '@operato/ops-contract'
27
-
28
- import { buildEntityDeltas } from '../shared/entity-delta.ts'
29
-
30
- const COMMISSIONING = 'urn:epcglobal:cbv:bizstep:commissioning'
31
- /* GS1 이 예제로 지정한 `952` 대역 — 실 배정 대역을 픽스처에 두지 않는다(CBV 2.0). */
32
- const PREFIX = '9521321'
33
- const RAW_GTIN = `urn:epc:idpat:sgtin:${PREFIX}.0001.*`
34
-
35
- const DEFINITION: any = {
36
- materials: [
37
- { key: 'raw', label: '원자재', locationType: 'raw-store' },
38
- { key: 'product', label: '완제품', locationType: 'fg-store' }
39
- ],
40
- locationTypes: [
41
- { key: 'raw-store', label: '자재 보관' },
42
- { key: 'cut-st', label: '절단' },
43
- { key: 'fg-store', label: '완제품 보관' }
44
- ],
45
- resourceTypes: [{ key: 'cutter', label: '절단기' }],
46
- operations: [{ key: 'cut', label: '절단', intent: 'process', locationType: 'cut-st', resourceType: 'cutter', bizStep: COMMISSIONING }],
47
- routes: [{ key: 'line', label: '라인', steps: ['cut'] }],
48
- recipes: [{ key: 'prod', label: '완제품', inputs: [{ material: 'raw', qty: 1 }], outputs: [{ material: 'product', qty: 1 }], route: 'line' }]
49
- }
50
- const SPEC: ProductionSpec = {
51
- definition: DEFINITION,
52
- binding: { raw: '0001', product: '0002' },
53
- identity: { documentTypes: { workorder: '403' }, namespaces: [`urn:epc:idpat:sgtin:${PREFIX}.`] },
54
- companyPrefix: PREFIX
55
- }
56
-
57
- function board(): TwinModelDef {
58
- return {
59
- locations: [
60
- { id: 'raw-store', type: 'raw-store', capacity: 1_000_000 },
61
- { id: 'cut-st', type: 'cut-st', capacity: 1_000_000 },
62
- { id: 'fg-store', type: 'fg-store', capacity: 1_000_000 }
63
- ],
64
- equipment: Array.from({ length: 8 }, (_, i) => ({ id: `cutter-${i}`, kind: 'cutter', homeLocation: 'cut-st' }))
65
- } as TwinModelDef
66
- }
67
-
68
- function scenario(ordersPerHour: number): ScenarioDef {
69
- return {
70
- seed: 9,
71
- generators: [
72
- {
73
- kind: 'inbound-arrival',
74
- stimulus: 'arrival',
75
- rate: { distribution: 'constant', meanPerHour: ordersPerHour * 4 },
76
- content: { skuMix: [{ gtin: RAW_GTIN, weight: 1 }], qtyPerLine: { min: 1, max: 1 } }
77
- },
78
- {
79
- kind: 'workorder',
80
- stimulus: 'order',
81
- rate: { distribution: 'constant', meanPerHour: ordersPerHour },
82
- content: { skuMix: [{ gtin: 'wo', weight: 1 }], qtyPerLine: { min: 1, max: 1 } }
83
- }
84
- ]
85
- } as ScenarioDef
86
- }
87
-
88
- interface Row {
89
- items: number
90
- entities: number
91
- payloads: number
92
- /** 물품 하나만 건드렸다고 말했을 때 만드는 payload 수 — 좁히기가 듣는지. */
93
- scopedPayloads: number
94
- snapshotMs: number
95
- /** 매핑 + 시그니처(다섯 번 중 가장 짧은 값). */
96
- buildMs: number
97
- broadcastMs: number
98
- /** 좁힌 창의 매핑 + 시그니처 시간 — 투영은 그대로 남는다(커널 몫). */
99
- scopedMs: number
100
- /** 만든 payload 목록 — 단정이 「무엇을 만들었나」를 직접 본다(수만으로는 축을 구별하지 못한다). */
101
- fullDeltas: any[]
102
- scopedDeltas: any[]
103
- }
104
-
105
- /** 한 규모에서 **브로드캐스팅 한 번**의 세 축을 잰다. 상태는 미리 쌓아 두고, 재는 것은 브로드캐스팅뿐이다. */
106
- function measure(ticks: number, ordersPerHour: number): Row {
107
- const k: any = new MesKernel('bench', undefined, SPEC)
108
- k.onEvent((_e: CanonicalEnvelope) => {})
109
- k.loadTwinModel(board())
110
- k.scenario.load(scenario(ordersPerHour))
111
- k.scenario.start()
112
- for (let i = 0; i < ticks; i++) k.tick(1000)
113
-
114
- /* ① 상태 투영 — 자리·물품·자원·작업·오더를 새 객체로 만든다. */
115
- const t0 = performance.now()
116
- const st = k.getSnapshot()
117
- const t1 = performance.now()
118
- /*
119
- * ②③ payload 만들기 + 시그니처 — **다섯 번 재 가장 짧은 값을 쓴다.** 한 번만 재면 그 순간의 GC 가
120
- * 값에 들어가, 좁힌 창이 전부 만든 창보다 오래 걸린 것처럼 보이는 일이 실제로 있었다.
121
- */
122
- const pass = (scope?: { items: ReadonlySet<string> }) => {
123
- let best = Infinity
124
- let built: any[] = []
125
- let chars = 0
126
- for (let i = 0; i < 5; i++) {
127
- const a = performance.now()
128
- built = buildEntityDeltas(st, 'bench', scope)
129
- chars = 0
130
- for (const d of built) chars += JSON.stringify(d.data).length
131
- best = Math.min(best, performance.now() - a)
132
- }
133
- return { built, chars, ms: Math.round(best * 10) / 10 }
134
- }
135
-
136
- const fullPass = pass()
137
- const deltas = fullPass.built
138
- const chars = fullPass.chars
139
-
140
- const entities =
141
- st.locations.length + st.items.length + st.equipment.length + (st.assets?.length ?? 0) + (st.persons?.length ?? 0) + st.tasks.length + st.orders.length
142
-
143
- /* ④ 좁힌 창 — 물품 하나만 건드렸다고 말한 경우. 같은 상태로 재야 비교가 성립한다. */
144
- const one = new Set<string>([st.items[0]?.epc].filter(Boolean) as string[])
145
- const scopedPass = pass({ items: one })
146
- const scoped = scopedPass.built
147
-
148
- assert.ok(chars > 0 && scopedPass.chars > 0, '문자열을 만들지 않았다면 측정이 성립하지 않는다')
149
- const ms = (a: number, b: number) => Math.round((b - a) * 10) / 10
150
- return {
151
- items: st.items.length,
152
- entities,
153
- payloads: deltas.length,
154
- scopedPayloads: scoped.length,
155
- snapshotMs: ms(t0, t1),
156
- buildMs: fullPass.ms,
157
- broadcastMs: Math.round((ms(t0, t1) + fullPass.ms) * 10) / 10,
158
- scopedMs: scopedPass.ms,
159
- fullDeltas: deltas,
160
- scopedDeltas: scoped
161
- }
162
- }
163
-
164
- test('브로드캐스팅 한 번의 비용 — 좁힌 창은 건드린 물품만 만든다', () => {
165
- /* 예열은 가장 큰 규모로 한 번 버린다 — 작은 규모부터 재면 뒤 측정이 앞의 JIT 이득을 본다. */
166
- measure(600, 3600)
167
-
168
- const rows = [measure(600, 60), measure(600, 480), measure(600, 3600)]
169
-
170
- console.log('[브로드캐스팅 한 번의 비용 · MES 선언본]')
171
- for (const r of rows) {
172
- console.log(
173
- ` 물품 ${String(r.items).padStart(5)} · 엔티티 ${String(r.entities).padStart(5)} — payload ${String(r.payloads).padStart(5)}개 · ` +
174
- `투영 ${String(r.snapshotMs).padStart(6)}ms · 만들기 ${String(r.buildMs).padStart(6)}ms · 합 ${r.broadcastMs}ms` +
175
- ` ▸ 좁힌 창: payload ${String(r.scopedPayloads).padStart(4)}개 · ${r.scopedMs}ms`
176
- )
177
- }
178
-
179
- /* 측정이 성립했는지 — 규모가 실제로 커져야 비교에 뜻이 있다. */
180
- assert.ok(rows[0].items > 0, '물품이 쌓여야 한다')
181
- assert.ok(rows[rows.length - 1].items > rows[0].items * 3, '규모가 실제로 커져야 한다')
182
-
183
- /*
184
- * ── 고친 뒤의 단정 (2026-08-21) ──────────────────────────────────────────
185
- * 전부 만드는 창은 여전히 엔티티 수에 비례한다 — 그 창은 그물이고 주기마다 한 번뿐이다(§그물).
186
- *
187
- * **좁힌 창이 만드는 물품 payload 는 말한 것 하나뿐이다.** 이것이 시간과 무관한 단정이다. 기울기로
188
- * 재지 않는 이유는 이 픽스처가 물품과 함께 오더·작업도 늘리기 때문이다 — 그 축은 좁히지 않으므로
189
- * (자리 점유·집약과 같은 이유) 기울기에는 남의 몫이 섞인다.
190
- *
191
- * 실 현장의 비율은 물품 쪽이 훨씬 무겁다(hatio-us: 물품 2,805 · 오더 192 · 작업 221). 이 픽스처는
192
- * 오더를 과하게 실은 쪽이므로, 여기서 보이는 절감은 **실 현장보다 작다.**
193
- */
194
- const last = rows[rows.length - 1]
195
- const itemPayloads = (ds: any[]) => ds.filter(d => d?.data?.entity === 'item').length
196
- assert.equal(itemPayloads(last.fullDeltas), last.items, '전부 만드는 창은 물품 전부를 만든다')
197
- assert.equal(itemPayloads(last.scopedDeltas), 1, '좁힌 창은 건드린 물품 하나만 만들어야 한다')
198
- /* 집약은 좁히지 않는다 — 목록 전체가 한 payload 라서 한 물품이 바뀌면 통째로 새로 만든다. */
199
- const aggregates = (ds: any[]) => ds.filter(d => String(d.tag).startsWith('__')).length
200
- assert.equal(aggregates(last.scopedDeltas), aggregates(last.fullDeltas), '집약 뷰는 좁힌 창에서도 그대로 나간다')
201
- })
@@ -1,58 +0,0 @@
1
- /*
2
- * 브로드캐스팅 주기는 **재 본 비용에 맞춘다** (2026-08-21).
3
- *
4
- * 한 번의 브로드캐스팅은 상태 크기에 비례한다(실측: 물품 2,400 개 트윈 하나가 4.5ms). 트윈이 스무 개면
5
- * 200ms 주기에서 90ms 가 브로드캐스팅이고, 그 시간에는 HTTP 도 구독도 서지 못한다. 그래서 브로드캐스팅이 주기의
6
- * 일정 몫을 넘게 쓰면 주기를 늘리고, 여유가 생기면 되돌린다.
7
- *
8
- * 지키는 것:
9
- * ① 무거우면 늘린다 — 상한까지만.
10
- * ② 가벼워지면 되돌린다 — 원래 주기 아래로는 내려가지 않는다.
11
- * ③ 경계에서 늘리고 줄이기를 반복하지 않는다(문턱이 둘이다).
12
- * ④ **늘렸다는 사실을 센다** — 알리지 않고 늦추면 사람은 화면이 낡은 이유를 알 수 없다.
13
- */
14
- import { test, beforeEach } from 'node:test'
15
- import assert from 'node:assert/strict'
16
- import { createRequire } from 'node:module'
17
-
18
- const req = createRequire(import.meta.url)
19
- const { TwinEngine } = req('../dist-server/engine/twin-engine.js')
20
-
21
- /** 주기 조정만 부른다 — 실제 브로드캐스팅(pubsub·DB)은 이 판정과 무관하다. */
22
- const adjust = (flushMs: number) => (TwinEngine as any).adjustBroadcastPeriod(flushMs)
23
-
24
- beforeEach(() => {
25
- TwinEngine.broadcastPeriodMs = TwinEngine.BROADCAST_COALESCE_MS
26
- TwinEngine.broadcastBackoffs = 0
27
- })
28
-
29
- test('브로드캐스팅이 주기의 몫을 넘게 쓰면 주기를 늘린다 — 상한까지만', () => {
30
- const base = TwinEngine.BROADCAST_COALESCE_MS
31
- adjust(base) // 주기를 통째로 쓴 셈
32
- assert.equal(TwinEngine.broadcastPeriodMs, base * 2)
33
-
34
- for (let i = 0; i < 10; i++) adjust(TwinEngine.broadcastPeriodMs)
35
- assert.equal(TwinEngine.broadcastPeriodMs, TwinEngine.BROADCAST_MAX_COALESCE_MS, '상한 위로는 올라가지 않는다')
36
- })
37
-
38
- test('늘렸다는 사실을 센다 — 알리지 않고 늦추지 않는다', () => {
39
- adjust(TwinEngine.BROADCAST_COALESCE_MS)
40
- assert.equal(TwinEngine.broadcastBackoffs, 1)
41
- })
42
-
43
- test('가벼워지면 되돌린다 — 원래 주기 아래로는 내려가지 않는다', () => {
44
- adjust(TwinEngine.BROADCAST_COALESCE_MS) // 200 → 400
45
- assert.ok(TwinEngine.broadcastPeriodMs > TwinEngine.BROADCAST_COALESCE_MS)
46
-
47
- for (let i = 0; i < 10; i++) adjust(0.5)
48
- assert.equal(TwinEngine.broadcastPeriodMs, TwinEngine.BROADCAST_COALESCE_MS)
49
- })
50
-
51
- test('경계에서 늘리고 줄이기를 반복하지 않는다 — 문턱이 둘이다', () => {
52
- const base = TwinEngine.BROADCAST_COALESCE_MS
53
- /* 늘리는 문턱(몫)과 되돌리는 문턱(몫의 절반) 사이의 값 — 어느 쪽도 아니어야 한다. */
54
- const between = base * TwinEngine.BROADCAST_LOAD_RATIO * 0.75
55
- for (let i = 0; i < 5; i++) adjust(between)
56
- assert.equal(TwinEngine.broadcastPeriodMs, base, '문턱 사이의 값은 주기를 바꾸지 않는다')
57
- assert.equal(TwinEngine.broadcastBackoffs, 0)
58
- })
@@ -1,244 +0,0 @@
1
- /*
2
- * ★ 브로드캐스팅이 서버를 죽였다 — 그 기전을 실제 라이브러리로 재고, 우리 코드가 그것을 넘기지 않는지 본다.
3
- *
4
- * ── 무엇이 났나 (2026-08-27 10:24 · 실측) ───────────────────────────────────
5
- * `RepeaterOverflowError: No more than 1024 pending calls to push are allowed on a single repeater.`
6
- * 가 브로드캐스팅 타이머 안에서 나서 프로세스가 내려갔다. 같은 예외로 2026-08-14 에도 죽었다.
7
- *
8
- * ── 기전 ────────────────────────────────────────────────────────────────────
9
- * 구독의 대기열에는 버퍼가 없다. `pubsub.subscribe` 가 `new Repeater(fn)` 을 버퍼 인자 없이 만든다.
10
- * 그래서 발행하는 순간에 「다음 값을 달라」는 요청이 이미 걸려 있어야 바로 전달되고, 아니면 대기열에
11
- * 쌓인다. 상한은 1024 이고 넘으면 예외가 난다.
12
- *
13
- * 값을 꺼내는 쪽은 비동기다. 그래서 **동기 반복문이 도는 중에는 한 건도 꺼내지 못한다.** 반복문으로
14
- * N 건을 발행하면 첫 건만 전달되고 나머지 N−1 건이 전부 쌓인다. 브라우저가 아무리 빨라도 넘는다 —
15
- * 속도 문제가 아니라 꺼낼 틈을 주지 않는 것이 원인이다.
16
- *
17
- * ── 왜 try/catch 로 못 막나 ─────────────────────────────────────────────────
18
- * 2026-08-14 에 `publishGuarded` 가 `pubsub.publish` 를 try/catch 로 감쌌고, 커밋 제목이 「방송이
19
- * 호스트를 죽이지 못하게」였다. 그것이 무력하다. 예외는 `EventTarget` 이 부른 리스너 안에서 나고,
20
- * 런타임은 리스너 예외를 호출자에게 주지 않고 uncaughtException 으로 보낸다. 이 테스트가 그것을
21
- * 값으로 못 박는다 — 그때 검증하지 않아서 3주 동안 막힌 줄 알고 있었다.
22
- *
23
- * ── 왜 오늘 났나 ────────────────────────────────────────────────────────────
24
- * 오늘 아침 chef 커넥터가 묻는 간격을 5초에서 30초로 올렸다(상대 서버 부담을 줄이려고). 요청 횟수는
25
- * 줄지만 한 번에 오는 양이 6배가 된다. 초당 130건이 들어오는 원본에서 한 묶음이 3,900건이 되고, 그
26
- * 묶음이 한 창에 몰려 반복문 하나가 1024 를 넘겼다.
27
- */
28
- import { test } from 'node:test'
29
- import assert from 'node:assert/strict'
30
- import { readFileSync } from 'node:fs'
31
- import { join } from 'node:path'
32
- import { spawnSync } from 'node:child_process'
33
-
34
- const ENGINE = join(import.meta.dirname, '..', 'server', 'engine', 'twin-engine.ts')
35
- const src = readFileSync(ENGINE, 'utf8')
36
-
37
- /** 저장소 뿌리 — 자식이 `graphql-yoga` 를 찾을 수 있어야 한다. */
38
- const REPO = join(import.meta.dirname, '..', '..', '..')
39
-
40
- /**
41
- * 발행을 **자식 프로세스**에서 한다 — 「프로세스가 죽는다」를 종료 코드로 확인하려면 그래야 한다.
42
- *
43
- * 같은 프로세스에서 재면 예외가 테스트 러너에 잡혀 이 테스트의 실패로 보고된다. 그것도 사실이지만
44
- * 확인하려는 것은 「감싸도 못 막고 프로세스가 내려간다」이므로 자식의 종료 코드로 판정한다.
45
- */
46
- function runChild(
47
- count: number,
48
- opts: { consume: boolean; chunk?: number; subscribers?: number; watchAll?: boolean }
49
- ) {
50
- const subscribers = opts.subscribers ?? 1
51
- const code = `
52
- import { createPubSub, pipe, filter } from 'graphql-yoga'
53
- const pubsub = createPubSub()
54
- const watchAll = ${!!opts.watchAll}
55
- let pulled = 0, ordered = true, lastSeen = -1
56
- if (${opts.consume}) {
57
- for (let s = 0; s < ${subscribers}; s++) {
58
- const stream = pipe(pubsub.subscribe('data'), filter(p => watchAll || p.tag === 'watched'))
59
- ;(async () => {
60
- for await (const p of stream) {
61
- /* 순서 확인은 첫 구독만 한다 — 여럿이 세면 서로의 값이 섞인다. */
62
- if (s === 0) {
63
- pulled++
64
- if (watchAll) {
65
- if (p.i !== lastSeen + 1) ordered = false
66
- lastSeen = p.i
67
- }
68
- }
69
- }
70
- })().catch(() => {})
71
- }
72
- /* 소비자들이 첫 요청을 걸 틈을 준다 — 이것이 없으면 리스너조차 등록되지 않는다(지연 구독). */
73
- await new Promise(r => setImmediate(r))
74
- }
75
- let thrownToCaller = 0, sinceYield = 0
76
- for (let i = 0; i < ${count}; i++) {
77
- try { pubsub.publish('data', { tag: (watchAll || i === 0) ? 'watched' : 'other-' + i, i }) }
78
- catch { thrownToCaller++ }
79
- const chunk = ${opts.chunk ?? 0}
80
- if (chunk && ++sinceYield >= chunk) { sinceYield = 0; await new Promise(r => setImmediate(r)) }
81
- }
82
- /* 남은 것을 다 꺼낼 틈을 준다 — 여기서 짧게 끊으면 「빠졌다」로 오판한다. */
83
- for (let k = 0; k < 50; k++) await new Promise(r => setImmediate(r))
84
- await new Promise(r => setTimeout(r, 100))
85
- console.log(JSON.stringify({ thrownToCaller, pulled, ordered }))
86
- `
87
- const r = spawnSync(process.execPath, ['--input-type=module', '-e', code], {
88
- cwd: REPO,
89
- encoding: 'utf8'
90
- })
91
- const line = (r.stdout ?? '').trim().split('\n').filter(Boolean).pop()
92
- return {
93
- status: r.status,
94
- overflowed: /No more than 1024 pending calls to push/.test(r.stderr ?? ''),
95
- result: line ? (JSON.parse(line) as { thrownToCaller: number; pulled: number; ordered: boolean }) : null
96
- }
97
- }
98
-
99
- test('★ 구독자가 있고 한 차례에 1024건을 넘게 발행하면 프로세스가 죽는다 — 브라우저 속도와 무관하다', () => {
100
- const r = runChild(2000, { consume: true })
101
- assert.ok(r.overflowed, '대기열이 넘쳐 예외가 나야 한다(이것이 서버를 죽인 그 예외다)')
102
- assert.notEqual(r.status, 0, '그 예외로 프로세스가 내려간다')
103
- })
104
-
105
- test('★ 그 예외는 publish() 를 감싼 try/catch 로 잡히지 않는다 — 08-14 의 가드가 무력한 이유', () => {
106
- const r = runChild(2000, { consume: true })
107
- assert.equal(r.result, null, '완주하지 못한다 — 결과를 낼 자리에 닿지 못한다')
108
- assert.ok(r.overflowed, '예외는 감싼 곳이 아니라 uncaughtException 으로 간다')
109
- })
110
-
111
- test('★ 상한마다 루프를 비워 주면 넘지 않는다 — 이것이 고친 방법이다', () => {
112
- const r = runChild(5000, { consume: true, chunk: 200 })
113
- assert.equal(r.status, 0, '청크마다 양보하면 프로세스가 살아 있다')
114
- assert.equal(r.overflowed, false, '대기열이 넘지 않는다')
115
- assert.ok((r.result?.pulled ?? 0) > 0, '소비자가 실제로 꺼내 간다')
116
- })
117
-
118
- test('★ 동기 반복문 중에는 소비자가 꺼내지 못한다 — 속도가 아니라 틈이 없는 것이 원인이다', () => {
119
- /* 1024 아래로 두어 죽지 않게 하고, 그 사이에 몇 건이 꺼내졌는지 본다. */
120
- const r = runChild(1000, { consume: true })
121
- assert.equal(r.status, 0)
122
- assert.ok((r.result?.pulled ?? -1) <= 2, `꺼낸 것이 ${r.result?.pulled}건뿐이다 — 1000건을 발행하는 동안`)
123
- })
124
-
125
- test('구독자가 없으면 아무것도 쌓이지 않는다 — 리스너가 없다', () => {
126
- const r = runChild(2000, { consume: false })
127
- assert.equal(r.status, 0, '들을 사람이 없으면 대기열도 없다')
128
- assert.equal(r.overflowed, false)
129
- })
130
-
131
-
132
-
133
-
134
-
135
-
136
- test('★ 엔진의 발행 반복문이 상한마다 루프를 비워 준다', () => {
137
- const at = src.indexOf('static async publishEntityData')
138
- assert.ok(at > 0, 'publishEntityData 가 async 여야 한다 — 양보할 수 없으면 상한을 지킬 수 없다')
139
- const body = src.slice(at, at + 6000)
140
- assert.match(body, /PUBLISH_CHUNK/, '한 차례의 상한에 이름이 있어야 한다')
141
- assert.match(
142
- body,
143
- /sinceYield \+= 0|\+\+sinceYield >= this\.PUBLISH_CHUNK[\s\S]{0,120}?setImmediate/,
144
- '상한에 닿으면 루프를 비워 줘야 한다'
145
- )
146
- /* 상한은 1024 보다 넉넉히 작아야 한다 — 한 청크를 다 꺼내지 못해도 여유가 남게. */
147
- const cap = Number(/static PUBLISH_CHUNK = ([0-9_]+)/.exec(src)?.[1]?.replace(/_/g, ''))
148
- assert.ok(cap > 0 && cap <= 512, `상한이 ${cap} 이다 — 1024 의 절반 아래여야 한다`)
149
- })
150
-
151
- test('★ 발행을 중간에 그만두지 않는다 — 그만두면 그 태그가 낡은 값으로 남는다', () => {
152
- const at = src.indexOf('static async publishEntityData')
153
- const body = src.slice(at, at + 6000)
154
- /* 상한에 닿았을 때 `break`·`return` 으로 빠지면 남은 태그는 이 창에서 발행되지 않는다. */
155
- assert.doesNotMatch(body, />= this\.PUBLISH_CHUNK[\s\S]{0,80}?(break|return)/, '상한에서 빠져나가지 않는다')
156
- })
157
-
158
- test('★ 한 창이 겹쳐 돌지 않는다 — 같은 태그가 두 순서로 나가지 않게', () => {
159
- const at = src.indexOf('static flushLiveBroadcasts')
160
- assert.ok(at > 0, 'flushLiveBroadcasts 가 있어야 한다')
161
- const body = src.slice(at, at + 1200)
162
- assert.match(body, /if \(this\.flushInFlight\)/, '앞 창이 돌고 있으면 들어가지 않는다')
163
- assert.match(body, /flushOverruns\+\+/, '겹친 횟수를 센다 — 알리지 않고 넘기지 않는다')
164
- /* 발행을 기다려야 청크 사이의 양보가 뜻을 갖는다. */
165
- assert.match(src, /await this\.publishEntityData\(inst\)/, '창이 발행을 기다린다')
166
- })
167
-
168
- test('★ 발행 건수를 남긴다 — 다음에 이 판단을 추측으로 하지 않게', () => {
169
- const at = src.indexOf('static async publishEntityData')
170
- const body = src.slice(at, at + 6000)
171
- assert.match(body, /publishedTotal/, '누적 발행 건수를 든다')
172
- assert.match(body, /건 발행/, '상한을 넘긴 창은 건수를 로그에 남긴다')
173
- })
174
-
175
- /*
176
- * ── 여기서부터: 상한 근처와 그 너머를 더 넓게 잰다 ────────────────────────────
177
- *
178
- * 위 테스트가 「1024 를 넘으면 죽고, 200마다 양보하면 산다」를 못 박았다. 그런데 실제 창은 18,426건이고
179
- * 구독은 하나가 아니다(`board-provider` 가 컴포넌트마다 하나씩 연다). 그 조건에서도 서는지 잰다.
180
- */
181
-
182
- test('★ 실제 규모에서 선다 — 한 창 18,426건 · 청크 200', () => {
183
- /* 2026-08-27 11:11 실측값 그대로. 이 수가 상한의 18배라서 청크 없이는 반드시 죽는다. */
184
- const r = runChild(18426, { consume: true, chunk: 200 })
185
- assert.equal(r.status, 0, '실측 규모에서 프로세스가 살아 있어야 한다')
186
- assert.equal(r.overflowed, false)
187
- })
188
-
189
- test('★ 구독이 여러 개여도 선다 — 화면은 컴포넌트마다 구독을 하나씩 연다', () => {
190
- /*
191
- * 지금 구조에서는 발행 하나가 **구독마다** 큐를 지나간다. 그래서 구독 수가 늘면 밀리는 총량도
192
- * 그만큼 늘고, 양보 한 번에 소비자 여럿이 나눠 꺼내야 한다. 그 조건에서도 상한을 넘지 않아야 한다.
193
- */
194
- const r = runChild(5000, { consume: true, chunk: 200, subscribers: 20 })
195
- assert.equal(r.status, 0, '구독 20개에서도 살아 있어야 한다')
196
- assert.equal(r.overflowed, false)
197
- })
198
-
199
- test('★ 한 실행 차례의 경계는 1,025건이다 — 재서 확인한 값이다', () => {
200
- /*
201
- * ── 측정값 (2026-08-27) ─────────────────────────────────────────────────────
202
- * 청크 1,024 · 1,025 산다
203
- * 청크 1,026 죽는다
204
- * 구독 수(1·5·20) 경계를 바꾸지 않는다 — 구독마다 자기 대기열이 따로다
205
- *
206
- * 1,025 까지 사는 이유: 청크가 시작될 때 소비자의 요청이 하나 걸려 있어 첫 건은 바로 전달되고,
207
- * 그 뒤 1,024건이 쌓인 상태에서 검사를 통과한다. 1,026번째에 상한에 닿는다.
208
- *
209
- * 처음에 「청크가 상한과 같으면 위험하다」고 단정했는데 틀렸다. 재서 고쳤다.
210
- */
211
- assert.equal(runChild(5000, { consume: true, chunk: 1025 }).status, 0, '1,025 는 산다')
212
- const over = runChild(5000, { consume: true, chunk: 1026 })
213
- assert.ok(over.overflowed, '1,026 은 넘친다')
214
- assert.notEqual(over.status, 0, '그리고 프로세스가 내려간다')
215
- })
216
-
217
- test('★ 그래도 여유를 둔다 — 같은 실행 차례에 다른 발행처가 함께 넣는다', () => {
218
- /*
219
- * 경계가 1,025 라도 그것에 붙여 쓰지 않는다. 이 채널에 발행하는 곳이 우리만이 아니다 —
220
- * `integration-base` 의 상태 등록 변경과 `shell` 의 진행률 보고가 같은 채널을 쓴다. 그것들이
221
- * 같은 실행 차례에 끼어들면 우리 몫에 더해진다.
222
- *
223
- * 엔진의 값이 200 이다(경계의 1/5). 이 테스트는 그 값이 여유 있는 쪽에 있는지만 본다.
224
- */
225
- const cap = Number(/static PUBLISH_CHUNK = ([0-9_]+)/.exec(src)?.[1]?.replace(/_/g, ''))
226
- assert.ok(cap > 0 && cap <= 512, `상한이 ${cap} 이다 — 경계(1,025)의 절반 아래여야 한다`)
227
- })
228
-
229
- test('청크가 넉넉히 작으면 구독이 늘어도 여유가 남는다 — 엔진의 200이 그 자리에 있다', () => {
230
- const r = runChild(5000, { consume: true, chunk: 200, subscribers: 50 })
231
- assert.equal(r.status, 0)
232
- assert.equal(r.overflowed, false)
233
- })
234
-
235
- test('★ 발행한 것이 하나도 빠지지 않는다 — 청크로 나눈 것이 값을 잃지 않았음을 확인한다', () => {
236
- /*
237
- * 청크는 시점만 나눈다. 건수·내용·순서가 그대로여야 한다. 그것을 확인하지 않으면 「죽지 않는다」만
238
- * 알고 「제대로 전달된다」는 모르는 상태가 된다.
239
- */
240
- const r = runChild(3000, { consume: true, chunk: 200, watchAll: true })
241
- assert.equal(r.status, 0)
242
- assert.equal(r.result?.pulled, 3000, '발행한 3,000건이 그대로 도착해야 한다')
243
- assert.equal(r.result?.ordered, true, '순서도 그대로여야 한다')
244
- })