@epztickets/common 1.81.0 → 1.83.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/build/events/jetstream-listener.d.ts +6 -0
- package/build/events/jetstream-listener.js +38 -2
- package/build/events/order-reschedule-requested-event.d.ts +11 -0
- package/build/events/order-reschedule-requested-event.js +2 -0
- package/build/events/order-rescheduled-event.d.ts +25 -0
- package/build/events/order-rescheduled-event.js +2 -0
- package/build/events/subjects.d.ts +4 -0
- package/build/events/subjects.js +9 -0
- package/build/events/timelock-move-rejected-event.d.ts +9 -0
- package/build/events/timelock-move-rejected-event.js +2 -0
- package/build/events/timelock-moved-event.d.ts +11 -0
- package/build/events/timelock-moved-event.js +2 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +4 -0
- package/package.json +1 -1
|
@@ -13,6 +13,12 @@ export declare abstract class JetStreamListener<T extends Event> {
|
|
|
13
13
|
constructor(js: JetStreamClient, jsm: JetStreamManager);
|
|
14
14
|
listen(): Promise<void>;
|
|
15
15
|
private ensureConsumer;
|
|
16
|
+
/**
|
|
17
|
+
* Ask JetStream to redeliver this message later (NAK with backoff).
|
|
18
|
+
* Use for "not ready yet" (replica missing) and transient failures.
|
|
19
|
+
* Safe to call from handlers whose tests pass a bare { ack } mock.
|
|
20
|
+
*/
|
|
21
|
+
protected defer(msg: JsMsg, reason?: string): void;
|
|
16
22
|
abstract onMessage(data: T["data"], msg: JsMsg): Promise<void>;
|
|
17
23
|
}
|
|
18
24
|
export {};
|
|
@@ -18,6 +18,20 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.JetStreamListener = void 0;
|
|
20
20
|
const nats_1 = require("nats");
|
|
21
|
+
// Must match max_deliver in ensureConsumer below.
|
|
22
|
+
const MAX_DELIVER = 5;
|
|
23
|
+
// Retry backoff for defer(): 2s, 4s, 8s, 16s (capped at 30s).
|
|
24
|
+
const BASE_RETRY_MS = 2000;
|
|
25
|
+
const MAX_RETRY_MS = 30000;
|
|
26
|
+
// ACK CONTRACT for onMessage implementations:
|
|
27
|
+
// - Return normally → the message is ACKed (done, never redelivered).
|
|
28
|
+
// This is true even if you didn't call msg.ack() yourself.
|
|
29
|
+
// - Want a retry (replica not caught up, transient DB/SMTP error)?
|
|
30
|
+
// `return this.defer(msg)` — NAKs with backoff so JetStream
|
|
31
|
+
// redelivers. Just returning without msg.ack() does NOT retry.
|
|
32
|
+
// - Throwing also retries (the base class defers for you).
|
|
33
|
+
// After MAX_DELIVER attempts JetStream stops redelivering; defer()
|
|
34
|
+
// logs an error on the final attempt so a dropped event is visible.
|
|
21
35
|
class JetStreamListener {
|
|
22
36
|
constructor(js, jsm) {
|
|
23
37
|
this.js = js;
|
|
@@ -42,10 +56,13 @@ class JetStreamListener {
|
|
|
42
56
|
try {
|
|
43
57
|
const data = JSON.parse(msg.data.toString());
|
|
44
58
|
yield this.onMessage(data, msg);
|
|
59
|
+
// No-op if onMessage already acked or deferred (nats ignores a
|
|
60
|
+
// second ack/nak on the same message).
|
|
45
61
|
msg.ack();
|
|
46
62
|
}
|
|
47
63
|
catch (err) {
|
|
48
|
-
console.error(
|
|
64
|
+
console.error(`[${this.durableName}] Listener error`, err);
|
|
65
|
+
this.defer(msg);
|
|
49
66
|
}
|
|
50
67
|
}
|
|
51
68
|
}
|
|
@@ -72,10 +89,29 @@ class JetStreamListener {
|
|
|
72
89
|
filter_subject: this.subject,
|
|
73
90
|
ack_policy: nats_1.AckPolicy.Explicit,
|
|
74
91
|
deliver_policy: nats_1.DeliverPolicy.All,
|
|
75
|
-
max_deliver:
|
|
92
|
+
max_deliver: MAX_DELIVER,
|
|
76
93
|
});
|
|
77
94
|
}
|
|
78
95
|
});
|
|
79
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Ask JetStream to redeliver this message later (NAK with backoff).
|
|
99
|
+
* Use for "not ready yet" (replica missing) and transient failures.
|
|
100
|
+
* Safe to call from handlers whose tests pass a bare { ack } mock.
|
|
101
|
+
*/
|
|
102
|
+
defer(msg, reason) {
|
|
103
|
+
var _a, _b;
|
|
104
|
+
const attempt = (_b = (_a = msg === null || msg === void 0 ? void 0 : msg.info) === null || _a === void 0 ? void 0 : _a.deliveryCount) !== null && _b !== void 0 ? _b : 1;
|
|
105
|
+
const delayMs = Math.min(BASE_RETRY_MS * 2 ** (attempt - 1), MAX_RETRY_MS);
|
|
106
|
+
const why = reason ? ` (${reason})` : "";
|
|
107
|
+
if (attempt >= MAX_DELIVER) {
|
|
108
|
+
console.error(`[${this.durableName}] giving up on ${this.subject} after ${attempt} attempts${why} — event will NOT be redelivered`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.warn(`[${this.durableName}] deferring ${this.subject}${why}; attempt ${attempt}/${MAX_DELIVER}, retry in ${delayMs}ms`);
|
|
112
|
+
}
|
|
113
|
+
if (typeof (msg === null || msg === void 0 ? void 0 : msg.nak) === "function")
|
|
114
|
+
msg.nak(delayMs);
|
|
115
|
+
}
|
|
80
116
|
}
|
|
81
117
|
exports.JetStreamListener = JetStreamListener;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Subjects } from "./subjects";
|
|
2
|
+
export interface OrderRescheduleRequestedEvent {
|
|
3
|
+
subject: Subjects.OrderRescheduleRequested;
|
|
4
|
+
data: {
|
|
5
|
+
orderId: string;
|
|
6
|
+
requestId: string;
|
|
7
|
+
sellableUnitId: string;
|
|
8
|
+
startTime: string;
|
|
9
|
+
endTime: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Subjects } from "./subjects";
|
|
2
|
+
export interface OrderRescheduledEvent {
|
|
3
|
+
subject: Subjects.OrderRescheduled;
|
|
4
|
+
data: {
|
|
5
|
+
id: string;
|
|
6
|
+
version: number;
|
|
7
|
+
userId: string;
|
|
8
|
+
ownerUserId?: string;
|
|
9
|
+
selfBooking?: boolean;
|
|
10
|
+
sellableUnit: {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
roomId: string;
|
|
14
|
+
};
|
|
15
|
+
classTitle?: string;
|
|
16
|
+
timezone?: string;
|
|
17
|
+
previousStartTime: string;
|
|
18
|
+
previousEndTime: string;
|
|
19
|
+
startTime: string;
|
|
20
|
+
endTime: string;
|
|
21
|
+
price: number;
|
|
22
|
+
priceDelta: number;
|
|
23
|
+
rescheduledBy: "renter" | "owner" | "admin";
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -19,6 +19,10 @@ export declare enum Subjects {
|
|
|
19
19
|
OrderRefunded = "events.order.refunded",
|
|
20
20
|
OrderRefundFailed = "events.order.refund-failed",
|
|
21
21
|
OrderAwaitingPayment = "events.order.awaiting-payment",
|
|
22
|
+
OrderRescheduleRequested = "events.order.reschedule-requested",
|
|
23
|
+
OrderRescheduled = "events.order.rescheduled",
|
|
24
|
+
TimeLockMoved = "events.timelock.moved",
|
|
25
|
+
TimeLockMoveRejected = "events.timelock.move-rejected",
|
|
22
26
|
ExpirationComplete = "events.expiration.complete",
|
|
23
27
|
PaymentCreated = "events.payment.created",
|
|
24
28
|
OwnerApproved = "events.owner.approved",
|
package/build/events/subjects.js
CHANGED
|
@@ -36,6 +36,15 @@ var Subjects;
|
|
|
36
36
|
// OrderCancelled/Completed transitions and the Stripe charge route would
|
|
37
37
|
// have no way to refuse pre-confirmation payments.
|
|
38
38
|
Subjects["OrderAwaitingPayment"] = "events.order.awaiting-payment";
|
|
39
|
+
// Reschedule lifecycle (move a paid booking to a new time, same
|
|
40
|
+
// order). orders publishes Requested → inventory moves the
|
|
41
|
+
// TimeLock in place and replies Moved or MoveRejected → orders
|
|
42
|
+
// applies the change and publishes Rescheduled for downstream
|
|
43
|
+
// consumers (notifications: emails + reminder reset).
|
|
44
|
+
Subjects["OrderRescheduleRequested"] = "events.order.reschedule-requested";
|
|
45
|
+
Subjects["OrderRescheduled"] = "events.order.rescheduled";
|
|
46
|
+
Subjects["TimeLockMoved"] = "events.timelock.moved";
|
|
47
|
+
Subjects["TimeLockMoveRejected"] = "events.timelock.move-rejected";
|
|
39
48
|
Subjects["ExpirationComplete"] = "events.expiration.complete";
|
|
40
49
|
Subjects["PaymentCreated"] = "events.payment.created";
|
|
41
50
|
Subjects["OwnerApproved"] = "events.owner.approved";
|
package/build/index.d.ts
CHANGED
|
@@ -37,6 +37,10 @@ export * from "./events/order-cancelled-event";
|
|
|
37
37
|
export * from "./events/order-completed-event";
|
|
38
38
|
export * from "./events/order-created-event";
|
|
39
39
|
export * from "./events/order-awaiting-payment-event";
|
|
40
|
+
export * from "./events/order-reschedule-requested-event";
|
|
41
|
+
export * from "./events/order-rescheduled-event";
|
|
42
|
+
export * from "./events/timelock-moved-event";
|
|
43
|
+
export * from "./events/timelock-move-rejected-event";
|
|
40
44
|
export * from "./events/order-refund-requested-event";
|
|
41
45
|
export * from "./events/order-refunded-event";
|
|
42
46
|
export * from "./events/order-refund-failed-event";
|
package/build/index.js
CHANGED
|
@@ -57,6 +57,10 @@ __exportStar(require("./events/order-cancelled-event"), exports);
|
|
|
57
57
|
__exportStar(require("./events/order-completed-event"), exports);
|
|
58
58
|
__exportStar(require("./events/order-created-event"), exports);
|
|
59
59
|
__exportStar(require("./events/order-awaiting-payment-event"), exports);
|
|
60
|
+
__exportStar(require("./events/order-reschedule-requested-event"), exports);
|
|
61
|
+
__exportStar(require("./events/order-rescheduled-event"), exports);
|
|
62
|
+
__exportStar(require("./events/timelock-moved-event"), exports);
|
|
63
|
+
__exportStar(require("./events/timelock-move-rejected-event"), exports);
|
|
60
64
|
__exportStar(require("./events/order-refund-requested-event"), exports);
|
|
61
65
|
__exportStar(require("./events/order-refunded-event"), exports);
|
|
62
66
|
__exportStar(require("./events/order-refund-failed-event"), exports);
|