@aeolus-fleet/core 0.24.0 → 0.25.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/README.md +5 -5
- package/dist/adapters/prisma/generated/browser.d.ts +12 -3
- package/dist/adapters/prisma/generated/client.d.ts +12 -3
- package/dist/adapters/prisma/generated/commonInputTypes.d.ts +60 -0
- package/dist/adapters/prisma/generated/enums.d.ts +15 -1
- package/dist/adapters/prisma/generated/enums.js +13 -1
- package/dist/adapters/prisma/generated/enums.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/class.d.ts +11 -0
- package/dist/adapters/prisma/generated/internal/class.js +4 -4
- package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +109 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js +16 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +17 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +16 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/adapters/prisma/generated/models/Delivery.d.ts +304 -4
- package/dist/adapters/prisma/generated/models/Fleet.d.ts +267 -0
- package/dist/adapters/prisma/generated/models/Lease.d.ts +332 -1
- package/dist/adapters/prisma/generated/models/OverdueDelivery.d.ts +1687 -0
- package/dist/adapters/prisma/generated/models/OverdueDelivery.js +2 -0
- package/dist/adapters/prisma/generated/models/OverdueDelivery.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Ship.d.ts +271 -0
- package/dist/adapters/prisma/generated/models.d.ts +1 -0
- package/dist/adapters/prisma/history.js +231 -46
- package/dist/adapters/prisma/history.js.map +1 -1
- package/dist/adapters/prisma/installation.js +30 -1
- package/dist/adapters/prisma/installation.js.map +1 -1
- package/dist/adapters/prisma/messaging.js +11 -7
- package/dist/adapters/prisma/messaging.js.map +1 -1
- package/dist/adapters/prisma/overdue.d.ts +4 -0
- package/dist/adapters/prisma/overdue.js +63 -0
- package/dist/adapters/prisma/overdue.js.map +1 -0
- package/dist/adapters/prisma/registry.js +32 -7
- package/dist/adapters/prisma/registry.js.map +1 -1
- package/dist/adapters/prisma/rows.d.ts +12 -1
- package/dist/adapters/prisma/rows.js +46 -1
- package/dist/adapters/prisma/rows.js.map +1 -1
- package/dist/adapters/prisma/unit-of-work.d.ts +2 -1
- package/dist/adapters/prisma/unit-of-work.js +2 -0
- package/dist/adapters/prisma/unit-of-work.js.map +1 -1
- package/dist/adapters/trpc/context.d.ts +16 -0
- package/dist/adapters/trpc/fleet.d.ts +232 -14
- package/dist/adapters/trpc/fleet.js +49 -6
- package/dist/adapters/trpc/fleet.js.map +1 -1
- package/dist/adapters/trpc/installation.d.ts +14 -0
- package/dist/adapters/trpc/installation.js +7 -1
- package/dist/adapters/trpc/installation.js.map +1 -1
- package/dist/adapters/trpc/router.d.ts +301 -9
- package/dist/adapters/trpc/ship-protocol.js +2 -2
- package/dist/adapters/trpc/ship-protocol.js.map +1 -1
- package/dist/adapters/trpc/ship.d.ts +87 -0
- package/dist/adapters/trpc/ship.js +96 -1
- package/dist/adapters/trpc/ship.js.map +1 -1
- package/dist/adapters/trpc/starting-prompt-text.d.ts +1 -1
- package/dist/adapters/trpc/starting-prompt-text.js +22 -25
- package/dist/adapters/trpc/starting-prompt-text.js.map +1 -1
- package/dist/adapters/trpc/trpc.js +3 -0
- package/dist/adapters/trpc/trpc.js.map +1 -1
- package/dist/app.d.ts +4 -2
- package/dist/app.js +21 -9
- package/dist/app.js.map +1 -1
- package/dist/domain/messaging/delivery.d.ts +88 -28
- package/dist/domain/messaging/delivery.js +213 -39
- package/dist/domain/messaging/delivery.js.map +1 -1
- package/dist/domain/messaging/dismiss-delivery.d.ts +1 -1
- package/dist/domain/messaging/dismiss-delivery.js +1 -1
- package/dist/domain/messaging/hand-over-delivery.d.ts +38 -0
- package/dist/domain/messaging/hand-over-delivery.js +46 -0
- package/dist/domain/messaging/hand-over-delivery.js.map +1 -0
- package/dist/domain/messaging/message.d.ts +12 -1
- package/dist/domain/messaging/message.js +2 -0
- package/dist/domain/messaging/message.js.map +1 -1
- package/dist/domain/messaging/overdue.d.ts +60 -0
- package/dist/domain/messaging/overdue.js +52 -0
- package/dist/domain/messaging/overdue.js.map +1 -0
- package/dist/domain/messaging/ports.d.ts +20 -0
- package/dist/domain/messaging/public.d.ts +1 -0
- package/dist/domain/messaging/public.js +2 -0
- package/dist/domain/messaging/public.js.map +1 -0
- package/dist/domain/messaging/push-receive-deliveries.d.ts +48 -0
- package/dist/domain/messaging/push-receive-deliveries.js +70 -0
- package/dist/domain/messaging/push-receive-deliveries.js.map +1 -0
- package/dist/domain/messaging/receive-deliveries.d.ts +39 -6
- package/dist/domain/messaging/receive-deliveries.js +80 -50
- package/dist/domain/messaging/receive-deliveries.js.map +1 -1
- package/dist/domain/messaging/report-handled.d.ts +22 -0
- package/dist/domain/messaging/report-handled.js +13 -0
- package/dist/domain/messaging/report-handled.js.map +1 -0
- package/dist/domain/messaging/report-not-handled.d.ts +22 -0
- package/dist/domain/messaging/report-not-handled.js +13 -0
- package/dist/domain/messaging/report-not-handled.js.map +1 -0
- package/dist/domain/messaging/report-turn-end.d.ts +29 -0
- package/dist/domain/messaging/report-turn-end.js +36 -0
- package/dist/domain/messaging/report-turn-end.js.map +1 -0
- package/dist/domain/messaging/resend-delivery.d.ts +1 -1
- package/dist/domain/messaging/resend-delivery.js +1 -1
- package/dist/domain/messaging/tell-overdue-deliveries.d.ts +25 -0
- package/dist/domain/messaging/tell-overdue-deliveries.js +30 -0
- package/dist/domain/messaging/tell-overdue-deliveries.js.map +1 -0
- package/dist/domain/registry/installation-fleet.d.ts +3 -2
- package/dist/domain/registry/installation-fleet.js.map +1 -1
- package/dist/domain/registry/leases.d.ts +26 -0
- package/dist/domain/registry/leases.js +26 -1
- package/dist/domain/registry/leases.js.map +1 -1
- package/dist/domain/registry/ping-status.d.ts +2 -2
- package/dist/domain/registry/ping-status.js +7 -4
- package/dist/domain/registry/ping-status.js.map +1 -1
- package/dist/domain/registry/ports.d.ts +40 -0
- package/dist/domain/registry/public.d.ts +2 -2
- package/dist/domain/registry/public.js +1 -1
- package/dist/domain/registry/public.js.map +1 -1
- package/dist/domain/registry/report-turn.d.ts +28 -0
- package/dist/domain/registry/report-turn.js +28 -0
- package/dist/domain/registry/report-turn.js.map +1 -0
- package/dist/domain/registry/turn.d.ts +25 -0
- package/dist/domain/registry/turn.js +30 -0
- package/dist/domain/registry/turn.js.map +1 -0
- package/dist/domain/shared/delivery-way.d.ts +83 -0
- package/dist/domain/shared/delivery-way.js +89 -0
- package/dist/domain/shared/delivery-way.js.map +1 -0
- package/dist/domain/shared/errors.d.ts +1 -1
- package/dist/domain/shared/errors.js.map +1 -1
- package/dist/domain/shared/history.d.ts +116 -19
- package/dist/domain/shared/history.js +1 -1
- package/dist/domain/shared/history.js.map +1 -1
- package/dist/domain/shared/read-message.d.ts +7 -3
- package/dist/domain/shared/read-message.js +7 -4
- package/dist/domain/shared/read-message.js.map +1 -1
- package/dist/domain/shared/read-needs-attention.d.ts +5 -5
- package/dist/domain/shared/read-needs-attention.js +4 -4
- package/dist/domain/shared/read-needs-attention.js.map +1 -1
- package/dist/domain/shared/read-no-ship-can-take.d.ts +13 -0
- package/dist/domain/shared/read-no-ship-can-take.js +12 -0
- package/dist/domain/shared/read-no-ship-can-take.js.map +1 -0
- package/dist/domain/shared/read-overdue.d.ts +13 -0
- package/dist/domain/shared/read-overdue.js +12 -0
- package/dist/domain/shared/read-overdue.js.map +1 -0
- package/dist/domain/shared/read-ship-messages.d.ts +4 -1
- package/dist/domain/shared/read-ship-messages.js +6 -1
- package/dist/domain/shared/read-ship-messages.js.map +1 -1
- package/dist/domain/shared/read-ship-way.d.ts +41 -0
- package/dist/domain/shared/read-ship-way.js +39 -0
- package/dist/domain/shared/read-ship-way.js.map +1 -0
- package/dist/repeating-pass.d.ts +15 -0
- package/dist/repeating-pass.js +31 -0
- package/dist/repeating-pass.js.map +1 -0
- package/dist/wiring.d.ts +19 -0
- package/dist/wiring.js +25 -0
- package/dist/wiring.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/prisma/migrations/20261012190000_delivery_handed/migration.sql +11 -0
- package/src/adapters/prisma/migrations/20261012210000_push_receive/migration.sql +7 -0
- package/src/adapters/prisma/migrations/20261013090000_handled/migration.sql +6 -0
- package/src/adapters/prisma/migrations/20261013100000_turn/migration.sql +6 -0
- package/src/adapters/prisma/migrations/20261013120000_overdue/migration.sql +28 -0
- package/src/adapters/prisma/migrations/20261013140000_delivery_state_index/migration.sql +4 -0
- package/src/adapters/prisma/schema.prisma +66 -4
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SYSTEM } from '../shared/events.js';
|
|
2
|
+
const MINUTE_MS = 60_000;
|
|
3
|
+
/** A delivery handed and not confirmed this long is overdue, whatever the turn. */
|
|
4
|
+
export const NOT_CONFIRMED_MINUTES = 10;
|
|
5
|
+
/** A delivery waiting this long while the session is idle is overdue. */
|
|
6
|
+
export const IDLE_MINUTES = 10;
|
|
7
|
+
/** A delivery waiting this long while the session is busy is overdue. */
|
|
8
|
+
export const BUSY_MINUTES = 60;
|
|
9
|
+
/**
|
|
10
|
+
* The crew's oldest waiting delivery whose clock ran out, if any. A handed
|
|
11
|
+
* delivery runs the 10 minute clock from its hand-over. A pending or received
|
|
12
|
+
* one runs 10 minutes while the session is idle and 60 while it is busy,
|
|
13
|
+
* counted from the latest of its state, the turn and the lease's push: a
|
|
14
|
+
* lease with no turn reported is idle since it was pushed.
|
|
15
|
+
*/
|
|
16
|
+
export function overdueDelivery(crew, now) {
|
|
17
|
+
const turn = crew.turn ?? { state: 'idle', at: crew.pushedAt };
|
|
18
|
+
const oldestFirst = crew.waiting.toSorted((first, second) => first.sentAt.getTime() - second.sentAt.getTime() || first.deliveryId.localeCompare(second.deliveryId));
|
|
19
|
+
for (const delivery of oldestFirst) {
|
|
20
|
+
const { clock, minutes, from } = clockOf(delivery, { turn, pushedAt: crew.pushedAt });
|
|
21
|
+
if (now.getTime() - from.getTime() >= minutes * MINUTE_MS) {
|
|
22
|
+
return { fleetId: crew.fleetId, shipId: crew.shipId, leaseId: crew.leaseId, delivery, clock, minutes };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
function clockOf(delivery, crew) {
|
|
28
|
+
if (delivery.state === 'handed') {
|
|
29
|
+
return { clock: 'notConfirmed', minutes: NOT_CONFIRMED_MINUTES, from: delivery.since };
|
|
30
|
+
}
|
|
31
|
+
const from = new Date(Math.max(delivery.since.getTime(), crew.turn.at.getTime(), crew.pushedAt.getTime()));
|
|
32
|
+
switch (crew.turn.state) {
|
|
33
|
+
case 'idle':
|
|
34
|
+
return { clock: 'idle', minutes: IDLE_MINUTES, from };
|
|
35
|
+
case 'busy':
|
|
36
|
+
return { clock: 'busy', minutes: BUSY_MINUTES, from };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** DeliveryOverdue: the fleet told argo, as the system, that the delivery's clock ran out. */
|
|
40
|
+
export function overdueEvent(overdue, at) {
|
|
41
|
+
return {
|
|
42
|
+
fleetId: overdue.fleetId,
|
|
43
|
+
type: 'DeliveryOverdue',
|
|
44
|
+
occurredAt: at,
|
|
45
|
+
actor: SYSTEM,
|
|
46
|
+
shipId: overdue.shipId,
|
|
47
|
+
messageId: overdue.delivery.messageId,
|
|
48
|
+
deliveryId: overdue.delivery.deliveryId,
|
|
49
|
+
details: { leaseId: overdue.leaseId, clock: overdue.clock, minutes: overdue.minutes },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=overdue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overdue.js","sourceRoot":"","sources":["../../../src/domain/messaging/overdue.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DeliveryId, FleetId, LeaseId, MessageId, ShipId } from '@aeolus-fleet/common';
|
|
2
2
|
import type { Delivery, Message } from './message.js';
|
|
3
|
+
import type { Overdue, PushedCrew } from './overdue.js';
|
|
3
4
|
/** One sender's idempotency key, in its fleet. */
|
|
4
5
|
export interface SenderKey {
|
|
5
6
|
fleetId: FleetId;
|
|
@@ -116,3 +117,22 @@ export interface ReceiverWatch {
|
|
|
116
117
|
/** Stops watching. */
|
|
117
118
|
stop(): void;
|
|
118
119
|
}
|
|
120
|
+
/** Outbound port: the fleet's open pushed leases, for the 10 and 60 minute clocks. Read without a lock. */
|
|
121
|
+
export interface PushedCrews {
|
|
122
|
+
/**
|
|
123
|
+
* Every open pushed lease of the fleet, with its turn and the deliveries
|
|
124
|
+
* waiting for it: pending for its ship or its type, or received or handed
|
|
125
|
+
* with the lease, each with when it entered its state.
|
|
126
|
+
*/
|
|
127
|
+
waiting(fleetId: FleetId): Promise<PushedCrew[]>;
|
|
128
|
+
}
|
|
129
|
+
/** Outbound port: the deliveries argo was told are overdue, once per lease and delivery. */
|
|
130
|
+
export interface OverdueDeliveryRepository {
|
|
131
|
+
/**
|
|
132
|
+
* Stores that argo is told the delivery is overdue on the lease, at `at`,
|
|
133
|
+
* only while the delivery is still in the state it was judged in and argo
|
|
134
|
+
* was not told of it on that lease before. Whether it stored it: two passes
|
|
135
|
+
* at once store it once.
|
|
136
|
+
*/
|
|
137
|
+
tell(overdue: Overdue, at: Date): Promise<boolean>;
|
|
138
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { OverdueClock, WaitingState } from './overdue.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/domain/messaging/public.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IdGenerator } from '@aeolus-fleet/common';
|
|
2
|
+
import { type HoldLeaseTx, type LeaseRepository } from '../registry/public.js';
|
|
3
|
+
import type { Crew } from '../shared/caller.js';
|
|
4
|
+
import type { Clock } from '../shared/clock.js';
|
|
5
|
+
import { type EventLog } from '../shared/events.js';
|
|
6
|
+
import { type Result } from '../shared/result.js';
|
|
7
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
8
|
+
import type { DeliveryRepository, ReceiverWakeups } from './ports.js';
|
|
9
|
+
import { type ReceivedDelivery, type ReceiveRefusal } from './receive-deliveries.js';
|
|
10
|
+
export interface PushReceiveDeliveriesTx extends HoldLeaseTx {
|
|
11
|
+
leases: Pick<LeaseRepository, 'findOpenByIdForShare' | 'markPushed'>;
|
|
12
|
+
deliveries: DeliveryRepository;
|
|
13
|
+
events: EventLog;
|
|
14
|
+
}
|
|
15
|
+
/** One delivery a push receive took, as the computer side keeps it: where it stands, and its last hand-over number. */
|
|
16
|
+
export interface PushReceivedDelivery extends ReceivedDelivery {
|
|
17
|
+
/** Received: not yet handed to the agent. Handed: handed already, its hand-over number reported. */
|
|
18
|
+
state: 'received' | 'handed';
|
|
19
|
+
/** The last hand-over number the crew reported; none while received, or when a plain receive handed it. */
|
|
20
|
+
handOverNumber: number | null;
|
|
21
|
+
}
|
|
22
|
+
export interface DeliveriesPushReceived {
|
|
23
|
+
/** None when the wait ended without a delivery. */
|
|
24
|
+
deliveries: PushReceivedDelivery[];
|
|
25
|
+
}
|
|
26
|
+
export type PushReceiveDeliveries = (crew: Crew, input: {
|
|
27
|
+
max?: number;
|
|
28
|
+
}) => Promise<Result<DeliveriesPushReceived, ReceiveRefusal>>;
|
|
29
|
+
/**
|
|
30
|
+
* Use case: the crew's computer side, the trierarch or the plugin watcher,
|
|
31
|
+
* receives for the agent (`pushReceive`, decision 0040), up to `max`, 1 to
|
|
32
|
+
* 10, one by default. Its scope (messages:receive) is checked before this
|
|
33
|
+
* runs. Each look is one unit of work (see `pushReceiptForCrew`). A pending
|
|
34
|
+
* delivery becomes received, in flight with the crew's ship and lease, and
|
|
35
|
+
* counts no attempt; the computer side reports handed once it hands it to
|
|
36
|
+
* the agent. Its own in flight comes again first, changing nothing, so a
|
|
37
|
+
* restart or a lost answer loses nothing. From its first push receive until
|
|
38
|
+
* it ends, the lease is pushed: the agent's plain receive answers nothing.
|
|
39
|
+
* When nothing is there it waits as a receive does, about 25 seconds.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createPushReceiveDeliveries(deps: {
|
|
42
|
+
uow: UnitOfWork<PushReceiveDeliveriesTx>;
|
|
43
|
+
clock: Clock;
|
|
44
|
+
ids: IdGenerator;
|
|
45
|
+
wakeups: ReceiverWakeups;
|
|
46
|
+
/** How long a push receive waits on an empty inbox; about 25 seconds unless a test says otherwise. */
|
|
47
|
+
waitMs?: number;
|
|
48
|
+
}): PushReceiveDeliveries;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { holdLease, markLeasePushed } from '../registry/public.js';
|
|
2
|
+
import { recordEvent } from '../shared/events.js';
|
|
3
|
+
import { ok } from '../shared/result.js';
|
|
4
|
+
import { pushReceiveDelivery } from './delivery.js';
|
|
5
|
+
import { RECEIVE_WAIT_MS, receivedDeliveryOf, waitForDeliveries, } from './receive-deliveries.js';
|
|
6
|
+
import { receiveMax } from './receive-max.js';
|
|
7
|
+
/**
|
|
8
|
+
* Takes up to `max` deliveries for the crew in one unit of work: marks its
|
|
9
|
+
* lease pushed (LeasePushed the first time), holds it, then takes its own in
|
|
10
|
+
* flight, received or handed,
|
|
11
|
+
* and then the oldest pending for its ship or its type, each received.
|
|
12
|
+
*/
|
|
13
|
+
async function pushReceiptForCrew(deps, receipt) {
|
|
14
|
+
const { tx, ids, at } = deps;
|
|
15
|
+
const { crew, max } = receipt;
|
|
16
|
+
await markLeasePushed({ tx, ids }, { fleetId: crew.fleetId, shipId: crew.shipId, leaseId: crew.leaseId, at });
|
|
17
|
+
const ship = await holdLease(tx, crew);
|
|
18
|
+
if (!ship.isOk) {
|
|
19
|
+
return ship;
|
|
20
|
+
}
|
|
21
|
+
const taken = await tx.deliveries.findClaimableForUpdate({
|
|
22
|
+
fleetId: crew.fleetId,
|
|
23
|
+
shipId: crew.shipId,
|
|
24
|
+
type: ship.value.type,
|
|
25
|
+
leaseId: crew.leaseId,
|
|
26
|
+
limit: max,
|
|
27
|
+
excluding: [],
|
|
28
|
+
});
|
|
29
|
+
const received = [];
|
|
30
|
+
for (const { delivery, message } of taken) {
|
|
31
|
+
const { delivery: changed, events } = pushReceiveDelivery(delivery, { crew, at });
|
|
32
|
+
await tx.deliveries.update(changed);
|
|
33
|
+
for (const event of events) {
|
|
34
|
+
await recordEvent({ events: tx.events, ids }, event);
|
|
35
|
+
}
|
|
36
|
+
const handedOut = await receivedDeliveryOf(tx, { delivery: changed, message });
|
|
37
|
+
if (!handedOut.isOk) {
|
|
38
|
+
return handedOut;
|
|
39
|
+
}
|
|
40
|
+
received.push({
|
|
41
|
+
...handedOut.value,
|
|
42
|
+
state: changed.state === 'handed' ? 'handed' : 'received',
|
|
43
|
+
handOverNumber: changed.handOverNumber,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return ok({ ship: ship.value, deliveries: received });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Use case: the crew's computer side, the trierarch or the plugin watcher,
|
|
50
|
+
* receives for the agent (`pushReceive`, decision 0040), up to `max`, 1 to
|
|
51
|
+
* 10, one by default. Its scope (messages:receive) is checked before this
|
|
52
|
+
* runs. Each look is one unit of work (see `pushReceiptForCrew`). A pending
|
|
53
|
+
* delivery becomes received, in flight with the crew's ship and lease, and
|
|
54
|
+
* counts no attempt; the computer side reports handed once it hands it to
|
|
55
|
+
* the agent. Its own in flight comes again first, changing nothing, so a
|
|
56
|
+
* restart or a lost answer loses nothing. From its first push receive until
|
|
57
|
+
* it ends, the lease is pushed: the agent's plain receive answers nothing.
|
|
58
|
+
* When nothing is there it waits as a receive does, about 25 seconds.
|
|
59
|
+
*/
|
|
60
|
+
export function createPushReceiveDeliveries(deps) {
|
|
61
|
+
const waitMs = deps.waitMs ?? RECEIVE_WAIT_MS;
|
|
62
|
+
return async (crew, input) => {
|
|
63
|
+
const max = receiveMax(input.max);
|
|
64
|
+
if (!max.isOk) {
|
|
65
|
+
return max;
|
|
66
|
+
}
|
|
67
|
+
return waitForDeliveries({ clock: deps.clock, wakeups: deps.wakeups, waitMs }, { crew, look: () => deps.uow.run((tx) => pushReceiptForCrew({ tx, ids: deps.ids, at: deps.clock.now() }, { crew, max: max.value })) });
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=push-receive-deliveries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-receive-deliveries.js","sourceRoot":"","sources":["../../../src/domain/messaging/push-receive-deliveries.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DeliveryId, IdGenerator, MessageId, ShipId } from '@aeolus-fleet/common';
|
|
2
|
-
import { type HoldLeaseTx, type LeaseEnded } from '../registry/public.js';
|
|
2
|
+
import { type FindShipTx, type HoldLeaseTx, type LeaseEnded, type LeaseRepository, type Ship } from '../registry/public.js';
|
|
3
3
|
import type { Crew } from '../shared/caller.js';
|
|
4
4
|
import type { Clock } from '../shared/clock.js';
|
|
5
5
|
import type { DomainError } from '../shared/errors.js';
|
|
@@ -7,8 +7,10 @@ import { type EventLog } from '../shared/events.js';
|
|
|
7
7
|
import { type Result } from '../shared/result.js';
|
|
8
8
|
import type { Recipient } from '../shared/selector.js';
|
|
9
9
|
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
10
|
+
import type { Delivery, Message } from './message.js';
|
|
10
11
|
import type { DeliveryRepository, ReceiverWakeups } from './ports.js';
|
|
11
12
|
export interface ReceiveDeliveriesTx extends HoldLeaseTx {
|
|
13
|
+
leases: Pick<LeaseRepository, 'findOpenByIdForShare' | 'isPushed'>;
|
|
12
14
|
deliveries: DeliveryRepository;
|
|
13
15
|
events: EventLog;
|
|
14
16
|
}
|
|
@@ -28,7 +30,7 @@ export interface ReceivedDelivery {
|
|
|
28
30
|
model: string | null;
|
|
29
31
|
inReplyTo: MessageId | null;
|
|
30
32
|
sentAt: Date;
|
|
31
|
-
/** How many times the delivery has been
|
|
33
|
+
/** How many times the delivery has been handed over, this time included: its attempts. */
|
|
32
34
|
attempts: number;
|
|
33
35
|
}
|
|
34
36
|
export interface DeliveriesReceived {
|
|
@@ -41,15 +43,25 @@ export type ReceiveDeliveries = (crew: Crew, input: {
|
|
|
41
43
|
}) => Promise<Result<DeliveriesReceived, ReceiveRefusal>>;
|
|
42
44
|
/** How long a receive waits for a delivery when none is there: about 25 seconds, then it returns empty. */
|
|
43
45
|
export declare const RECEIVE_WAIT_MS = 25000;
|
|
46
|
+
/**
|
|
47
|
+
* The delivery as its crew gets it: with its message, and its sender by id
|
|
48
|
+
* and by the name and type it has in Registry now.
|
|
49
|
+
*/
|
|
50
|
+
export declare function receivedDeliveryOf(tx: FindShipTx, held: {
|
|
51
|
+
delivery: Delivery;
|
|
52
|
+
message: Message;
|
|
53
|
+
}): Promise<Result<ReceivedDelivery, DomainError<'SHIP_NOT_FOUND'>>>;
|
|
44
54
|
/**
|
|
45
55
|
* Use case: a crew receives its deliveries (`receive`), up to `max`, 1 to 10,
|
|
46
56
|
* one by default. Its scope (messages:receive) is checked before this runs.
|
|
47
57
|
* Each attempt is one unit of work (see `claimForCrew`): every delivery it
|
|
48
|
-
* returns is in flight
|
|
49
|
-
* acknowledges it or the lease ends, and the crew's next receive
|
|
50
|
-
* again, counted as another
|
|
51
|
-
*
|
|
58
|
+
* returns is handed at once, in flight with the crew's ship and lease, until
|
|
59
|
+
* the ship acknowledges it or the lease ends, and the crew's next receive
|
|
60
|
+
* hands it again, counted as another attempt, so a lost reply loses nothing.
|
|
61
|
+
* Its fifth attempt makes it undeliverable instead. Each delivery names its sender by id,
|
|
52
62
|
* and by the name and type the sender has now, so the crew can answer by name.
|
|
63
|
+
* On a pushed lease it hands nothing, its pending deliveries included: the
|
|
64
|
+
* computer side takes them with a push receive (decision 0040).
|
|
53
65
|
*
|
|
54
66
|
* When nothing is there it waits, about 25 seconds, for a wake-up for its ship
|
|
55
67
|
* or its type (ADR 0003: LISTEN/NOTIFY after commit), then returns empty. It
|
|
@@ -66,3 +78,24 @@ export declare function createReceiveDeliveries(deps: {
|
|
|
66
78
|
/** How long a receive waits on an empty inbox; about 25 seconds unless a test says otherwise. */
|
|
67
79
|
waitMs?: number;
|
|
68
80
|
}): ReceiveDeliveries;
|
|
81
|
+
/**
|
|
82
|
+
* Looks for the crew's deliveries, one unit of work per `look`, and
|
|
83
|
+
* when there are none waits for a wake-up for its ship or its type, until
|
|
84
|
+
* `waitMs` has passed. It starts watching before it looks a second time, so a
|
|
85
|
+
* delivery that commits between its first look and its watch is found by that
|
|
86
|
+
* second look. A wake-up that brings nothing for it leaves it waiting for the
|
|
87
|
+
* rest of its time.
|
|
88
|
+
*/
|
|
89
|
+
export declare function waitForDeliveries<Found, Refusal>(deps: {
|
|
90
|
+
clock: Clock;
|
|
91
|
+
wakeups: ReceiverWakeups;
|
|
92
|
+
waitMs: number;
|
|
93
|
+
}, wait: {
|
|
94
|
+
crew: Crew;
|
|
95
|
+
look: () => Promise<Result<{
|
|
96
|
+
ship: Ship;
|
|
97
|
+
deliveries: Found[];
|
|
98
|
+
}, Refusal>>;
|
|
99
|
+
}): Promise<Result<{
|
|
100
|
+
deliveries: Found[];
|
|
101
|
+
}, Refusal>>;
|
|
@@ -1,10 +1,36 @@
|
|
|
1
|
-
import { findShip, holdLease } from '../registry/public.js';
|
|
1
|
+
import { findShip, holdLease, isLeasePushed } from '../registry/public.js';
|
|
2
2
|
import { recordEvent } from '../shared/events.js';
|
|
3
3
|
import { ok } from '../shared/result.js';
|
|
4
|
-
import {
|
|
4
|
+
import { handDelivery } from './delivery.js';
|
|
5
5
|
import { receiveMax } from './receive-max.js';
|
|
6
6
|
/** How long a receive waits for a delivery when none is there: about 25 seconds, then it returns empty. */
|
|
7
7
|
export const RECEIVE_WAIT_MS = 25_000;
|
|
8
|
+
/**
|
|
9
|
+
* The delivery as its crew gets it: with its message, and its sender by id
|
|
10
|
+
* and by the name and type it has in Registry now.
|
|
11
|
+
*/
|
|
12
|
+
export async function receivedDeliveryOf(tx, held) {
|
|
13
|
+
const { delivery, message } = held;
|
|
14
|
+
const sender = await findShip(tx, { fleetId: delivery.fleetId, shipId: message.senderShipId });
|
|
15
|
+
if (!sender.isOk) {
|
|
16
|
+
// A message's sender always exists: ships are never deleted, and the foreign key keeps the sender in its fleet.
|
|
17
|
+
return sender;
|
|
18
|
+
}
|
|
19
|
+
return ok({
|
|
20
|
+
deliveryId: delivery.id,
|
|
21
|
+
messageId: message.id,
|
|
22
|
+
senderShipId: message.senderShipId,
|
|
23
|
+
senderName: sender.value.name,
|
|
24
|
+
senderType: sender.value.type,
|
|
25
|
+
recipient: delivery.recipient,
|
|
26
|
+
payload: message.payload,
|
|
27
|
+
contentType: message.contentType,
|
|
28
|
+
model: message.model,
|
|
29
|
+
inReplyTo: message.inReplyToMessageId,
|
|
30
|
+
sentAt: message.createdAt,
|
|
31
|
+
attempts: delivery.attempts,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
8
34
|
/**
|
|
9
35
|
* Claims up to `max` deliveries for the crew in one unit of work: holds its
|
|
10
36
|
* lease, then takes its own deliveries in flight, then the oldest pending ones
|
|
@@ -19,6 +45,10 @@ async function claimForCrew(deps, claim) {
|
|
|
19
45
|
if (!ship.isOk) {
|
|
20
46
|
return ship;
|
|
21
47
|
}
|
|
48
|
+
if (await isLeasePushed(tx, crew)) {
|
|
49
|
+
// The computer side takes a pushed lease's deliveries; the agent's own receive never gets one (decision 0040).
|
|
50
|
+
return ok({ ship: ship.value, deliveries: [] });
|
|
51
|
+
}
|
|
22
52
|
const handedOut = [];
|
|
23
53
|
const claimed = [];
|
|
24
54
|
let hasMore = true;
|
|
@@ -35,31 +65,17 @@ async function claimForCrew(deps, claim) {
|
|
|
35
65
|
hasMore = claimable.length === limit;
|
|
36
66
|
for (const { delivery, message } of claimable) {
|
|
37
67
|
claimed.push(delivery.id);
|
|
38
|
-
const { outcome, delivery: changed, events } =
|
|
68
|
+
const { outcome, delivery: changed, events } = handDelivery(delivery, { crew, at });
|
|
39
69
|
await tx.deliveries.update(changed);
|
|
40
70
|
for (const event of events) {
|
|
41
71
|
await recordEvent({ events: tx.events, ids }, event);
|
|
42
72
|
}
|
|
43
|
-
if (outcome === '
|
|
44
|
-
const
|
|
45
|
-
if (!
|
|
46
|
-
|
|
47
|
-
return sender;
|
|
73
|
+
if (outcome === 'handed') {
|
|
74
|
+
const received = await receivedDeliveryOf(tx, { delivery: changed, message });
|
|
75
|
+
if (!received.isOk) {
|
|
76
|
+
return received;
|
|
48
77
|
}
|
|
49
|
-
handedOut.push(
|
|
50
|
-
deliveryId: changed.id,
|
|
51
|
-
messageId: message.id,
|
|
52
|
-
senderShipId: message.senderShipId,
|
|
53
|
-
senderName: sender.value.name,
|
|
54
|
-
senderType: sender.value.type,
|
|
55
|
-
recipient: changed.recipient,
|
|
56
|
-
payload: message.payload,
|
|
57
|
-
contentType: message.contentType,
|
|
58
|
-
model: message.model,
|
|
59
|
-
inReplyTo: message.inReplyToMessageId,
|
|
60
|
-
sentAt: message.createdAt,
|
|
61
|
-
attempts: changed.attempts,
|
|
62
|
-
});
|
|
78
|
+
handedOut.push(received.value);
|
|
63
79
|
}
|
|
64
80
|
}
|
|
65
81
|
}
|
|
@@ -69,11 +85,13 @@ async function claimForCrew(deps, claim) {
|
|
|
69
85
|
* Use case: a crew receives its deliveries (`receive`), up to `max`, 1 to 10,
|
|
70
86
|
* one by default. Its scope (messages:receive) is checked before this runs.
|
|
71
87
|
* Each attempt is one unit of work (see `claimForCrew`): every delivery it
|
|
72
|
-
* returns is in flight
|
|
73
|
-
* acknowledges it or the lease ends, and the crew's next receive
|
|
74
|
-
* again, counted as another
|
|
75
|
-
*
|
|
88
|
+
* returns is handed at once, in flight with the crew's ship and lease, until
|
|
89
|
+
* the ship acknowledges it or the lease ends, and the crew's next receive
|
|
90
|
+
* hands it again, counted as another attempt, so a lost reply loses nothing.
|
|
91
|
+
* Its fifth attempt makes it undeliverable instead. Each delivery names its sender by id,
|
|
76
92
|
* and by the name and type the sender has now, so the crew can answer by name.
|
|
93
|
+
* On a pushed lease it hands nothing, its pending deliveries included: the
|
|
94
|
+
* computer side takes them with a push receive (decision 0040).
|
|
77
95
|
*
|
|
78
96
|
* When nothing is there it waits, about 25 seconds, for a wake-up for its ship
|
|
79
97
|
* or its type (ADR 0003: LISTEN/NOTIFY after commit), then returns empty. It
|
|
@@ -89,31 +107,43 @@ export function createReceiveDeliveries(deps) {
|
|
|
89
107
|
if (!max.isOk) {
|
|
90
108
|
return max;
|
|
91
109
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
return waitForDeliveries({ clock: deps.clock, wakeups: deps.wakeups, waitMs }, { crew, look: () => deps.uow.run((tx) => claimForCrew({ tx, ids: deps.ids, at: deps.clock.now() }, { crew, max: max.value })) });
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Looks for the crew's deliveries, one unit of work per `look`, and
|
|
115
|
+
* when there are none waits for a wake-up for its ship or its type, until
|
|
116
|
+
* `waitMs` has passed. It starts watching before it looks a second time, so a
|
|
117
|
+
* delivery that commits between its first look and its watch is found by that
|
|
118
|
+
* second look. A wake-up that brings nothing for it leaves it waiting for the
|
|
119
|
+
* rest of its time.
|
|
120
|
+
*/
|
|
121
|
+
export async function waitForDeliveries(deps, wait) {
|
|
122
|
+
const { crew, look } = wait;
|
|
123
|
+
const until = deps.clock.now().getTime() + deps.waitMs;
|
|
124
|
+
let watch;
|
|
125
|
+
try {
|
|
126
|
+
for (;;) {
|
|
127
|
+
const attempt = await look();
|
|
128
|
+
if (!attempt.isOk) {
|
|
129
|
+
return attempt;
|
|
130
|
+
}
|
|
131
|
+
const { ship, deliveries } = attempt.value;
|
|
132
|
+
if (deliveries.length > 0) {
|
|
133
|
+
return ok({ deliveries });
|
|
134
|
+
}
|
|
135
|
+
if (watch === undefined) {
|
|
136
|
+
watch = deps.wakeups.watch({ fleetId: crew.fleetId, shipId: crew.shipId, type: ship.type });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const remainingMs = until - deps.clock.now().getTime();
|
|
140
|
+
if (remainingMs <= 0 || (await watch.next(remainingMs)) === 'timedOut') {
|
|
141
|
+
return ok({ deliveries: [] });
|
|
112
142
|
}
|
|
113
143
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
watch?.stop();
|
|
147
|
+
}
|
|
118
148
|
}
|
|
119
149
|
//# sourceMappingURL=receive-deliveries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receive-deliveries.js","sourceRoot":"","sources":["../../../src/domain/messaging/receive-deliveries.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"receive-deliveries.js","sourceRoot":"","sources":["../../../src/domain/messaging/receive-deliveries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DeliveryId, IdGenerator } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Crew } from '../shared/caller.js';
|
|
3
|
+
import type { Clock } from '../shared/clock.js';
|
|
4
|
+
import type { Result } from '../shared/result.js';
|
|
5
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
6
|
+
import { type ReportTurnEndRefusal, type ReportTurnEndTx } from './report-turn-end.js';
|
|
7
|
+
export type ReportHandled = (crew: Crew, input: {
|
|
8
|
+
deliveryId: DeliveryId;
|
|
9
|
+
}) => Promise<Result<undefined, ReportTurnEndRefusal>>;
|
|
10
|
+
/**
|
|
11
|
+
* Use case: a pushed crew reports the turn that took an acknowledged
|
|
12
|
+
* delivery ended by itself (`handled`, decision 0040). Its scope
|
|
13
|
+
* (messages:receive) is checked before this runs. In one unit of work it
|
|
14
|
+
* holds the crew's lease, so a release waits for it, locks the delivery and
|
|
15
|
+
* moves it to handled with DeliveryHandled. Reporting it again is OK and
|
|
16
|
+
* changes nothing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createReportHandled(deps: {
|
|
19
|
+
uow: UnitOfWork<ReportTurnEndTx>;
|
|
20
|
+
clock: Clock;
|
|
21
|
+
ids: IdGenerator;
|
|
22
|
+
}): ReportHandled;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { reportTurnEnd } from './report-turn-end.js';
|
|
2
|
+
/**
|
|
3
|
+
* Use case: a pushed crew reports the turn that took an acknowledged
|
|
4
|
+
* delivery ended by itself (`handled`, decision 0040). Its scope
|
|
5
|
+
* (messages:receive) is checked before this runs. In one unit of work it
|
|
6
|
+
* holds the crew's lease, so a release waits for it, locks the delivery and
|
|
7
|
+
* moves it to handled with DeliveryHandled. Reporting it again is OK and
|
|
8
|
+
* changes nothing.
|
|
9
|
+
*/
|
|
10
|
+
export function createReportHandled(deps) {
|
|
11
|
+
return (crew, input) => deps.uow.run((tx) => reportTurnEnd({ tx, clock: deps.clock, ids: deps.ids }, { crew, ...input, end: 'handled' }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=report-handled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-handled.js","sourceRoot":"","sources":["../../../src/domain/messaging/report-handled.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAmD,MAAM,sBAAsB,CAAC;AAItG;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAA0E;IAC5G,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAC5I,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DeliveryId, IdGenerator } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Crew } from '../shared/caller.js';
|
|
3
|
+
import type { Clock } from '../shared/clock.js';
|
|
4
|
+
import type { Result } from '../shared/result.js';
|
|
5
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
6
|
+
import { type ReportTurnEndRefusal, type ReportTurnEndTx } from './report-turn-end.js';
|
|
7
|
+
export type ReportNotHandled = (crew: Crew, input: {
|
|
8
|
+
deliveryId: DeliveryId;
|
|
9
|
+
}) => Promise<Result<undefined, ReportTurnEndRefusal>>;
|
|
10
|
+
/**
|
|
11
|
+
* Use case: a pushed crew reports the turn a confirmed message was handed
|
|
12
|
+
* once more to died too (`notHandled`, decision 0040). Its scope
|
|
13
|
+
* (messages:receive) is checked before this runs. In one unit of work it
|
|
14
|
+
* holds the crew's lease, locks the delivery and moves it to not handled
|
|
15
|
+
* with DeliveryNotHandled, which puts it in Needs attention. Reporting it
|
|
16
|
+
* again is OK and changes nothing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createReportNotHandled(deps: {
|
|
19
|
+
uow: UnitOfWork<ReportTurnEndTx>;
|
|
20
|
+
clock: Clock;
|
|
21
|
+
ids: IdGenerator;
|
|
22
|
+
}): ReportNotHandled;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { reportTurnEnd } from './report-turn-end.js';
|
|
2
|
+
/**
|
|
3
|
+
* Use case: a pushed crew reports the turn a confirmed message was handed
|
|
4
|
+
* once more to died too (`notHandled`, decision 0040). Its scope
|
|
5
|
+
* (messages:receive) is checked before this runs. In one unit of work it
|
|
6
|
+
* holds the crew's lease, locks the delivery and moves it to not handled
|
|
7
|
+
* with DeliveryNotHandled, which puts it in Needs attention. Reporting it
|
|
8
|
+
* again is OK and changes nothing.
|
|
9
|
+
*/
|
|
10
|
+
export function createReportNotHandled(deps) {
|
|
11
|
+
return (crew, input) => deps.uow.run((tx) => reportTurnEnd({ tx, clock: deps.clock, ids: deps.ids }, { crew, ...input, end: 'notHandled' }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=report-not-handled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-not-handled.js","sourceRoot":"","sources":["../../../src/domain/messaging/report-not-handled.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAmD,MAAM,sBAAsB,CAAC;AAItG;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAA0E;IAC/G,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;AAC/I,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DeliveryId, IdGenerator } from '@aeolus-fleet/common';
|
|
2
|
+
import { type HoldLeaseTx, type LeaseEnded } from '../registry/public.js';
|
|
3
|
+
import type { Crew } from '../shared/caller.js';
|
|
4
|
+
import type { Clock } from '../shared/clock.js';
|
|
5
|
+
import { type DomainError } from '../shared/errors.js';
|
|
6
|
+
import { type EventLog } from '../shared/events.js';
|
|
7
|
+
import { type Result } from '../shared/result.js';
|
|
8
|
+
import { type TurnEnd, type TurnEndRefusal } from './delivery.js';
|
|
9
|
+
import type { DeliveryRepository } from './ports.js';
|
|
10
|
+
export interface ReportTurnEndTx extends HoldLeaseTx {
|
|
11
|
+
deliveries: Pick<DeliveryRepository, 'findForUpdate' | 'update'>;
|
|
12
|
+
events: EventLog;
|
|
13
|
+
}
|
|
14
|
+
export type ReportTurnEndRefusal = DomainError<'DELIVERY_NOT_FOUND'> | TurnEndRefusal | LeaseEnded;
|
|
15
|
+
/**
|
|
16
|
+
* The unit of work of handled and not handled, which differ only in how the
|
|
17
|
+
* turn ended: hold the crew's lease, so a release waits for it and an ended
|
|
18
|
+
* lease is refused; lock the delivery, so two reports take turns; apply the
|
|
19
|
+
* report and write its event.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reportTurnEnd(deps: {
|
|
22
|
+
tx: ReportTurnEndTx;
|
|
23
|
+
clock: Clock;
|
|
24
|
+
ids: IdGenerator;
|
|
25
|
+
}, report: {
|
|
26
|
+
crew: Crew;
|
|
27
|
+
deliveryId: DeliveryId;
|
|
28
|
+
end: TurnEnd;
|
|
29
|
+
}): Promise<Result<undefined, ReportTurnEndRefusal>>;
|