@operato/twin-kernel 0.11.25 → 0.11.26
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/flow-engine.js +4 -2
- package/dist/observed-reducer.js +3 -2
- package/dist-cjs/index.cjs +28 -2
- package/package.json +2 -2
package/dist/flow-engine.js
CHANGED
|
@@ -17,7 +17,7 @@ import { resolveSubject } from '@operato/ops-contract';
|
|
|
17
17
|
import { WMS_ORDER_KIND } from '@operato/ops-contract';
|
|
18
18
|
import { transformationEvent, aggregationEvent, objectEvent, parseEpc, DISP, ILMD_ATTR, CBV_BIZSTEP, objectUri, bizTransactionUri, gdtiUri } from '@operato/ops-contract';
|
|
19
19
|
import { allocationPolicyOf } from "./allocation-policy.js";
|
|
20
|
-
import { ORDER_FOLD_DEFAULT, emptyFoldedOrders, foldOrdersInto, foldedOrderCount, orderFoldPolicyOf, planOrderFold } from '@operato/ops-contract';
|
|
20
|
+
import { ORDER_FOLD_DEFAULT, emptyFoldedOrders, foldOrdersInto, foldedOrderCount, pruneFoldedHours, orderFoldPolicyOf, planOrderFold } from '@operato/ops-contract';
|
|
21
21
|
import { OP_PARAM } from '@operato/ops-contract';
|
|
22
22
|
import { parseIsoDuration } from '@operato/ops-contract';
|
|
23
23
|
import { analyzeCapacity } from '@operato/ops-contract';
|
|
@@ -721,7 +721,9 @@ export class FlowEngine {
|
|
|
721
721
|
const ids = planOrderFold([...this.orders.values()], nowMs ?? this.nowMs(), this.orderFoldPolicy);
|
|
722
722
|
if (!ids.length)
|
|
723
723
|
return 0;
|
|
724
|
-
|
|
724
|
+
/* 창 밖 시간 칸은 접을 때 버린다 — 칸 수가 T/1h 를 넘지 않게(ADR-0092 결정 2 보탬). */
|
|
725
|
+
const now = nowMs ?? this.nowMs();
|
|
726
|
+
this.foldedOrders = pruneFoldedHours(foldOrdersInto(this.foldedOrders, ids.map(id => this.orders.get(id)).filter(Boolean)), now, this.orderFoldPolicy);
|
|
725
727
|
for (const id of ids)
|
|
726
728
|
this.orders.delete(id);
|
|
727
729
|
this.revision++;
|
package/dist/observed-reducer.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import { computeOee, isWorkShiftExecutionBasis } from '@operato/ops-contract';
|
|
23
23
|
import { OP_EVENT, capabilityOf, itemKeyOf, judgeAgainstSpec, requiredTestsFor, locationStatusOf, readBoardEquipment, readBoardLocations, readBoardAssets, effectivityAt, offCalendarAt, offCalendarReasonAt, activeShiftAt } from '@operato/ops-contract';
|
|
24
24
|
import { ILMD_ATTR, parseEpc } from '@operato/ops-contract';
|
|
25
|
-
import { emptyFoldedOrders, foldOrdersInto, foldedOrderCount, isOrderTerminal, orderFoldPolicyOf, planOrderFold, standsNewOrderRow } from '@operato/ops-contract';
|
|
25
|
+
import { emptyFoldedOrders, foldOrdersInto, foldedOrderCount, pruneFoldedHours, isOrderTerminal, orderFoldPolicyOf, planOrderFold, standsNewOrderRow } from '@operato/ops-contract';
|
|
26
26
|
import { expiryFromAttributes, lotFromAttributes } from '@operato/ops-contract';
|
|
27
27
|
/* 클래스 마스터 표는 상태를 들므로 커널에 있다(§`class-master-table`). */
|
|
28
28
|
import { ClassMasterTable } from "./class-master-table.js";
|
|
@@ -1423,7 +1423,8 @@ export class ObservedReducer {
|
|
|
1423
1423
|
if (!ids.length)
|
|
1424
1424
|
return 0;
|
|
1425
1425
|
const rows = ids.map(id => this.orders.get(id)).filter(Boolean);
|
|
1426
|
-
|
|
1426
|
+
/* 창 밖 시간 칸은 접을 때 버린다 — 칸 수가 T/1h 를 넘지 않게(ADR-0092 결정 2 보탬). */
|
|
1427
|
+
this.foldedOrders = pruneFoldedHours(foldOrdersInto(this.foldedOrders, rows), nowMs, this.orderFoldPolicy);
|
|
1427
1428
|
for (const id of ids) {
|
|
1428
1429
|
this.orders.delete(id);
|
|
1429
1430
|
this.lastAt.delete(`order:${id}`);
|
package/dist-cjs/index.cjs
CHANGED
|
@@ -1910,6 +1910,7 @@ function gs1KeyDigitViolation(uri) {
|
|
|
1910
1910
|
}
|
|
1911
1911
|
|
|
1912
1912
|
// ../ops-contract/dist/order-fold.js
|
|
1913
|
+
var ORDER_FOLD_HOUR_MS = 60 * 60 * 1e3;
|
|
1913
1914
|
var ORDER_FOLD_DEFAULT = Object.freeze({ afterMs: 24 * 60 * 60 * 1e3, maxTerminal: 1e3 });
|
|
1914
1915
|
function orderFoldPolicyOf(declared) {
|
|
1915
1916
|
const policy = { ...ORDER_FOLD_DEFAULT };
|
|
@@ -1922,6 +1923,9 @@ function orderFoldPolicyOf(declared) {
|
|
|
1922
1923
|
}
|
|
1923
1924
|
policy[key] = key === "maxTerminal" ? Math.floor(v) : v;
|
|
1924
1925
|
}
|
|
1926
|
+
if (policy.afterMs % ORDER_FOLD_HOUR_MS !== 0) {
|
|
1927
|
+
return { error: `order fold afterMs must be a whole number of hours, got ${policy.afterMs} ms \u2014 the window is counted in hour slots (ADR-0092)` };
|
|
1928
|
+
}
|
|
1925
1929
|
if (policy.maxTerminal < 1)
|
|
1926
1930
|
return { error: "order fold maxTerminal must be at least 1 (ADR-0092)" };
|
|
1927
1931
|
return { policy };
|
|
@@ -1949,6 +1953,7 @@ function foldOrdersInto(folded, orders) {
|
|
|
1949
1953
|
counts: Object.fromEntries(Object.entries(folded?.counts ?? {}).map(([k, v]) => [k, { ...v }])),
|
|
1950
1954
|
boundaryMs: folded?.boundaryMs ?? null
|
|
1951
1955
|
};
|
|
1956
|
+
const hours = Object.fromEntries(Object.entries(folded?.hours ?? {}).map(([h, byKind]) => [h, Object.fromEntries(Object.entries(byKind).map(([k, v]) => [k, { ...v }]))]));
|
|
1952
1957
|
for (const o of orders) {
|
|
1953
1958
|
const kind = String(o.kind ?? "");
|
|
1954
1959
|
const status = String(o.status ?? "");
|
|
@@ -1956,8 +1961,12 @@ function foldOrdersInto(folded, orders) {
|
|
|
1956
1961
|
byStatus[status] = (byStatus[status] ?? 0) + 1;
|
|
1957
1962
|
if (typeof o.terminalAtMs === "number" && Number.isFinite(o.terminalAtMs)) {
|
|
1958
1963
|
out.boundaryMs = out.boundaryMs === null ? o.terminalAtMs : Math.max(out.boundaryMs, o.terminalAtMs);
|
|
1964
|
+
const slot = (hours[String(hourStartOf(o.terminalAtMs))] ??= {})[kind] ??= {};
|
|
1965
|
+
slot[status] = (slot[status] ?? 0) + 1;
|
|
1959
1966
|
}
|
|
1960
1967
|
}
|
|
1968
|
+
if (Object.keys(hours).length)
|
|
1969
|
+
out.hours = hours;
|
|
1961
1970
|
return out;
|
|
1962
1971
|
}
|
|
1963
1972
|
function standsNewOrderRow(record, eventTimeMs, folded) {
|
|
@@ -1970,6 +1979,22 @@ function standsNewOrderRow(record, eventTimeMs, folded) {
|
|
|
1970
1979
|
return true;
|
|
1971
1980
|
return eventTimeMs > boundary;
|
|
1972
1981
|
}
|
|
1982
|
+
function hourStartOf(ms2) {
|
|
1983
|
+
return Math.floor(ms2 / ORDER_FOLD_HOUR_MS) * ORDER_FOLD_HOUR_MS;
|
|
1984
|
+
}
|
|
1985
|
+
function finishedWindowStartMs(nowMs, policy = ORDER_FOLD_DEFAULT) {
|
|
1986
|
+
return hourStartOf(nowMs) - policy.afterMs;
|
|
1987
|
+
}
|
|
1988
|
+
function pruneFoldedHours(folded, nowMs, policy = ORDER_FOLD_DEFAULT) {
|
|
1989
|
+
if (!folded.hours)
|
|
1990
|
+
return folded;
|
|
1991
|
+
const start = finishedWindowStartMs(nowMs, policy);
|
|
1992
|
+
const kept = Object.fromEntries(Object.entries(folded.hours).filter(([h]) => Number(h) >= start));
|
|
1993
|
+
const out = { counts: folded.counts, boundaryMs: folded.boundaryMs };
|
|
1994
|
+
if (Object.keys(kept).length)
|
|
1995
|
+
out.hours = kept;
|
|
1996
|
+
return out;
|
|
1997
|
+
}
|
|
1973
1998
|
|
|
1974
1999
|
// ../ops-contract/dist/iso-duration.js
|
|
1975
2000
|
var RE = /^(-)?P(?:(\d+(?:\.\d+)?)W)?(?:(\d+(?:\.\d+)?)D)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/;
|
|
@@ -3852,7 +3877,7 @@ var ObservedReducer = class {
|
|
|
3852
3877
|
const ids = planOrderFold([...this.orders.values()], nowMs, this.orderFoldPolicy);
|
|
3853
3878
|
if (!ids.length) return 0;
|
|
3854
3879
|
const rows = ids.map((id) => this.orders.get(id)).filter(Boolean);
|
|
3855
|
-
this.foldedOrders = foldOrdersInto(this.foldedOrders, rows);
|
|
3880
|
+
this.foldedOrders = pruneFoldedHours(foldOrdersInto(this.foldedOrders, rows), nowMs, this.orderFoldPolicy);
|
|
3856
3881
|
for (const id of ids) {
|
|
3857
3882
|
this.orders.delete(id);
|
|
3858
3883
|
this.lastAt.delete(`order:${id}`);
|
|
@@ -4524,7 +4549,8 @@ var FlowEngine = class {
|
|
|
4524
4549
|
}
|
|
4525
4550
|
const ids = planOrderFold([...this.orders.values()], nowMs ?? this.nowMs(), this.orderFoldPolicy);
|
|
4526
4551
|
if (!ids.length) return 0;
|
|
4527
|
-
|
|
4552
|
+
const now = nowMs ?? this.nowMs();
|
|
4553
|
+
this.foldedOrders = pruneFoldedHours(foldOrdersInto(this.foldedOrders, ids.map((id) => this.orders.get(id)).filter(Boolean)), now, this.orderFoldPolicy);
|
|
4528
4554
|
for (const id of ids) this.orders.delete(id);
|
|
4529
4555
|
this.revision++;
|
|
4530
4556
|
return ids.length;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@operato/twin-kernel",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Twin Domain Kernel — framework-agnostic, zero-dep (domain + sim + 3-channel contract). WMS/YMS/MES, EPCIS 2.0 · ISA-95.",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
"test": "node --test test/*.test.ts"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@operato/ops-contract": "^0.9.
|
|
31
|
+
"@operato/ops-contract": "^0.9.37"
|
|
32
32
|
}
|
|
33
33
|
}
|