@cogitator-ai/channels 0.9.3 → 0.10.1

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 (102) hide show
  1. package/README.md +101 -11
  2. package/dist/assistant-config.d.ts +16 -0
  3. package/dist/assistant-config.d.ts.map +1 -1
  4. package/dist/assistant-config.js +22 -0
  5. package/dist/assistant-config.js.map +1 -1
  6. package/dist/channels/bluesky/account.d.ts +18 -0
  7. package/dist/channels/bluesky/account.d.ts.map +1 -0
  8. package/dist/channels/bluesky/account.js +25 -0
  9. package/dist/channels/bluesky/account.js.map +1 -0
  10. package/dist/channels/bluesky/channel.d.ts +89 -0
  11. package/dist/channels/bluesky/channel.d.ts.map +1 -0
  12. package/dist/channels/bluesky/channel.js +427 -0
  13. package/dist/channels/bluesky/channel.js.map +1 -0
  14. package/dist/channels/bluesky/config.d.ts +16 -0
  15. package/dist/channels/bluesky/config.d.ts.map +1 -0
  16. package/dist/channels/bluesky/config.js +2 -0
  17. package/dist/channels/bluesky/config.js.map +1 -0
  18. package/dist/channels/bluesky/connection.d.ts +40 -0
  19. package/dist/channels/bluesky/connection.d.ts.map +1 -0
  20. package/dist/channels/bluesky/connection.js +159 -0
  21. package/dist/channels/bluesky/connection.js.map +1 -0
  22. package/dist/channels/bluesky/feed.d.ts +59 -0
  23. package/dist/channels/bluesky/feed.d.ts.map +1 -0
  24. package/dist/channels/bluesky/feed.js +324 -0
  25. package/dist/channels/bluesky/feed.js.map +1 -0
  26. package/dist/channels/bluesky/index.d.ts +5 -0
  27. package/dist/channels/bluesky/index.d.ts.map +1 -0
  28. package/dist/channels/bluesky/index.js +4 -0
  29. package/dist/channels/bluesky/index.js.map +1 -0
  30. package/dist/channels/threads/account.d.ts +42 -0
  31. package/dist/channels/threads/account.d.ts.map +1 -0
  32. package/dist/channels/threads/account.js +64 -0
  33. package/dist/channels/threads/account.js.map +1 -0
  34. package/dist/channels/threads/channel.d.ts +119 -0
  35. package/dist/channels/threads/channel.d.ts.map +1 -0
  36. package/dist/channels/threads/channel.js +405 -0
  37. package/dist/channels/threads/channel.js.map +1 -0
  38. package/dist/channels/threads/client.d.ts +42 -0
  39. package/dist/channels/threads/client.d.ts.map +1 -0
  40. package/dist/channels/threads/client.js +102 -0
  41. package/dist/channels/threads/client.js.map +1 -0
  42. package/dist/channels/threads/feed.d.ts +79 -0
  43. package/dist/channels/threads/feed.d.ts.map +1 -0
  44. package/dist/channels/threads/feed.js +396 -0
  45. package/dist/channels/threads/feed.js.map +1 -0
  46. package/dist/channels/threads/index.d.ts +6 -0
  47. package/dist/channels/threads/index.d.ts.map +1 -0
  48. package/dist/channels/threads/index.js +6 -0
  49. package/dist/channels/threads/index.js.map +1 -0
  50. package/dist/channels/threads/token.d.ts +51 -0
  51. package/dist/channels/threads/token.d.ts.map +1 -0
  52. package/dist/channels/threads/token.js +128 -0
  53. package/dist/channels/threads/token.js.map +1 -0
  54. package/dist/feeds/attachments.d.ts +15 -0
  55. package/dist/feeds/attachments.d.ts.map +1 -0
  56. package/dist/feeds/attachments.js +85 -0
  57. package/dist/feeds/attachments.js.map +1 -0
  58. package/dist/feeds/errors.d.ts +42 -0
  59. package/dist/feeds/errors.d.ts.map +1 -0
  60. package/dist/feeds/errors.js +66 -0
  61. package/dist/feeds/errors.js.map +1 -0
  62. package/dist/feeds/index.d.ts +8 -0
  63. package/dist/feeds/index.d.ts.map +1 -0
  64. package/dist/feeds/index.js +6 -0
  65. package/dist/feeds/index.js.map +1 -0
  66. package/dist/feeds/publish-store.d.ts +148 -0
  67. package/dist/feeds/publish-store.d.ts.map +1 -0
  68. package/dist/feeds/publish-store.js +345 -0
  69. package/dist/feeds/publish-store.js.map +1 -0
  70. package/dist/feeds/publisher.d.ts +118 -0
  71. package/dist/feeds/publisher.d.ts.map +1 -0
  72. package/dist/feeds/publisher.js +308 -0
  73. package/dist/feeds/publisher.js.map +1 -0
  74. package/dist/feeds/storage.d.ts +33 -0
  75. package/dist/feeds/storage.d.ts.map +1 -0
  76. package/dist/feeds/storage.js +61 -0
  77. package/dist/feeds/storage.js.map +1 -0
  78. package/dist/feeds/text.d.ts +26 -0
  79. package/dist/feeds/text.d.ts.map +1 -0
  80. package/dist/feeds/text.js +126 -0
  81. package/dist/feeds/text.js.map +1 -0
  82. package/dist/feeds/token-store.d.ts +45 -0
  83. package/dist/feeds/token-store.d.ts.map +1 -0
  84. package/dist/feeds/token-store.js +128 -0
  85. package/dist/feeds/token-store.js.map +1 -0
  86. package/dist/formatters/markdown.d.ts.map +1 -1
  87. package/dist/formatters/markdown.js +6 -0
  88. package/dist/formatters/markdown.js.map +1 -1
  89. package/dist/formatters/plain-text.d.ts +7 -0
  90. package/dist/formatters/plain-text.d.ts.map +1 -0
  91. package/dist/formatters/plain-text.js +38 -0
  92. package/dist/formatters/plain-text.js.map +1 -0
  93. package/dist/gateway.js +1 -1
  94. package/dist/gateway.js.map +1 -1
  95. package/dist/index.d.ts +5 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +4 -0
  98. package/dist/index.js.map +1 -1
  99. package/dist/runtime-builder.d.ts.map +1 -1
  100. package/dist/runtime-builder.js +54 -0
  101. package/dist/runtime-builder.js.map +1 -1
  102. package/package.json +23 -15
