@pg-prime/events 0.0.0 → 0.2.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/LICENSE +373 -0
- package/README.md +42 -1
- package/dist/channel.d.ts +19 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +51 -0
- package/dist/channel.js.map +1 -0
- package/dist/define.d.ts +49 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +39 -0
- package/dist/define.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +57 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +99 -0
- package/dist/events.js.map +1 -0
- package/dist/hooks.d.ts +40 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +27 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/log/cursor.d.ts +37 -0
- package/dist/log/cursor.d.ts.map +1 -0
- package/dist/log/cursor.js +58 -0
- package/dist/log/cursor.js.map +1 -0
- package/dist/log/migrations.d.ts +3 -0
- package/dist/log/migrations.d.ts.map +1 -0
- package/dist/log/migrations.js +55 -0
- package/dist/log/migrations.js.map +1 -0
- package/dist/log/sql.d.ts +68 -0
- package/dist/log/sql.d.ts.map +1 -0
- package/dist/log/sql.js +251 -0
- package/dist/log/sql.js.map +1 -0
- package/dist/log/subscription.d.ts +53 -0
- package/dist/log/subscription.d.ts.map +1 -0
- package/dist/log/subscription.js +272 -0
- package/dist/log/subscription.js.map +1 -0
- package/dist/log/topic.d.ts +48 -0
- package/dist/log/topic.d.ts.map +1 -0
- package/dist/log/topic.js +111 -0
- package/dist/log/topic.js.map +1 -0
- package/dist/payload.d.ts +40 -0
- package/dist/payload.d.ts.map +1 -0
- package/dist/payload.js +53 -0
- package/dist/payload.js.map +1 -0
- package/dist/unsupported-typescript.d.ts +70 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +31 -0
- package/dist/util.js.map +1 -0
- package/dist/waker.d.ts +22 -0
- package/dist/waker.d.ts.map +1 -0
- package/dist/waker.js +86 -0
- package/dist/waker.js.map +1 -0
- package/package.json +49 -3
package/dist/log/sql.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { sql } from 'pg-prime';
|
|
2
|
+
const run = (q, label, f) => q.withOptions({ label: `events.${label}` }).sql `${f}`.execute();
|
|
3
|
+
/** For statements that always return one row (aggregates). */
|
|
4
|
+
const one = async (q, label, f) => (await run(q, label, f))[0];
|
|
5
|
+
const ENTRY = sql `id, xid::text as xid, type, key, payload, headers, at`;
|
|
6
|
+
function entryRow(r) {
|
|
7
|
+
return {
|
|
8
|
+
id: r['id'],
|
|
9
|
+
xid: BigInt(r['xid']),
|
|
10
|
+
type: r['type'],
|
|
11
|
+
key: r['key'],
|
|
12
|
+
payload: r['payload'],
|
|
13
|
+
headers: r['headers'],
|
|
14
|
+
at: r['at'],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const xids = (c) => [...c.pending.keys()].map(String);
|
|
18
|
+
const afters = (c) => [...c.pending.values()];
|
|
19
|
+
function cursorOf(r) {
|
|
20
|
+
const p = r['pending'].map(BigInt);
|
|
21
|
+
const a = r['pending_after'];
|
|
22
|
+
return {
|
|
23
|
+
xid: BigInt(r['last_xid']),
|
|
24
|
+
id: r['last_id'],
|
|
25
|
+
pending: new Map(p.map((x, i) => [x, a[i]])),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function statements(schema) {
|
|
29
|
+
const entries = sql.ident(schema, 'entries');
|
|
30
|
+
const topics = sql.ident(schema, 'topics');
|
|
31
|
+
const subs = sql.ident(schema, 'subscriptions');
|
|
32
|
+
const parked = sql.ident(schema, 'parked');
|
|
33
|
+
const setCursor = (c) => sql `last_xid = ${String(c.xid)}::xid8, last_id = ${c.id}::bigint,
|
|
34
|
+
pending = ${xids(c)}::xid8[], pending_after = ${afters(c)}::bigint[]`;
|
|
35
|
+
const guard = (t, s, token) => sql `topic = ${t} and name = ${s} and token = ${token}`;
|
|
36
|
+
return {
|
|
37
|
+
async publish(q, topic, channel, rows) {
|
|
38
|
+
const json = `[${rows
|
|
39
|
+
.map((r) => `{"type":${JSON.stringify(r.type)},"key":${JSON.stringify(r.key)},` +
|
|
40
|
+
`"headers":${JSON.stringify(r.headers)},"payload":${r.payload}}`)
|
|
41
|
+
.join(',')}]`;
|
|
42
|
+
const r = await one(q, 'publish', sql `with e as (
|
|
43
|
+
insert into ${entries} (topic, type, key, payload, headers)
|
|
44
|
+
select ${topic}, r.type, r.key, coalesce(r.payload, 'null'::jsonb), r.headers
|
|
45
|
+
from rows from (jsonb_to_recordset(${json}::jsonb)
|
|
46
|
+
as (type text, key text, payload jsonb, headers jsonb)) with ordinality as r(type, key, payload, headers, n)
|
|
47
|
+
order by r.n
|
|
48
|
+
returning id
|
|
49
|
+
)
|
|
50
|
+
select array_agg(id order by id) as ids,
|
|
51
|
+
(select pg_notify(${channel}, '') where exists (select from e)) is not null as woke
|
|
52
|
+
from e`);
|
|
53
|
+
return r['ids'];
|
|
54
|
+
},
|
|
55
|
+
async seedNow(q) {
|
|
56
|
+
const r = await one(q, 'seed', sql `select pg_snapshot_xmax(s)::text as xmax, array(select pg_snapshot_xip(s))::text[] as xip
|
|
57
|
+
from pg_current_snapshot() s`);
|
|
58
|
+
return { xmax: BigInt(r['xmax']), xip: r['xip'].map(BigInt) };
|
|
59
|
+
},
|
|
60
|
+
async upsertTopic(q, name, keepMs, untilConsumed) {
|
|
61
|
+
await run(q, 'topic', sql `insert into ${topics} (name, keep_ms, keep_until_consumed)
|
|
62
|
+
values (${name}, ${keepMs}::bigint, ${untilConsumed})
|
|
63
|
+
on conflict (name) do update set keep_ms = excluded.keep_ms,
|
|
64
|
+
keep_until_consumed = excluded.keep_until_consumed`);
|
|
65
|
+
},
|
|
66
|
+
async upsertSubscription(q, t, s, types, c) {
|
|
67
|
+
await run(q, 'subscription', sql `insert into ${subs} (topic, name, types, last_xid, last_id, pending, pending_after)
|
|
68
|
+
values (${t}, ${s}, ${types}::text[], ${String(c.xid)}::xid8, ${c.id}::bigint,
|
|
69
|
+
${xids(c)}::xid8[], ${afters(c)}::bigint[])
|
|
70
|
+
on conflict (topic, name) do update set types = excluded.types`);
|
|
71
|
+
},
|
|
72
|
+
async lease(q, t, s, leaseMs) {
|
|
73
|
+
const [r] = await run(q, 'lease', sql `update ${subs} set token = gen_random_uuid()::text,
|
|
74
|
+
lease_until = now() + ${leaseMs}::bigint * interval '1 ms'
|
|
75
|
+
where topic = ${t} and name = ${s} and (token is null or lease_until < now())
|
|
76
|
+
returning token, last_xid::text as last_xid, last_id, pending::text[] as pending,
|
|
77
|
+
pending_after, types, head_id, head_size,
|
|
78
|
+
greatest(0, extract(epoch from head_retry_at - now()) * 1000)::float8 as retry_in`);
|
|
79
|
+
if (r === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
return {
|
|
82
|
+
token: r['token'],
|
|
83
|
+
cursor: cursorOf(r),
|
|
84
|
+
types: r['types'],
|
|
85
|
+
headId: r['head_id'],
|
|
86
|
+
headSize: r['head_size'],
|
|
87
|
+
retryInMs: r['retry_in'] ?? 0,
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
async heartbeat(q, t, s, token, leaseMs) {
|
|
91
|
+
const rows = await run(q, 'heartbeat', sql `update ${subs} set lease_until = now() + ${leaseMs}::bigint * interval '1 ms'
|
|
92
|
+
where ${guard(t, s, token)} returning 1`);
|
|
93
|
+
return rows.length === 1;
|
|
94
|
+
},
|
|
95
|
+
async release(q, t, s, token) {
|
|
96
|
+
await run(q, 'release', sql `update ${subs} set token = null, lease_until = null where ${guard(t, s, token)}`);
|
|
97
|
+
},
|
|
98
|
+
async read(q, t, c, n, types) {
|
|
99
|
+
const rows = await run(q, 'read', sql `with late as (
|
|
100
|
+
select e.* from unnest(${xids(c)}::xid8[], ${afters(c)}::bigint[]) as p(xid, after)
|
|
101
|
+
cross join lateral (
|
|
102
|
+
select * from ${entries} e
|
|
103
|
+
where e.topic = ${t} and e.xid = p.xid and e.id > p.after
|
|
104
|
+
order by e.id limit ${n}::int
|
|
105
|
+
) e
|
|
106
|
+
order by e.xid, e.id limit ${n}::int
|
|
107
|
+
), next as (
|
|
108
|
+
select * from ${entries}
|
|
109
|
+
where topic = ${t} and (xid, id) > (${String(c.xid)}::xid8, ${c.id}::bigint)
|
|
110
|
+
order by xid, id limit ${n}::int - (select count(*) from late)
|
|
111
|
+
), pos as (
|
|
112
|
+
select xid, id from next order by xid desc, id desc limit 1
|
|
113
|
+
), cut as (
|
|
114
|
+
select xid, id from late order by xid, id offset ${n}::int - 1
|
|
115
|
+
)
|
|
116
|
+
select (select xid from pos)::text as pos_xid, (select id from pos) as pos_id,
|
|
117
|
+
(select xid from cut)::text as late_xid, (select id from cut) as late_id,
|
|
118
|
+
array(select pg_snapshot_xip(pg_current_snapshot()))::text[] as running,
|
|
119
|
+
x.id, x.xid::text as xid, x.type, x.key, x.payload, x.headers, x.at
|
|
120
|
+
from (select) m
|
|
121
|
+
left join (select * from late union all select * from next) x
|
|
122
|
+
on ${types}::text[] is null or x.type = any(${types}::text[])
|
|
123
|
+
order by x.xid, x.id`);
|
|
124
|
+
const head = rows[0];
|
|
125
|
+
const at = (x) => head[`${x}_xid`] === null
|
|
126
|
+
? null
|
|
127
|
+
: { xid: BigInt(head[`${x}_xid`]), id: head[`${x}_id`] };
|
|
128
|
+
return {
|
|
129
|
+
view: {
|
|
130
|
+
pos: at('pos'),
|
|
131
|
+
late: at('late'),
|
|
132
|
+
running: head['running'].map(BigInt),
|
|
133
|
+
},
|
|
134
|
+
rows: head['id'] === null ? [] : rows.map(entryRow),
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
async mark(q, t, s, token, first, size) {
|
|
138
|
+
const [r] = await run(q, 'attempt', sql `update ${subs} set head_id = ${first}::bigint, head_size = ${size}::int,
|
|
139
|
+
head_attempts = case when ${size}::int > 1 then 0
|
|
140
|
+
when head_id = ${first}::bigint and head_size = 1 then head_attempts + 1
|
|
141
|
+
else 1 end
|
|
142
|
+
where ${guard(t, s, token)}
|
|
143
|
+
returning head_attempts`);
|
|
144
|
+
return r?.['head_attempts'];
|
|
145
|
+
},
|
|
146
|
+
async commit(q, t, s, token, c) {
|
|
147
|
+
const rows = await run(q, 'commit', sql `update ${subs} set ${setCursor(c)}, head_id = null, head_size = 0, head_attempts = 0,
|
|
148
|
+
head_retry_at = null, updated_at = now()
|
|
149
|
+
where ${guard(t, s, token)} returning 1`);
|
|
150
|
+
return rows.length === 1;
|
|
151
|
+
},
|
|
152
|
+
async stored(q, t, s, token) {
|
|
153
|
+
const [r] = await run(q, 'stored', sql `select last_xid::text as last_xid, last_id, pending::text[] as pending, pending_after
|
|
154
|
+
from ${subs} where ${guard(t, s, token)} for share`);
|
|
155
|
+
return r === undefined ? undefined : cursorOf(r);
|
|
156
|
+
},
|
|
157
|
+
async nack(q, t, s, token, delayMs) {
|
|
158
|
+
const rows = await run(q, 'nack', sql `update ${subs} set head_retry_at = now() + ${delayMs}::float8 * interval '1 ms'
|
|
159
|
+
where ${guard(t, s, token)} returning 1`);
|
|
160
|
+
return rows.length === 1;
|
|
161
|
+
},
|
|
162
|
+
async park(q, t, s, token, c, entry, attempts, error) {
|
|
163
|
+
const rows = await run(q, 'park', sql `with c as (
|
|
164
|
+
update ${subs} set ${setCursor(c)}, head_id = null, head_size = 0, head_attempts = 0,
|
|
165
|
+
head_retry_at = null, updated_at = now()
|
|
166
|
+
where ${guard(t, s, token)}
|
|
167
|
+
returning topic, name
|
|
168
|
+
)
|
|
169
|
+
insert into ${parked} (topic, subscription, entry, attempts, error)
|
|
170
|
+
select topic, name, ${entry}::bigint, ${attempts}::int, ${error}::text from c
|
|
171
|
+
on conflict (topic, subscription, entry) do update set attempts = excluded.attempts,
|
|
172
|
+
error = excluded.error, parked_at = clock_timestamp()
|
|
173
|
+
returning 1`);
|
|
174
|
+
return rows.length === 1;
|
|
175
|
+
},
|
|
176
|
+
async maintain(q, t, everyMs) {
|
|
177
|
+
const [gate] = await run(q, 'maintain', sql `update ${topics} set maint_at = now()
|
|
178
|
+
where name = ${t} and keep_ms is not null
|
|
179
|
+
and maint_at < now() - ${everyMs}::bigint * interval '1 ms'
|
|
180
|
+
returning keep_ms, keep_until_consumed`);
|
|
181
|
+
if (gate === undefined)
|
|
182
|
+
return { deleted: 0, behind: false };
|
|
183
|
+
let deleted = 0;
|
|
184
|
+
let behind = false;
|
|
185
|
+
for (;;) {
|
|
186
|
+
const r = await one(q, 'retention', sql `with d as (
|
|
187
|
+
delete from ${entries} where id in (
|
|
188
|
+
select id from ${entries} e
|
|
189
|
+
where e.topic = ${t} and e.at < now() - ${gate['keep_ms']}::bigint * interval '1 ms'
|
|
190
|
+
and not exists (select from ${parked} p where p.topic = ${t} and p.entry = e.id)
|
|
191
|
+
and (not ${gate['keep_until_consumed']}::boolean or not exists (
|
|
192
|
+
select from ${subs} s where s.topic = ${t}
|
|
193
|
+
and ((e.xid, e.id) > (s.last_xid, s.last_id) or e.xid = any(s.pending))))
|
|
194
|
+
order by id limit 1000)
|
|
195
|
+
returning xid, id
|
|
196
|
+
)
|
|
197
|
+
select count(*)::int as n, exists (select from d join ${subs} s on s.topic = ${t}
|
|
198
|
+
and ((d.xid, d.id) > (s.last_xid, s.last_id) or d.xid = any(s.pending))) as behind
|
|
199
|
+
from d`);
|
|
200
|
+
deleted += r['n'];
|
|
201
|
+
behind ||= r['behind'] === true;
|
|
202
|
+
if (r['n'] < 1000)
|
|
203
|
+
return { deleted, behind };
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
async reset(q, t, s, c) {
|
|
207
|
+
const rows = await run(q, 'reset', sql `update ${subs} set ${setCursor(c)}, head_id = null, head_size = 0, head_attempts = 0,
|
|
208
|
+
head_retry_at = null, token = null, lease_until = null, updated_at = now()
|
|
209
|
+
where topic = ${t} and name = ${s} returning 1`);
|
|
210
|
+
return rows.length === 1;
|
|
211
|
+
},
|
|
212
|
+
async lag(q, t, s) {
|
|
213
|
+
const r = await one(q, 'lag', sql `select count(e.id)::int as n, min(e.at) as oldest
|
|
214
|
+
from ${subs} s join ${entries} e on e.topic = s.topic
|
|
215
|
+
and ((e.xid, e.id) > (s.last_xid, s.last_id)
|
|
216
|
+
or exists (select from unnest(s.pending, s.pending_after) p(xid, after)
|
|
217
|
+
where p.xid = e.xid and e.id > p.after))
|
|
218
|
+
and (s.types is null or e.type = any(s.types))
|
|
219
|
+
where s.topic = ${t} and s.name = ${s}`);
|
|
220
|
+
return {
|
|
221
|
+
entries: r['n'],
|
|
222
|
+
oldestAt: r['oldest'],
|
|
223
|
+
};
|
|
224
|
+
},
|
|
225
|
+
async parked(q, t, s, limit) {
|
|
226
|
+
const rows = await run(q, 'parked', sql `select ${ENTRY}, p.attempts, p.error
|
|
227
|
+
from ${parked} p join ${entries} e on e.id = p.entry
|
|
228
|
+
where p.topic = ${t} and p.subscription = ${s}
|
|
229
|
+
order by p.entry limit ${limit}::int`);
|
|
230
|
+
return rows.map((r) => ({
|
|
231
|
+
...entryRow(r),
|
|
232
|
+
attempts: r['attempts'],
|
|
233
|
+
error: r['error'],
|
|
234
|
+
}));
|
|
235
|
+
},
|
|
236
|
+
async discard(q, t, s, ids) {
|
|
237
|
+
const rows = await run(q, 'discard', sql `delete from ${parked} where topic = ${t} and subscription = ${s}
|
|
238
|
+
and entry = any(${ids}::bigint[]) returning 1`);
|
|
239
|
+
return rows.length;
|
|
240
|
+
},
|
|
241
|
+
async remove(q, t, s) {
|
|
242
|
+
await run(q, 'remove', sql `delete from ${subs} where topic = ${t} and name = ${s}`);
|
|
243
|
+
},
|
|
244
|
+
async browse(q, t, afterId, limit) {
|
|
245
|
+
const rows = await run(q, 'browse', sql `select ${ENTRY} from ${entries}
|
|
246
|
+
where topic = ${t} and id > ${afterId}::bigint order by id limit ${limit}::int`);
|
|
247
|
+
return rows.map(entryRow);
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=sql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/log/sql.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AsyncDisposable_, Queryable } from 'pg-prime';
|
|
2
|
+
import type { SubscriptionDef } from '../define.js';
|
|
3
|
+
import type { Core } from '../events.js';
|
|
4
|
+
import type { Entry } from './topic.js';
|
|
5
|
+
export interface ReadContext {
|
|
6
|
+
readonly signal: AbortSignal;
|
|
7
|
+
/** 1-based count of attempts at this entry; a multi-entry batch reports 1. */
|
|
8
|
+
readonly attempt: number;
|
|
9
|
+
/**
|
|
10
|
+
* Commits the offset inside your transaction: exactly-once effects for same-database sinks.
|
|
11
|
+
* Once that transaction commits, a later throw does not redeliver what it covered.
|
|
12
|
+
*/
|
|
13
|
+
commit(opts: {
|
|
14
|
+
tx: Queryable<any>;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export type EntryHandler<T> = (e: Entry<T>, ctx: ReadContext) => Promise<void>;
|
|
18
|
+
export type BatchHandler<T> = {
|
|
19
|
+
batch: (es: readonly Entry<T>[], ctx: ReadContext) => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
export interface Reader extends AsyncDisposable_ {
|
|
22
|
+
/** True while this reader holds the subscription's lease. */
|
|
23
|
+
readonly active: boolean;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export interface RunOptions {
|
|
27
|
+
batchSize?: number;
|
|
28
|
+
leaseMs?: number;
|
|
29
|
+
pollMs?: number;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
export interface SubscriptionHandle<T> {
|
|
33
|
+
run(handler: EntryHandler<T> | BatchHandler<T>, opts?: RunOptions): Reader;
|
|
34
|
+
/** Moves the cursor and drops the current lease; `after` takes an `Entry.cursor`. */
|
|
35
|
+
reset(to: 'beginning' | 'now' | {
|
|
36
|
+
after: string;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
lag(): Promise<{
|
|
39
|
+
entries: number;
|
|
40
|
+
oldestAt: Date | null;
|
|
41
|
+
}>;
|
|
42
|
+
parked(opts?: {
|
|
43
|
+
limit?: number;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
entry: Omit<Entry<T>, 'cursor'>;
|
|
46
|
+
attempts: number;
|
|
47
|
+
error: string | null;
|
|
48
|
+
}[]>;
|
|
49
|
+
discard(entryIds: readonly bigint[]): Promise<number>;
|
|
50
|
+
remove(): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export declare function subscriptionHandle<T>(core: Core, def: SubscriptionDef<T>): SubscriptionHandle<T>;
|
|
53
|
+
//# sourceMappingURL=subscription.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/log/subscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAQxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD;AACD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAC9E,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpE,CAAA;AACD,MAAM,WAAW,MAAO,SAAQ,gBAAgB;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AACD,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAC1E,qFAAqF;IACrF,KAAK,CAAC,EAAE,EAAE,WAAW,GAAG,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,GAAG,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;IAC1D,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CACxC;QACE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;QAC/B,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,EAAE,CACJ,CAAA;IACD,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACrD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAID,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAwChG"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { EventsLeaseLostError } from '../errors.js';
|
|
2
|
+
import { ASYNC_DISPOSE, backoffMs, sleep } from '../util.js';
|
|
3
|
+
import { waker } from '../waker.js';
|
|
4
|
+
import { BEGINNING, advance, advanceTo, decodeCursor, encodeCursor, seed } from './cursor.js';
|
|
5
|
+
import { entryOf } from './topic.js';
|
|
6
|
+
const MAINTENANCE_MS = 60_000;
|
|
7
|
+
export function subscriptionHandle(core, def) {
|
|
8
|
+
const t = def.topic.name;
|
|
9
|
+
const s = def.name;
|
|
10
|
+
return {
|
|
11
|
+
run: (handler, opts = {}) => startReader(core, def, handler, opts),
|
|
12
|
+
async reset(to) {
|
|
13
|
+
await core.ready(def);
|
|
14
|
+
const c = to === 'beginning'
|
|
15
|
+
? BEGINNING
|
|
16
|
+
: to === 'now'
|
|
17
|
+
? await core.sql.seedNow(core.db).then((x) => seed(x.xmax, x.xip))
|
|
18
|
+
: decodeCursor(to.after);
|
|
19
|
+
await core.sql.reset(core.db, t, s, c);
|
|
20
|
+
},
|
|
21
|
+
async lag() {
|
|
22
|
+
await core.ready(def);
|
|
23
|
+
return core.sql.lag(core.db, t, s);
|
|
24
|
+
},
|
|
25
|
+
async parked(opts = {}) {
|
|
26
|
+
await core.ready(def);
|
|
27
|
+
const rows = await core.sql.parked(core.db, t, s, opts.limit ?? 100);
|
|
28
|
+
return Promise.all(rows.map(async (r) => ({
|
|
29
|
+
entry: await entryOf(def.topic, r),
|
|
30
|
+
attempts: r.attempts,
|
|
31
|
+
error: r.error,
|
|
32
|
+
})));
|
|
33
|
+
},
|
|
34
|
+
async discard(ids) {
|
|
35
|
+
await core.ready(def);
|
|
36
|
+
return ids.length === 0 ? 0 : core.sql.discard(core.db, t, s, ids);
|
|
37
|
+
},
|
|
38
|
+
async remove() {
|
|
39
|
+
await core.ready(def);
|
|
40
|
+
await core.sql.remove(core.db, t, s);
|
|
41
|
+
core.forget(def);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function startReader(core, def, handler, opts) {
|
|
46
|
+
const { db, sql, hooks } = core;
|
|
47
|
+
const t = def.topic.name;
|
|
48
|
+
const s = def.name;
|
|
49
|
+
const batchSize = opts.batchSize ?? 100;
|
|
50
|
+
const leaseMs = opts.leaseMs ?? 30_000;
|
|
51
|
+
const pollMs = opts.pollMs ?? 5000;
|
|
52
|
+
const stop = new AbortController();
|
|
53
|
+
opts.signal?.addEventListener('abort', () => stop.abort(), { once: true });
|
|
54
|
+
if (opts.signal?.aborted === true)
|
|
55
|
+
stop.abort();
|
|
56
|
+
let active = false;
|
|
57
|
+
let lastError;
|
|
58
|
+
let nextMaintenance = 0;
|
|
59
|
+
const lostError = () => new EventsLeaseLostError(`@pg-prime/events: subscription ${t}/${s} lost its lease to another reader.`);
|
|
60
|
+
async function serve(lease, wake) {
|
|
61
|
+
const token = lease.token;
|
|
62
|
+
let cursor = lease.cursor;
|
|
63
|
+
// A marker still set at takeover means an attempt crashed or was nacked: retry its entries one by one.
|
|
64
|
+
let isolate = lease.headId === null ? 0 : lease.headSize;
|
|
65
|
+
const held = { lost: false };
|
|
66
|
+
const handlerStop = new AbortController();
|
|
67
|
+
const onStop = () => handlerStop.abort();
|
|
68
|
+
stop.signal.addEventListener('abort', onStop, { once: true });
|
|
69
|
+
let beating = false;
|
|
70
|
+
const heartbeat = setInterval(() => {
|
|
71
|
+
if (beating)
|
|
72
|
+
return;
|
|
73
|
+
beating = true;
|
|
74
|
+
sql
|
|
75
|
+
.heartbeat(db, t, s, token, leaseMs)
|
|
76
|
+
.then((ok) => {
|
|
77
|
+
if (ok)
|
|
78
|
+
return;
|
|
79
|
+
held.lost = true;
|
|
80
|
+
handlerStop.abort();
|
|
81
|
+
})
|
|
82
|
+
.catch((e) => hooks.internal('heartbeat-failed', `@pg-prime/events: heartbeat of ${t}/${s} failed.`, e))
|
|
83
|
+
.finally(() => (beating = false));
|
|
84
|
+
}, leaseMs / 3);
|
|
85
|
+
const commit = async (c) => {
|
|
86
|
+
if (!(await sql.commit(db, t, s, token, c)))
|
|
87
|
+
throw lostError();
|
|
88
|
+
cursor = c;
|
|
89
|
+
};
|
|
90
|
+
/** Runs one attempt over `rows`, the first `rows.length` matching entries of `view`. */
|
|
91
|
+
const attempt = async (rows, view, whole) => {
|
|
92
|
+
const first = rows[0];
|
|
93
|
+
const attempts = await sql.mark(db, t, s, token, first.id, rows.length);
|
|
94
|
+
if (attempts === undefined)
|
|
95
|
+
throw lostError();
|
|
96
|
+
const cursors = [];
|
|
97
|
+
for (const r of rows)
|
|
98
|
+
cursors.push(advance(cursors.at(-1) ?? cursor, view, r));
|
|
99
|
+
if (whole)
|
|
100
|
+
cursors.push(advanceTo(cursors.pop(), view));
|
|
101
|
+
if (rows.length === 1 && attempts > def.retry.maxAttempts) {
|
|
102
|
+
const error = lastError?.id === first.id ? lastError.error : null;
|
|
103
|
+
const c = cursors[0];
|
|
104
|
+
if (!(await sql.park(db, t, s, token, c, first.id, attempts - 1, error)))
|
|
105
|
+
throw lostError();
|
|
106
|
+
cursor = c;
|
|
107
|
+
isolate = Math.max(0, isolate - 1);
|
|
108
|
+
hooks.emit('onPark', { topic: t, subscription: s, entry: first.id, error });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
let committed;
|
|
112
|
+
const ctx = (c) => ({
|
|
113
|
+
signal: handlerStop.signal,
|
|
114
|
+
attempt: Math.max(1, attempts),
|
|
115
|
+
async commit({ tx }) {
|
|
116
|
+
if (!(await sql.commit(tx, t, s, token, c))) {
|
|
117
|
+
// The handler may swallow the error; held.lost still ends the batch.
|
|
118
|
+
held.lost = true;
|
|
119
|
+
handlerStop.abort();
|
|
120
|
+
throw lostError();
|
|
121
|
+
}
|
|
122
|
+
committed = encodeCursor(c);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const started = Date.now();
|
|
126
|
+
let done = 0;
|
|
127
|
+
let failure;
|
|
128
|
+
try {
|
|
129
|
+
const es = await Promise.all(rows.map(async (r, i) => ({
|
|
130
|
+
...(await entryOf(def.topic, r)),
|
|
131
|
+
cursor: encodeCursor(cursors[i]),
|
|
132
|
+
})));
|
|
133
|
+
if (typeof handler === 'function') {
|
|
134
|
+
for (const [i, e] of es.entries()) {
|
|
135
|
+
// Only a lost lease cuts a batch short; close() still holds it and lets the batch finish.
|
|
136
|
+
if (held.lost)
|
|
137
|
+
throw lostError();
|
|
138
|
+
await handler(e, ctx(cursors[i]));
|
|
139
|
+
done = i + 1;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
await handler.batch(es, ctx(cursors.at(-1)));
|
|
144
|
+
done = es.length;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
failure = { error };
|
|
149
|
+
}
|
|
150
|
+
if (failure !== undefined && committed !== undefined) {
|
|
151
|
+
// The handler's transaction may or may not have committed; the stored cursor says which.
|
|
152
|
+
const stored = await sql.stored(db, t, s, token);
|
|
153
|
+
if (stored === undefined)
|
|
154
|
+
throw lostError();
|
|
155
|
+
committed = encodeCursor(stored);
|
|
156
|
+
done = Math.max(done, cursors.findIndex((c) => encodeCursor(c) === committed) + 1);
|
|
157
|
+
}
|
|
158
|
+
if (done > 0) {
|
|
159
|
+
const c = cursors[done - 1];
|
|
160
|
+
if (encodeCursor(c) === committed)
|
|
161
|
+
cursor = c;
|
|
162
|
+
else
|
|
163
|
+
await commit(c);
|
|
164
|
+
hooks.emit('onDeliver', {
|
|
165
|
+
topic: t,
|
|
166
|
+
subscription: s,
|
|
167
|
+
count: done,
|
|
168
|
+
durationMs: Date.now() - started,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (failure === undefined || done === rows.length) {
|
|
172
|
+
isolate = Math.max(0, isolate - done);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (rows.length > 1) {
|
|
176
|
+
// A batch failure is never charged: retry the rest one entry at a time.
|
|
177
|
+
isolate = rows.length - done;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (held.lost)
|
|
181
|
+
throw lostError();
|
|
182
|
+
lastError = { id: first.id, error: String(failure.error) };
|
|
183
|
+
// The next attempt must be this entry alone, or a larger batch would reset its count.
|
|
184
|
+
isolate = Math.max(isolate, 1);
|
|
185
|
+
const delay = backoffMs(def.retry, attempts);
|
|
186
|
+
if (!(await sql.nack(db, t, s, token, delay)))
|
|
187
|
+
throw lostError();
|
|
188
|
+
hooks.emit('onRetry', {
|
|
189
|
+
topic: t,
|
|
190
|
+
subscription: s,
|
|
191
|
+
entry: first.id,
|
|
192
|
+
attempt: attempts,
|
|
193
|
+
error: failure.error,
|
|
194
|
+
});
|
|
195
|
+
await sleep(delay, stop.signal);
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
active = true;
|
|
199
|
+
if (lease.retryInMs > 0)
|
|
200
|
+
await sleep(lease.retryInMs, stop.signal);
|
|
201
|
+
while (!stop.signal.aborted) {
|
|
202
|
+
if (held.lost)
|
|
203
|
+
throw lostError();
|
|
204
|
+
if (Date.now() >= nextMaintenance) {
|
|
205
|
+
nextMaintenance = Date.now() + MAINTENANCE_MS;
|
|
206
|
+
const m = await sql.maintain(db, t, MAINTENANCE_MS);
|
|
207
|
+
if (m.behind) {
|
|
208
|
+
hooks.internal('subscription-behind-retention', `@pg-prime/events: retention on ${t} removed entries a subscription had not read; ` +
|
|
209
|
+
`it continues from the oldest surviving entry. Use keepUntilConsumed to prevent this.`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const { view, rows } = await sql.read(db, t, cursor, isolate > 0 ? 1 : batchSize, def.types);
|
|
213
|
+
if (rows.length === 0) {
|
|
214
|
+
const c = advanceTo(cursor, view);
|
|
215
|
+
if (encodeCursor(c) !== encodeCursor(cursor))
|
|
216
|
+
await commit(c);
|
|
217
|
+
else
|
|
218
|
+
await wake.wait();
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const batch = isolate > 0 ? rows.slice(0, 1) : rows;
|
|
222
|
+
await attempt(batch, view, batch.length === rows.length);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
active = false;
|
|
227
|
+
clearInterval(heartbeat);
|
|
228
|
+
stop.signal.removeEventListener('abort', onStop);
|
|
229
|
+
if (!held.lost)
|
|
230
|
+
await sql.release(db, t, s, token).catch(() => { });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const loop = (async () => {
|
|
234
|
+
const wake = waker(db, core.topicChannel(t), {
|
|
235
|
+
pollMs,
|
|
236
|
+
signal: stop.signal,
|
|
237
|
+
onInternal: (e) => hooks.emit('onInternal', e),
|
|
238
|
+
});
|
|
239
|
+
while (!stop.signal.aborted) {
|
|
240
|
+
try {
|
|
241
|
+
await core.ready(def);
|
|
242
|
+
const lease = await sql.lease(db, t, s, leaseMs);
|
|
243
|
+
if (lease === undefined)
|
|
244
|
+
await sleep(leaseMs / 2, stop.signal);
|
|
245
|
+
else
|
|
246
|
+
await serve(lease, wake);
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
if (e instanceof EventsLeaseLostError)
|
|
250
|
+
continue;
|
|
251
|
+
hooks.internal('reader-failed', `@pg-prime/events: reader ${t}/${s} failed; retrying.`, e);
|
|
252
|
+
await sleep(pollMs, stop.signal);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
await wake.close();
|
|
256
|
+
})();
|
|
257
|
+
const close = async () => {
|
|
258
|
+
stop.abort();
|
|
259
|
+
await loop;
|
|
260
|
+
core.running.delete(reader);
|
|
261
|
+
};
|
|
262
|
+
const reader = {
|
|
263
|
+
get active() {
|
|
264
|
+
return active;
|
|
265
|
+
},
|
|
266
|
+
close,
|
|
267
|
+
[ASYNC_DISPOSE]: close,
|
|
268
|
+
};
|
|
269
|
+
core.running.add(reader);
|
|
270
|
+
return reader;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=subscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/log/subscription.ts"],"names":[],"mappings":"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"}
|