@@ -0,0 +1,148 @@
1
+ import type { FeedPost } from '@cogitator-ai/types';
2
+ import type { FeedErrorCode } from './errors.js';
3
+ import { type PgClient } from './storage.js';
4
+ /** How one feed of a job is doing. */
5
+ export interface FeedDelivery {
6
+ feed: string;
7
+ status: 'pending' | 'published' | 'failed';
8
+ /** Attempts that could have published: a wait for a full quota is not one. */
9
+ attempts: number;
10
+ /** The feed's idempotency key, kept from before the first attempt until it is published. */
11
+ idempotencyKey?: string;
12
+ /** When to try next, in ms since the epoch, while pending. */
13
+ nextAttemptAt: number;
14
+ post?: {
15
+ id: string;
16
+ url: string;
17
+ publishedAt: number;
18
+ };
19
+ error?: {
20
+ code: FeedErrorCode;
21
+ message: string;
22
+ };
23
+ }
24
+ /** A post on its way to one or more feeds. */
25
+ export interface PublishJob {
26
+ id: string;
27
+ /** Publishing twice with the same key publishes once. */
28
+ key?: string;
29
+ post: FeedPost;
30
+ createdAt: number;
31
+ deliveries: FeedDelivery[];
32
+ }
33
+ /** Whether a job still has a feed to publish to. */
34
+ export declare function isPending(job: PublishJob): boolean;
35
+ /** When the job's next pending delivery is due, or `undefined` when it is done. */
36
+ export declare function nextDueAt(job: PublishJob): number | undefined;
37
+ /** A worker's hold on a job: who holds it, and for how long a claim or an extension lasts. */
38
+ export interface JobClaim {
39
+ owner: string;
40
+ /** In ms. */
41
+ ttl: number;
42
+ }
43
+ /**
44
+ * Where a publisher keeps its jobs, so scheduled and retried posts survive a
45
+ * restart. A worker claims a job before it publishes it, extends the claim
46
+ * while it works, and can save the job only while the claim is its own, so
47
+ * a worker that lost its claim never overwrites the one that took over.
48
+ */
49
+ export interface PublishStore {
50
+ /** Adds `job`, unless one with the same key exists: that one is returned instead. */
51
+ add(job: PublishJob): Promise<PublishJob>;
52
+ get(id: string): Promise<PublishJob | undefined>;
53
+ /** Claims the job with the earliest delivery due by `now` that no one holds. */
54
+ claimNext(now: number, claim: JobClaim): Promise<PublishJob | undefined>;
55
+ /** Claims one job, `false` when someone holds it or it is missing. */
56
+ claim(id: string, claim: JobClaim): Promise<boolean>;
57
+ /** Extends `claim.owner`'s claim by `claim.ttl` from now, `false` when it lost it. */
58
+ extend(id: string, claim: JobClaim): Promise<boolean>;
59
+ /** Saves a job while `owner` holds it, `false` when the claim was lost and nothing was saved. */
60
+ save(job: PublishJob, owner: string): Promise<boolean>;
61
+ /** Releases `owner`'s claim on a job. */
62
+ release(id: string, owner: string): Promise<void>;
63
+ list(filter?: {
64
+ pending?: boolean;
65
+ }): Promise<PublishJob[]>;
66
+ /** Removes a job no worker holds, `false` when it is missing or held. */
67
+ remove(id: string): Promise<boolean>;
68
+ }
69
+ /** A job as JSON: attachment bytes become base64. */
70
+ export declare function encodeJob(job: PublishJob): string;
71
+ /** A job back from `encodeJob`. */
72
+ export declare function decodeJob(json: string | unknown): PublishJob;
73
+ /** Jobs in memory, for tests and a publisher that needs no restart safety. */
74
+ export declare class MemoryPublishStore implements PublishStore {
75
+ private readonly jobs;
76
+ private readonly claims;
77
+ constructor(now?: () => number);
78
+ add(job: PublishJob): Promise<PublishJob>;
79
+ get(id: string): Promise<PublishJob | undefined>;
80
+ claimNext(now: number, claim: JobClaim): Promise<PublishJob | undefined>;
81
+ claim(id: string, claim: JobClaim): Promise<boolean>;
82
+ extend(id: string, claim: JobClaim): Promise<boolean>;
83
+ save(job: PublishJob, owner: string): Promise<boolean>;
84
+ release(id: string, owner: string): Promise<void>;
85
+ list(filter?: {
86
+ pending?: boolean;
87
+ }): Promise<PublishJob[]>;
88
+ remove(id: string): Promise<boolean>;
89
+ }
90
+ export interface FilePublishStoreOptions {
91
+ /** The directory with one JSON file per job (default `~/.cogitator/feed-jobs`). */
92
+ directory?: string;
93
+ }
94
+ /**
95
+ * Jobs as one JSON file each, written atomically, for a single publishing
96
+ * process: claims live in that process. Several workers need
97
+ * `PostgresPublishStore`.
98
+ */
99
+ export declare class FilePublishStore implements PublishStore {
100
+ readonly directory: string;
101
+ private readonly queue;
102
+ private readonly claims;
103
+ constructor(options?: FilePublishStoreOptions, now?: () => number);
104
+ add(job: PublishJob): Promise<PublishJob>;
105
+ get(id: string): Promise<PublishJob | undefined>;
106
+ claimNext(now: number, claim: JobClaim): Promise<PublishJob | undefined>;
107
+ claim(id: string, claim: JobClaim): Promise<boolean>;
108
+ extend(id: string, claim: JobClaim): Promise<boolean>;
109
+ save(job: PublishJob, owner: string): Promise<boolean>;
110
+ release(id: string, owner: string): Promise<void>;
111
+ list(filter?: {
112
+ pending?: boolean;
113
+ }): Promise<PublishJob[]>;
114
+ remove(id: string): Promise<boolean>;
115
+ private fileOf;
116
+ private write;
117
+ private read;
118
+ private readAll;
119
+ }
120
+ export interface PostgresPublishStoreOptions {
121
+ client: PgClient;
122
+ /** Table name (default `cogitator_feed_jobs`), created on first use. */
123
+ table?: string;
124
+ }
125
+ /**
126
+ * Jobs in a Postgres table. Claims are leases on the database clock, taken
127
+ * with `FOR UPDATE SKIP LOCKED`, so several publishing workers split the due
128
+ * jobs between them, and a worker saves a job only while its lease holds.
129
+ */
130
+ export declare class PostgresPublishStore implements PublishStore {
131
+ private readonly client;
132
+ private readonly table;
133
+ private ready?;
134
+ constructor(options: PostgresPublishStoreOptions);
135
+ add(job: PublishJob): Promise<PublishJob>;
136
+ get(id: string): Promise<PublishJob | undefined>;
137
+ claimNext(now: number, claim: JobClaim): Promise<PublishJob | undefined>;
138
+ claim(id: string, claim: JobClaim): Promise<boolean>;
139
+ extend(id: string, claim: JobClaim): Promise<boolean>;
140
+ save(job: PublishJob, owner: string): Promise<boolean>;
141
+ release(id: string, owner: string): Promise<void>;
142
+ list(filter?: {
143
+ pending?: boolean;
144
+ }): Promise<PublishJob[]>;
145
+ remove(id: string): Promise<boolean>;
146
+ private ensureTable;
147
+ }
148
+ //# sourceMappingURL=publish-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-store.d.ts","sourceRoot":"","sources":["../../src/feeds/publish-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,345 @@
1
+ import { mkdir, readdir, readFile, rm } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { createIfMissing, fromJson, SerialQueue, TABLE_NAME, writeFileAtomic, } from './storage.js';
5
+ /** Whether a job still has a feed to publish to. */
6
+ export function isPending(job) {
7
+ return job.deliveries.some((delivery) => delivery.status === 'pending');
8
+ }
9
+ /** When the job's next pending delivery is due, or `undefined` when it is done. */
10
+ export function nextDueAt(job) {
11
+ const due = job.deliveries
12
+ .filter((delivery) => delivery.status === 'pending')
13
+ .map((delivery) => delivery.nextAttemptAt);
14
+ return due.length > 0 ? Math.min(...due) : undefined;
15
+ }
16
+ /** A job as JSON: attachment bytes become base64. */
17
+ export function encodeJob(job) {
18
+ return JSON.stringify(job, (_key, value) => value instanceof Uint8Array ? { __bytes: Buffer.from(value).toString('base64') } : value);
19
+ }
20
+ /** A job back from `encodeJob`. */
21
+ export function decodeJob(json) {
22
+ const text = typeof json === 'string' ? json : JSON.stringify(json);
23
+ return JSON.parse(text, (_key, value) => typeof value === 'object' &&
24
+ value !== null &&
25
+ '__bytes' in value &&
26
+ typeof value.__bytes === 'string'
27
+ ? new Uint8Array(Buffer.from(value.__bytes, 'base64'))
28
+ : value);
29
+ }
30
+ const copyOf = (job) => decodeJob(encodeJob(job));
31
+ /** Claims held by one process, for the in-memory and file stores. */
32
+ class LocalClaims {
33
+ now;
34
+ claims = new Map();
35
+ constructor(now) {
36
+ this.now = now;
37
+ }
38
+ held(id) {
39
+ return (this.claims.get(id)?.until ?? 0) > this.now();
40
+ }
41
+ holds(id, owner) {
42
+ const claim = this.claims.get(id);
43
+ return claim?.owner === owner && claim.until > this.now();
44
+ }
45
+ take(id, claim) {
46
+ this.claims.set(id, { owner: claim.owner, until: this.now() + claim.ttl });
47
+ }
48
+ release(id, owner) {
49
+ if (this.claims.get(id)?.owner === owner)
50
+ this.claims.delete(id);
51
+ }
52
+ drop(id) {
53
+ this.claims.delete(id);
54
+ }
55
+ }
56
+ /** Jobs in memory, for tests and a publisher that needs no restart safety. */
57
+ export class MemoryPublishStore {
58
+ jobs = new Map();
59
+ claims;
60
+ constructor(now = Date.now) {
61
+ this.claims = new LocalClaims(now);
62
+ }
63
+ async add(job) {
64
+ const existing = job.key
65
+ ? [...this.jobs.values()].find((candidate) => candidate.key === job.key)
66
+ : undefined;
67
+ if (existing)
68
+ return copyOf(existing);
69
+ this.jobs.set(job.id, copyOf(job));
70
+ return copyOf(job);
71
+ }
72
+ async get(id) {
73
+ const job = this.jobs.get(id);
74
+ return job ? copyOf(job) : undefined;
75
+ }
76
+ async claimNext(now, claim) {
77
+ const [next] = [...this.jobs.values()]
78
+ .filter((job) => !this.claims.held(job.id) && (nextDueAt(job) ?? Infinity) <= now)
79
+ .sort((a, b) => (nextDueAt(a) ?? 0) - (nextDueAt(b) ?? 0));
80
+ if (!next)
81
+ return undefined;
82
+ this.claims.take(next.id, claim);
83
+ return copyOf(next);
84
+ }
85
+ async claim(id, claim) {
86
+ if (!this.jobs.has(id) || this.claims.held(id))
87
+ return false;
88
+ this.claims.take(id, claim);
89
+ return true;
90
+ }
91
+ async extend(id, claim) {
92
+ if (!this.claims.holds(id, claim.owner))
93
+ return false;
94
+ this.claims.take(id, claim);
95
+ return true;
96
+ }
97
+ async save(job, owner) {
98
+ if (!this.claims.holds(job.id, owner))
99
+ return false;
100
+ this.jobs.set(job.id, copyOf(job));
101
+ return true;
102
+ }
103
+ async release(id, owner) {
104
+ this.claims.release(id, owner);
105
+ }
106
+ async list(filter = {}) {
107
+ return [...this.jobs.values()]
108
+ .filter((job) => filter.pending === undefined || isPending(job) === filter.pending)
109
+ .sort((a, b) => a.createdAt - b.createdAt)
110
+ .map(copyOf);
111
+ }
112
+ async remove(id) {
113
+ if (this.claims.held(id))
114
+ return false;
115
+ return this.jobs.delete(id);
116
+ }
117
+ }
118
+ /**
119
+ * Jobs as one JSON file each, written atomically, for a single publishing
120
+ * process: claims live in that process. Several workers need
121
+ * `PostgresPublishStore`.
122
+ */
123
+ export class FilePublishStore {
124
+ directory;
125
+ queue = new SerialQueue();
126
+ claims;
127
+ constructor(options = {}, now = Date.now) {
128
+ this.directory = options.directory ?? join(homedir(), '.cogitator', 'feed-jobs');
129
+ this.claims = new LocalClaims(now);
130
+ }
131
+ async add(job) {
132
+ return this.queue.run(async () => {
133
+ if (job.key) {
134
+ const existing = (await this.readAll()).find((candidate) => candidate.key === job.key);
135
+ if (existing)
136
+ return existing;
137
+ }
138
+ await this.write(job);
139
+ return copyOf(job);
140
+ });
141
+ }
142
+ async get(id) {
143
+ return this.queue.run(() => this.read(id));
144
+ }
145
+ async claimNext(now, claim) {
146
+ return this.queue.run(async () => {
147
+ const [next] = (await this.readAll())
148
+ .filter((job) => !this.claims.held(job.id) && (nextDueAt(job) ?? Infinity) <= now)
149
+ .sort((a, b) => (nextDueAt(a) ?? 0) - (nextDueAt(b) ?? 0));
150
+ if (next)
151
+ this.claims.take(next.id, claim);
152
+ return next;
153
+ });
154
+ }
155
+ async claim(id, claim) {
156
+ return this.queue.run(async () => {
157
+ if (this.claims.held(id) || !(await this.read(id)))
158
+ return false;
159
+ this.claims.take(id, claim);
160
+ return true;
161
+ });
162
+ }
163
+ async extend(id, claim) {
164
+ return this.queue.run(async () => {
165
+ if (!this.claims.holds(id, claim.owner))
166
+ return false;
167
+ this.claims.take(id, claim);
168
+ return true;
169
+ });
170
+ }
171
+ async save(job, owner) {
172
+ return this.queue.run(async () => {
173
+ if (!this.claims.holds(job.id, owner))
174
+ return false;
175
+ await this.write(job);
176
+ return true;
177
+ });
178
+ }
179
+ async release(id, owner) {
180
+ await this.queue.run(async () => this.claims.release(id, owner));
181
+ }
182
+ async list(filter = {}) {
183
+ return this.queue.run(async () => (await this.readAll())
184
+ .filter((job) => filter.pending === undefined || isPending(job) === filter.pending)
185
+ .sort((a, b) => a.createdAt - b.createdAt));
186
+ }
187
+ async remove(id) {
188
+ return this.queue.run(async () => {
189
+ if (this.claims.held(id) || !(await this.read(id)))
190
+ return false;
191
+ await rm(this.fileOf(id), { force: true });
192
+ this.claims.drop(id);
193
+ return true;
194
+ });
195
+ }
196
+ fileOf(id) {
197
+ return join(this.directory, `${id.replace(/[^\w-]/g, '_')}.json`);
198
+ }
199
+ async write(job) {
200
+ await writeFileAtomic(this.fileOf(job.id), encodeJob(job));
201
+ }
202
+ async read(id) {
203
+ try {
204
+ return decodeJob(await readFile(this.fileOf(id), 'utf-8'));
205
+ }
206
+ catch (error) {
207
+ if (error.code === 'ENOENT')
208
+ return undefined;
209
+ throw error;
210
+ }
211
+ }
212
+ async readAll() {
213
+ await mkdir(this.directory, { recursive: true });
214
+ const jobs = [];
215
+ for (const name of await readdir(this.directory)) {
216
+ if (!name.endsWith('.json'))
217
+ continue;
218
+ try {
219
+ jobs.push(decodeJob(await readFile(join(this.directory, name), 'utf-8')));
220
+ }
221
+ catch {
222
+ console.warn(`[feeds] Skipping unreadable job file ${join(this.directory, name)}`);
223
+ }
224
+ }
225
+ return jobs;
226
+ }
227
+ }
228
+ /**
229
+ * Jobs in a Postgres table. Claims are leases on the database clock, taken
230
+ * with `FOR UPDATE SKIP LOCKED`, so several publishing workers split the due
231
+ * jobs between them, and a worker saves a job only while its lease holds.
232
+ */
233
+ export class PostgresPublishStore {
234
+ client;
235
+ table;
236
+ ready;
237
+ constructor(options) {
238
+ const table = options.table ?? 'cogitator_feed_jobs';
239
+ if (!TABLE_NAME.test(table))
240
+ throw new Error(`Invalid feed job table name: ${table}`);
241
+ this.client = options.client;
242
+ this.table = table;
243
+ }
244
+ async add(job) {
245
+ await this.ensureTable();
246
+ const { rows } = await this.client.query(`INSERT INTO ${this.table} (id, key, next_due_at, created_at, data)
247
+ VALUES ($1, $2, $3, $4, $5::jsonb)
248
+ ON CONFLICT DO NOTHING
249
+ RETURNING data`, [job.id, job.key ?? null, nextDueAt(job) ?? null, job.createdAt, encodeJob(job)]);
250
+ if (rows[0])
251
+ return decodeJob(fromJson(rows[0].data));
252
+ const existing = job.key
253
+ ? await this.client.query(`SELECT data FROM ${this.table} WHERE key = $1`, [job.key])
254
+ : await this.client.query(`SELECT data FROM ${this.table} WHERE id = $1`, [job.id]);
255
+ if (!existing.rows[0])
256
+ throw new Error(`Could not add feed job ${job.id}`);
257
+ return decodeJob(fromJson(existing.rows[0].data));
258
+ }
259
+ async get(id) {
260
+ await this.ensureTable();
261
+ const { rows } = await this.client.query(`SELECT data FROM ${this.table} WHERE id = $1`, [id]);
262
+ return rows[0] ? decodeJob(fromJson(rows[0].data)) : undefined;
263
+ }
264
+ async claimNext(now, claim) {
265
+ await this.ensureTable();
266
+ const { rows } = await this.client.query(`UPDATE ${this.table}
267
+ SET claimed_until = now() + $2::double precision * interval '1 millisecond',
268
+ claimed_by = $3
269
+ WHERE id = (
270
+ SELECT id FROM ${this.table}
271
+ WHERE next_due_at IS NOT NULL AND next_due_at <= $1
272
+ AND (claimed_until IS NULL OR claimed_until < now())
273
+ ORDER BY next_due_at
274
+ LIMIT 1
275
+ FOR UPDATE SKIP LOCKED)
276
+ RETURNING data`, [now, claim.ttl, claim.owner]);
277
+ return rows[0] ? decodeJob(fromJson(rows[0].data)) : undefined;
278
+ }
279
+ async claim(id, claim) {
280
+ await this.ensureTable();
281
+ const { rows } = await this.client.query(`UPDATE ${this.table}
282
+ SET claimed_until = now() + $2::double precision * interval '1 millisecond',
283
+ claimed_by = $3
284
+ WHERE id = $1 AND (claimed_until IS NULL OR claimed_until < now())
285
+ RETURNING id`, [id, claim.ttl, claim.owner]);
286
+ return rows.length > 0;
287
+ }
288
+ async extend(id, claim) {
289
+ await this.ensureTable();
290
+ const { rows } = await this.client.query(`UPDATE ${this.table}
291
+ SET claimed_until = now() + $2::double precision * interval '1 millisecond'
292
+ WHERE id = $1 AND claimed_by = $3 AND claimed_until > now()
293
+ RETURNING id`, [id, claim.ttl, claim.owner]);
294
+ return rows.length > 0;
295
+ }
296
+ async save(job, owner) {
297
+ await this.ensureTable();
298
+ const { rows } = await this.client.query(`UPDATE ${this.table} SET data = $2::jsonb, next_due_at = $3
299
+ WHERE id = $1 AND claimed_by = $4 AND claimed_until > now()
300
+ RETURNING id`, [job.id, encodeJob(job), nextDueAt(job) ?? null, owner]);
301
+ return rows.length > 0;
302
+ }
303
+ async release(id, owner) {
304
+ await this.ensureTable();
305
+ await this.client.query(`UPDATE ${this.table} SET claimed_until = NULL, claimed_by = NULL
306
+ WHERE id = $1 AND claimed_by = $2`, [id, owner]);
307
+ }
308
+ async list(filter = {}) {
309
+ await this.ensureTable();
310
+ const where = filter.pending === undefined
311
+ ? ''
312
+ : filter.pending
313
+ ? 'WHERE next_due_at IS NOT NULL'
314
+ : 'WHERE next_due_at IS NULL';
315
+ const { rows } = await this.client.query(`SELECT data FROM ${this.table} ${where} ORDER BY created_at`);
316
+ return rows.map((row) => decodeJob(fromJson(row.data)));
317
+ }
318
+ async remove(id) {
319
+ await this.ensureTable();
320
+ const { rows } = await this.client.query(`DELETE FROM ${this.table}
321
+ WHERE id = $1 AND (claimed_until IS NULL OR claimed_until < now())
322
+ RETURNING id`, [id]);
323
+ return rows.length > 0;
324
+ }
325
+ ensureTable() {
326
+ this.ready ??= (async () => {
327
+ await createIfMissing(this.client, `CREATE TABLE IF NOT EXISTS ${this.table} (
328
+ id text PRIMARY KEY,
329
+ key text UNIQUE,
330
+ next_due_at bigint,
331
+ created_at bigint NOT NULL,
332
+ claimed_until timestamptz,
333
+ claimed_by text,
334
+ data jsonb NOT NULL
335
+ )`);
336
+ const index = `${this.table.replace('.', '_')}_due_idx`;
337
+ await createIfMissing(this.client, `CREATE INDEX IF NOT EXISTS ${index} ON ${this.table} (next_due_at) WHERE next_due_at IS NOT NULL`);
338
+ })().catch((error) => {
339
+ this.ready = undefined;
340
+ throw error;
341
+ });
342
+ return this.ready;
343
+ }
344
+ }
345
+ //# sourceMappingURL=publish-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-store.js","sourceRoot":"","sources":["../../src/feeds/publish-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import type { FeedChannel, FeedPost, PublishedPost } from '@cogitator-ai/types';
2
+ import { type PublishJob, type PublishStore } from './publish-store.js';
3
+ export interface FeedRetryOptions {
4
+ /** Attempts per feed before it fails for good (default 5). */
5
+ maxAttempts?: number;
6
+ /** The wait before the second attempt, doubled for each one after, in ms (default 60 000). */
7
+ baseDelay?: number;
8
+ /** The longest wait between attempts, in ms (default one hour). */
9
+ maxDelay?: number;
10
+ }
11
+ export interface FeedPublishedEvent {
12
+ job: PublishJob;
13
+ feed: string;
14
+ post: PublishedPost;
15
+ }
16
+ export interface FeedFailedEvent {
17
+ job: PublishJob;
18
+ feed: string;
19
+ error: Error;
20
+ /** Whether the feed gave up: no attempt follows. */
21
+ final: boolean;
22
+ }
23
+ export interface FeedPublisherOptions {
24
+ feeds: FeedChannel[];
25
+ /** Where jobs are kept (default in memory: scheduled and retried posts do not survive a restart). */
26
+ store?: PublishStore;
27
+ retry?: FeedRetryOptions;
28
+ /** How often a started publisher looks for due jobs, in ms (default 15 000). */
29
+ pollInterval?: number;
30
+ /**
31
+ * How long a claim on a job lasts, in ms (default five minutes). The
32
+ * publisher extends it every third of that while it works on the job, so
33
+ * this is how soon another worker takes over a job whose worker died.
34
+ */
35
+ claimTtl?: number;
36
+ /**
37
+ * A text longer than a feed takes: `truncate` (default) cuts it at a word
38
+ * with an ellipsis for that feed, `fail` fails that feed.
39
+ */
40
+ overflow?: 'truncate' | 'fail';
41
+ /** Goes through every step but publishing. Dry runs keep their keys apart from real ones. */
42
+ dryRun?: boolean;
43
+ onPublished?: (event: FeedPublishedEvent) => void | Promise<void>;
44
+ onFailed?: (event: FeedFailedEvent) => void | Promise<void>;
45
+ /** The clock, for tests. */
46
+ now?: () => number;
47
+ }
48
+ export interface PublishOptions {
49
+ /** The feeds to publish to, by type (default every feed of the publisher). */
50
+ feeds?: string[];
51
+ /** Publishing twice with the same key publishes once: the second call returns the first job. */
52
+ key?: string;
53
+ /** When to publish. A time in the future schedules the post. */
54
+ publishAt?: Date | number;
55
+ }
56
+ export interface PublishOutcome {
57
+ job: PublishJob;
58
+ /** Whether the post waits for its time, or for another attempt, rather than being done. */
59
+ pending: boolean;
60
+ /** Whether a job with the same key existed, which is what `job` is. */
61
+ duplicate: boolean;
62
+ }
63
+ /**
64
+ * Publishes posts to several feeds: now or at a time, each feed tried and
65
+ * retried on its own, each outcome saved as soon as it is known. Each
66
+ * delivery keeps the feed's idempotency key from before its first attempt,
67
+ * so an attempt after a crash or a lost answer finds the post instead of
68
+ * publishing it twice, and a key makes the whole publication idempotent.
69
+ */
70
+ export declare class FeedPublisher {
71
+ private readonly options;
72
+ private readonly feeds;
73
+ private readonly store;
74
+ private readonly retry;
75
+ private readonly pollInterval;
76
+ private readonly claimTtl;
77
+ private readonly now;
78
+ private readonly owner;
79
+ private timer?;
80
+ private ticking?;
81
+ private stopping;
82
+ private readonly connected;
83
+ constructor(options: FeedPublisherOptions);
84
+ /** Publishes `post` now, or schedules it with `publishAt`. */
85
+ publish(post: FeedPost, options?: PublishOptions): Promise<PublishOutcome>;
86
+ /** Looks for due jobs every `pollInterval` until `stop()`: scheduled posts and retries. */
87
+ start(): void;
88
+ /** Stops looking for due jobs, letting the job being published finish, and waits for it. */
89
+ stop(): Promise<void>;
90
+ /**
91
+ * Publishes the jobs that are due now, one at a time, so a claim is taken
92
+ * only when the job is about to be published. `start()` does this on a timer.
93
+ */
94
+ tick(): Promise<void>;
95
+ get(id: string): Promise<PublishJob | undefined>;
96
+ list(filter?: {
97
+ pending?: boolean;
98
+ }): Promise<PublishJob[]>;
99
+ /** Drops a job before it is published, `false` when it is missing or being published. */
100
+ cancel(id: string): Promise<boolean>;
101
+ /**
102
+ * Connects feeds that will publish later, so a feed that keeps a token
103
+ * renews it until then instead of finding it expired when the post is due.
104
+ * A feed that cannot connect now is tried again the next time.
105
+ */
106
+ private connect;
107
+ private claimOf;
108
+ /** Publishes a job this publisher claimed, extending the claim while it works, then releases it. */
109
+ private run;
110
+ private process;
111
+ /** Saves the job while the claim holds, `false` when another worker took it over. */
112
+ private save;
113
+ private attempt;
114
+ private send;
115
+ private backoff;
116
+ private notify;
117
+ }
118
+ //# sourceMappingURL=publisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../src/feeds/publisher.ts"],"names":[],"mappings":"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"}