@bumail/queue 0.1.0 → 0.3.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 +71 -5
- package/dist/chunks/{index-xhsw4xcz.js → index-vg971acr.js} +70 -6
- package/dist/chunks/index-vg971acr.js.map +12 -0
- package/dist/chunks/index-y3n1w2az.js +18 -0
- package/dist/chunks/index-y3n1w2az.js.map +10 -0
- package/dist/contract/checks.d.ts +6 -0
- package/dist/contract/checks.d.ts.map +1 -1
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.js +86 -55
- package/dist/index.js.map +8 -8
- package/dist/masked.d.ts +7 -0
- package/dist/masked.d.ts.map +1 -0
- package/dist/memory/index.js +3 -5
- package/dist/memory/index.js.map +2 -2
- package/dist/postgres/connect.d.ts +17 -0
- package/dist/postgres/connect.d.ts.map +1 -0
- package/dist/postgres/index.d.ts +2 -0
- package/dist/postgres/index.d.ts.map +1 -0
- package/dist/postgres/index.js +374 -0
- package/dist/postgres/index.js.map +14 -0
- package/dist/postgres/options.d.ts +37 -0
- package/dist/postgres/options.d.ts.map +1 -0
- package/dist/postgres/rows.d.ts +21 -0
- package/dist/postgres/rows.d.ts.map +1 -0
- package/dist/postgres/schema.d.ts +20 -0
- package/dist/postgres/schema.d.ts.map +1 -0
- package/dist/postgres/statements.d.ts +54 -0
- package/dist/postgres/statements.d.ts.map +1 -0
- package/dist/postgres/store.d.ts +38 -0
- package/dist/postgres/store.d.ts.map +1 -0
- package/dist/queue/deliver.d.ts +7 -0
- package/dist/queue/deliver.d.ts.map +1 -1
- package/dist/queue/lease.d.ts +41 -0
- package/dist/queue/lease.d.ts.map +1 -0
- package/dist/queue/outcome.d.ts.map +1 -1
- package/dist/queue/settings/index.d.ts.map +1 -1
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/redis/connect.d.ts +25 -0
- package/dist/redis/connect.d.ts.map +1 -0
- package/dist/redis/index.d.ts +3 -0
- package/dist/redis/index.d.ts.map +1 -0
- package/dist/redis/index.js +430 -0
- package/dist/redis/index.js.map +14 -0
- package/dist/redis/items.d.ts +13 -0
- package/dist/redis/items.d.ts.map +1 -0
- package/dist/redis/options.d.ts +47 -0
- package/dist/redis/options.d.ts.map +1 -0
- package/dist/redis/run.d.ts +12 -0
- package/dist/redis/run.d.ts.map +1 -0
- package/dist/redis/scripts.d.ts +60 -0
- package/dist/redis/scripts.d.ts.map +1 -0
- package/dist/redis/store.d.ts +30 -0
- package/dist/redis/store.d.ts.map +1 -0
- package/dist/sqlite/index.js +3 -5
- package/dist/sqlite/index.js.map +2 -2
- package/dist/text.d.ts +9 -3
- package/dist/text.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/guide.md +314 -7
- package/docs/roadmap.md +73 -19
- package/docs/troubleshooting.md +317 -7
- package/package.json +15 -3
- package/dist/chunks/index-p4k4rjb7.js +0 -15
- package/dist/chunks/index-p4k4rjb7.js.map +0 -10
- package/dist/chunks/index-xhsw4xcz.js.map +0 -10
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { QueueItem } from '../contract/types';
|
|
2
|
+
/** An item's hash, as `HGETALL` gives it: a map, or a script's flat list of names and values. */
|
|
3
|
+
export type Fields = Readonly<Record<string, string>>;
|
|
4
|
+
/** A script's `HGETALL`, `[name, value, …]`, as a map; a map as it is. */
|
|
5
|
+
export declare function fieldsOf(reply: unknown): Fields | undefined;
|
|
6
|
+
/** The item a hash holds. Times are kept as JavaScript wrote them, so each reads back exactly. */
|
|
7
|
+
export declare function itemOf(fields: Fields): QueueItem;
|
|
8
|
+
export declare const isId: (id: unknown) => id is string;
|
|
9
|
+
/** A time as a script takes it: the string JavaScript writes, which reads back exactly. */
|
|
10
|
+
export declare const time: (value: number) => string;
|
|
11
|
+
/** What `COMPLETE` records of an attempt: the item dropped, or its new state. */
|
|
12
|
+
export declare const outcomeOf: (item: QueueItem) => string[];
|
|
13
|
+
//# sourceMappingURL=items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../src/redis/items.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,mBAAmB,CAAC;AAEnE,iGAAiG;AACjG,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEtD,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAW3D;AAID,kGAAkG;AAClG,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAehD;AAQD,eAAO,MAAM,IAAI,GAAI,IAAI,OAAO,KAAG,EAAE,IAAI,MACH,CAAC;AAEvC,2FAA2F;AAC3F,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,WAAkB,CAAC;AAErD,iFAAiF;AACjF,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,KAAG,MAAM,EAS9C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a Redis queue keeps its items, and the client it reaches them
|
|
3
|
+
* through.
|
|
4
|
+
*
|
|
5
|
+
* Typed by shape rather than as `Bun.RedisClient`, so the declarations a
|
|
6
|
+
* consumer's `tsc` reads from `@bumail/queue/redis` name no global of
|
|
7
|
+
* Bun's: a `Bun.RedisClient` fits `RedisQueueClient` (`open.spec.ts`
|
|
8
|
+
* checks it, though only because method parameters are compared both
|
|
9
|
+
* ways: Bun declares `args: string[]`; that it writes a `Uint8Array` as
|
|
10
|
+
* its bytes is what the Redis specs show), and so does any client with
|
|
11
|
+
* these methods.
|
|
12
|
+
*/
|
|
13
|
+
/** A Redis client, such as `new Bun.RedisClient(url)`. */
|
|
14
|
+
export interface RedisQueueClient {
|
|
15
|
+
/**
|
|
16
|
+
* One command; resolves with its reply, a bulk string decoded as
|
|
17
|
+
* UTF-8. An argument may be bytes (`Bun.RedisClient` sends a
|
|
18
|
+
* `Uint8Array` as it is), which is how a message is written.
|
|
19
|
+
*/
|
|
20
|
+
send(command: string, args: (string | Uint8Array)[]): Promise<unknown>;
|
|
21
|
+
/** A string value as its bytes, or `null` when there is no such key: how a message is read. */
|
|
22
|
+
getBuffer(key: string): Promise<Uint8Array | null>;
|
|
23
|
+
close(): unknown;
|
|
24
|
+
}
|
|
25
|
+
interface KeyPrefixOption {
|
|
26
|
+
/**
|
|
27
|
+
* Put before each key, so several queues, or a queue and the
|
|
28
|
+
* application, share one Redis database: lowercase letters, digits,
|
|
29
|
+
* `_`, `:`, `.` and `-`, starting with a letter, at most 40. Default
|
|
30
|
+
* `bumail:queue:`.
|
|
31
|
+
*/
|
|
32
|
+
readonly keyPrefix?: string;
|
|
33
|
+
}
|
|
34
|
+
/** The application's client, which it configures and closes itself. */
|
|
35
|
+
export interface RedisQueueClientOptions extends KeyPrefixOption {
|
|
36
|
+
readonly client: RedisQueueClient;
|
|
37
|
+
readonly url?: undefined;
|
|
38
|
+
}
|
|
39
|
+
/** A `redis://` (or `rediss://`, …) URL, for which the store opens a client of its own, closed by `close()`. */
|
|
40
|
+
export interface RedisQueueUrlOptions extends KeyPrefixOption {
|
|
41
|
+
readonly url: string | URL;
|
|
42
|
+
readonly client?: undefined;
|
|
43
|
+
}
|
|
44
|
+
/** `client` or `url`, never both. */
|
|
45
|
+
export type RedisQueueStoreOptions = RedisQueueClientOptions | RedisQueueUrlOptions;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/redis/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,+FAA+F;IAC/F,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,KAAK,IAAI,OAAO,CAAC;CACjB;AAED,UAAU,eAAe;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,uEAAuE;AACvE,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC/D,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,gHAAgH;AAChH,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,qCAAqC;AACrC,MAAM,MAAM,sBAAsB,GAC/B,uBAAuB,GACvB,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Keys } from './connect';
|
|
2
|
+
import type { RedisQueueClient } from './options';
|
|
3
|
+
import { type Script } from './scripts';
|
|
4
|
+
/**
|
|
5
|
+
* Runs a script by its SHA-1 (`EVALSHA`), or, when Redis does not have
|
|
6
|
+
* it, by its source (`EVAL`), which also keeps it for the next call.
|
|
7
|
+
* Either way Redis runs it whole.
|
|
8
|
+
*/
|
|
9
|
+
export declare function run(client: RedisQueueClient, script: Script, keys: string[], args: (string | Uint8Array)[]): Promise<unknown>;
|
|
10
|
+
/** Reads the layout version, writing it on a new queue; a newer one is `INVALID`. */
|
|
11
|
+
export declare function checkLayout(client: RedisQueueClient, keys: Keys): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/redis/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAMhD;;;;GAIG;AACH,wBAAsB,GAAG,CACxB,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,GAC3B,OAAO,CAAC,OAAO,CAAC,CAQlB;AAKD,qFAAqF;AACrF,wBAAsB,WAAW,CAChC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,IAAI,GACR,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Lua scripts a Redis store runs: each operation that writes is one
|
|
3
|
+
* script, so Redis runs it whole, with no other command between its
|
|
4
|
+
* steps. The fixed keys come as `KEYS`; an item's own keys are its
|
|
5
|
+
* prefix (`ARGV[1]`), `item:` or `message:`, and its id.
|
|
6
|
+
*
|
|
7
|
+
* An item is a hash, `<prefix>item:<id>`; its message a string,
|
|
8
|
+
* `<prefix>message:<id>`, written from the bytes given, as they are. Its
|
|
9
|
+
* member in the sorted sets is its sequence number, sixteen digits, `:`,
|
|
10
|
+
* and its id: Redis orders members of one score by their bytes, so items
|
|
11
|
+
* equally due come oldest first. Times travel as the strings JavaScript
|
|
12
|
+
* writes for them and are only compared here (`tonumber`), never written
|
|
13
|
+
* back from Lua, so none loses a digit.
|
|
14
|
+
*/
|
|
15
|
+
/** A script, and the SHA-1 `EVALSHA` names it by. */
|
|
16
|
+
export interface Script {
|
|
17
|
+
readonly source: string;
|
|
18
|
+
readonly sha: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* KEYS schema; ARGV prefix, version. Writes the version on a new queue;
|
|
22
|
+
* returns the one found.
|
|
23
|
+
*/
|
|
24
|
+
export declare const SCHEMA: Script;
|
|
25
|
+
/**
|
|
26
|
+
* KEYS items, ready, seq; ARGV prefix, id, from, recipients, size,
|
|
27
|
+
* created, message, max (or ''). `{'full', n}` when `max` items are
|
|
28
|
+
* there already, else `{'ok'}`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const ADD: Script;
|
|
31
|
+
/**
|
|
32
|
+
* KEYS ready, leases, items; ARGV prefix, owner, now, expiry. The
|
|
33
|
+
* earliest due, then the oldest, of the items no lease holds and of those
|
|
34
|
+
* whose lease expired, leased to the owner; its fields, or false. The
|
|
35
|
+
* expired leases are read whole: there are as many as the leases a
|
|
36
|
+
* crashed or stalled worker left behind, and the leased items an admin
|
|
37
|
+
* moved later, until they are due.
|
|
38
|
+
*/
|
|
39
|
+
export declare const CLAIM: Script;
|
|
40
|
+
/** KEYS leases; ARGV prefix, id, owner, expiry. 1 while the owner holds the lease, else 0. */
|
|
41
|
+
export declare const RENEW: Script;
|
|
42
|
+
/**
|
|
43
|
+
* KEYS items, ready, leases; ARGV prefix, id, owner, rev, then 'drop',
|
|
44
|
+
* or 'record' and recipients, next, attempts, delay. 0 when the owner
|
|
45
|
+
* does not hold the lease; -1 when another outcome was recorded since
|
|
46
|
+
* the item was read at `rev`, to read it again; 1 once recorded, the
|
|
47
|
+
* lease let go of, or the item and its message dropped.
|
|
48
|
+
*/
|
|
49
|
+
export declare const COMPLETE: Script;
|
|
50
|
+
/**
|
|
51
|
+
* KEYS items, ready, leases; ARGV prefix, id, at, owner (or ''). With an
|
|
52
|
+
* owner, only while it holds the lease, which it lets go of; without,
|
|
53
|
+
* the lease stays. 1 when moved, else 0.
|
|
54
|
+
*/
|
|
55
|
+
export declare const RESCHEDULE: Script;
|
|
56
|
+
/** KEYS items, ready, leases; ARGV prefix, id. The item's fields as it stood, or false; dropped with its message. */
|
|
57
|
+
export declare const CANCEL: Script;
|
|
58
|
+
/** KEYS items; ARGV prefix, first, last. A page of items, each its fields, in one read. */
|
|
59
|
+
export declare const LIST: Script;
|
|
60
|
+
//# sourceMappingURL=scripts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/redis/scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAuBH,qDAAqD;AACrD,MAAM,WAAW,MAAM;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAQD;;;GAGG;AACH,eAAO,MAAM,MAAM,QAKjB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,GAAG,QAcd,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,QAyBhB,CAAC;AAEH,8FAA8F;AAC9F,eAAO,MAAM,KAAK,QAMhB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,QAmBnB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,UAAU,QAerB,CAAC;AAEH,qHAAqH;AACrH,eAAO,MAAM,MAAM,QAUjB,CAAC;AAEH,2FAA2F;AAC3F,eAAO,MAAM,IAAI,QAMf,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { QueueStore } from '../contract/queue-store';
|
|
2
|
+
import type { AddOptions, AttemptResult, ClaimRequest, NewQueueItem, QueueItem, QueueListOptions } from '../contract/types';
|
|
3
|
+
import type { RedisQueueStoreOptions } from './options';
|
|
4
|
+
/**
|
|
5
|
+
* A `QueueStore` on Redis through Bun's own `Bun.RedisClient`: several
|
|
6
|
+
* instances, on one machine or many, share one queue. Every operation
|
|
7
|
+
* that writes is one Lua script, which Redis runs whole, so two
|
|
8
|
+
* instances never take the same item. The due items are in sorted sets,
|
|
9
|
+
* each item a hash, its message a string written byte for byte. One
|
|
10
|
+
* Redis, or a primary with replicas — not Redis Cluster.
|
|
11
|
+
*/
|
|
12
|
+
export declare class RedisQueueStore implements QueueStore {
|
|
13
|
+
#private;
|
|
14
|
+
private constructor();
|
|
15
|
+
/** Checks the options; connects to nothing until the first call. What is wrong is `INVALID`. */
|
|
16
|
+
static open(options: RedisQueueStoreOptions): RedisQueueStore;
|
|
17
|
+
/** Closes the client the store opened for a URL, never one it was given; closing twice is fine. */
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
add(item: NewQueueItem, options?: AddOptions): Promise<QueueItem>;
|
|
20
|
+
get(id: string): Promise<QueueItem | undefined>;
|
|
21
|
+
list(options?: QueueListOptions): Promise<QueueItem[]>;
|
|
22
|
+
count(): Promise<number>;
|
|
23
|
+
readMessage(id: string): Promise<Uint8Array | undefined>;
|
|
24
|
+
claim(request: ClaimRequest): Promise<QueueItem | undefined>;
|
|
25
|
+
renew(id: string, owner: string, expiresAt: number): Promise<boolean>;
|
|
26
|
+
complete(id: string, owner: string, result: AttemptResult): Promise<QueueItem | undefined>;
|
|
27
|
+
reschedule(id: string, at: number, owner?: string): Promise<boolean>;
|
|
28
|
+
cancel(id: string): Promise<QueueItem | undefined>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/redis/store.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,KAAK,EAAoB,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAa1E;;;;;;;GAOG;AACH,qBAAa,eAAgB,YAAW,UAAU;;IAOjD,OAAO;IAMP,gGAAgG;IAChG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe;IAI7D,mGAAmG;IAC7F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCtB,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC;IA2BrE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAS/C,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAatD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAKxB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAOxD,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAc5D,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAarE,QAAQ,CACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,aAAa,GACnB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IA2B3B,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAepE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;CAQxD"}
|
package/dist/sqlite/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
QueueError2,
|
|
2
3
|
checkTime,
|
|
3
4
|
checkOwner,
|
|
4
5
|
checkNewItem,
|
|
@@ -9,10 +10,7 @@ import {
|
|
|
9
10
|
isDone,
|
|
10
11
|
applyAttempt,
|
|
11
12
|
newItem
|
|
12
|
-
} from "../chunks/index-
|
|
13
|
-
import {
|
|
14
|
-
QueueError2
|
|
15
|
-
} from "../chunks/index-p4k4rjb7.js";
|
|
13
|
+
} from "../chunks/index-vg971acr.js";
|
|
16
14
|
|
|
17
15
|
// src/sqlite/open.ts
|
|
18
16
|
import { Database } from "bun:sqlite";
|
|
@@ -284,5 +282,5 @@ export {
|
|
|
284
282
|
SqliteQueueStore
|
|
285
283
|
};
|
|
286
284
|
|
|
287
|
-
//# debugId=
|
|
285
|
+
//# debugId=1AE80C41E9F1FD2664756E2164756E21
|
|
288
286
|
//# sourceMappingURL=index.js.map
|
package/dist/sqlite/index.js.map
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"import type { QueueItem, RecipientState } from '../contract/types';\n\n/** A row of `items`, as `bun:sqlite` reads it. */\nexport interface ItemRow {\n\treadonly id: string;\n\treadonly sender: string;\n\treadonly recipients: string;\n\treadonly size: number;\n\treadonly created_at: number;\n\treadonly next_attempt_at: number;\n\treadonly attempts: number;\n\treadonly delay_notified: number;\n\treadonly lease_owner: string | null;\n\treadonly lease_expires_at: number | null;\n}\n\n/** The columns a query reads to build an item. */\nexport const COLUMNS =\n\t'id, sender, recipients, size, created_at, next_attempt_at, attempts, delay_notified, lease_owner, lease_expires_at';\n\nexport function itemOf(row: ItemRow): QueueItem {\n\tconst item: QueueItem = {\n\t\tid: row.id,\n\t\tfrom: row.sender,\n\t\trecipients: JSON.parse(row.recipients) as RecipientState[],\n\t\tsize: row.size,\n\t\tcreatedAt: row.created_at,\n\t\tnextAttemptAt: row.next_attempt_at,\n\t\tattempts: row.attempts,\n\t\tdelayNotified: row.delay_notified === 1,\n\t};\n\tif (row.lease_owner === null || row.lease_expires_at === null) return item;\n\treturn {\n\t\t...item,\n\t\tlease: { owner: row.lease_owner, expiresAt: row.lease_expires_at },\n\t};\n}\n\n/** The named parameters that write an item's state back. */\nexport function stateOf(item: QueueItem) {\n\treturn {\n\t\tid: item.id,\n\t\trecipients: JSON.stringify(item.recipients),\n\t\tnext_attempt_at: item.nextAttemptAt,\n\t\tattempts: item.attempts,\n\t\tdelay_notified: item.delayNotified ? 1 : 0,\n\t\tlease_owner: item.lease?.owner ?? null,\n\t\tlease_expires_at: item.lease?.expiresAt ?? null,\n\t};\n}\n",
|
|
8
8
|
"import type { Database } from 'bun:sqlite';\nimport {\n\tapplyAttempt,\n\tcheckClaim,\n\tcheckList,\n\tcheckMaxItems,\n\tcheckNewItem,\n\tcheckOwner,\n\tcheckResult,\n\tcheckTime,\n\tisDone,\n\tnewItem,\n} from '../contract/checks';\nimport type { QueueStore } from '../contract/queue-store';\nimport type {\n\tAddOptions,\n\tAttemptResult,\n\tClaimRequest,\n\tNewQueueItem,\n\tQueueItem,\n\tQueueListOptions,\n} from '../contract/types';\nimport { QueueError } from '../errors';\nimport { openDatabase } from './open';\nimport type { SqliteQueueStoreOptions } from './options';\nimport { COLUMNS, type ItemRow, itemOf, stateOf } from './rows';\n\nexport type { SqliteQueueStoreOptions } from './options';\n\nconst DUE = `next_attempt_at <= $now\n\tAND (lease_owner IS NULL OR lease_expires_at <= $now)`;\n\n/**\n * A `QueueStore` on `bun:sqlite`: one directory holding `queue.sqlite`,\n * which several processes on one machine may open together. Every\n * operation is one transaction — a claim is a single `UPDATE … RETURNING`\n * — so two workers never take the same item. Messages live in a table of\n * their own, dropped with their item.\n */\nexport class SqliteQueueStore implements QueueStore {\n\treadonly #db: Database;\n\t#closed = false;\n\n\tprivate constructor(db: Database) {\n\t\tthis.#db = db;\n\t}\n\n\t/** Opens the store in `directory`, creating it if need be; what fails is `INVALID`. */\n\tstatic open(options: SqliteQueueStoreOptions): SqliteQueueStore {\n\t\treturn new SqliteQueueStore(openDatabase(options));\n\t}\n\n\t/** Lets go of the database; closing twice is fine. */\n\tclose(): void {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#db.close();\n\t}\n\n\tget #open(): Database {\n\t\tif (this.#closed) {\n\t\t\tthrow new QueueError('CLOSED', 'The queue store is closed');\n\t\t}\n\t\treturn this.#db;\n\t}\n\n\t#row(id: string, owner?: string): ItemRow | null {\n\t\tconst db = this.#open;\n\t\tif (owner === undefined) {\n\t\t\treturn db\n\t\t\t\t.query<ItemRow, [string]>(`SELECT ${COLUMNS} FROM items WHERE id = ?`)\n\t\t\t\t.get(id);\n\t\t}\n\t\treturn db\n\t\t\t.query<ItemRow, [string, string]>(\n\t\t\t\t`SELECT ${COLUMNS} FROM items WHERE id = ? AND lease_owner = ?`,\n\t\t\t)\n\t\t\t.get(id, owner);\n\t}\n\n\t#write(item: QueueItem): void {\n\t\tthis.#open\n\t\t\t.query(\n\t\t\t\t`UPDATE items SET recipients = $recipients,\n\t\t\t\tnext_attempt_at = $next_attempt_at, attempts = $attempts,\n\t\t\t\tdelay_notified = $delay_notified, lease_owner = $lease_owner,\n\t\t\t\tlease_expires_at = $lease_expires_at WHERE id = $id`,\n\t\t\t)\n\t\t\t.run(stateOf(item));\n\t}\n\n\tasync add(item: NewQueueItem, options: AddOptions = {}): Promise<QueueItem> {\n\t\tcheckNewItem(item);\n\t\tconst max = checkMaxItems(options.maxItems);\n\t\tconst db = this.#open;\n\t\tconst added = newItem(crypto.randomUUID(), item);\n\t\tdb.transaction(() => {\n\t\t\tif (max !== undefined) {\n\t\t\t\tconst { n } = db\n\t\t\t\t\t.query<{ n: number }, []>('SELECT count(*) AS n FROM items')\n\t\t\t\t\t.get() as { n: number };\n\t\t\t\tif (n >= max) {\n\t\t\t\t\tthrow new QueueError(\n\t\t\t\t\t\t'QUEUE_FULL',\n\t\t\t\t\t\t`The queue holds ${n} items, its limit`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdb.query(\n\t\t\t\t`INSERT INTO items (id, sender, recipients, size, created_at,\n\t\t\t\tnext_attempt_at, attempts, delay_notified)\n\t\t\t\tVALUES ($id, $sender, $recipients, $size, $created_at,\n\t\t\t\t$next_attempt_at, 0, 0)`,\n\t\t\t).run({\n\t\t\t\tid: added.id,\n\t\t\t\tsender: added.from,\n\t\t\t\trecipients: JSON.stringify(added.recipients),\n\t\t\t\tsize: added.size,\n\t\t\t\tcreated_at: added.createdAt,\n\t\t\t\tnext_attempt_at: added.nextAttemptAt,\n\t\t\t});\n\t\t\tdb.query('INSERT INTO messages (item_id, content) VALUES (?, ?)').run(\n\t\t\t\tadded.id,\n\t\t\t\titem.message,\n\t\t\t);\n\t\t}).immediate();\n\t\treturn added;\n\t}\n\n\tasync get(id: string): Promise<QueueItem | undefined> {\n\t\tconst row = this.#row(id);\n\t\treturn row ? itemOf(row) : undefined;\n\t}\n\n\tasync list(options?: QueueListOptions): Promise<QueueItem[]> {\n\t\tconst { offset, limit } = checkList(options);\n\t\treturn this.#open\n\t\t\t.query<ItemRow, [number, number]>(\n\t\t\t\t`SELECT ${COLUMNS} FROM items ORDER BY next_attempt_at, seq\n\t\t\t\tLIMIT ? OFFSET ?`,\n\t\t\t)\n\t\t\t.all(limit, offset)\n\t\t\t.map(itemOf);\n\t}\n\n\tasync count(): Promise<number> {\n\t\tconst row = this.#open\n\t\t\t.query<{ n: number }, []>('SELECT count(*) AS n FROM items')\n\t\t\t.get();\n\t\treturn row?.n ?? 0;\n\t}\n\n\tasync readMessage(id: string): Promise<Uint8Array | undefined> {\n\t\tconst row = this.#open\n\t\t\t.query<{ content: Uint8Array }, [string]>(\n\t\t\t\t'SELECT content FROM messages WHERE item_id = ?',\n\t\t\t)\n\t\t\t.get(id);\n\t\treturn row ? new Uint8Array(row.content) : undefined;\n\t}\n\n\tasync claim(request: ClaimRequest): Promise<QueueItem | undefined> {\n\t\tcheckClaim(request);\n\t\tconst row = this.#open\n\t\t\t.query<ItemRow, Record<string, string | number>>(\n\t\t\t\t`UPDATE items SET lease_owner = $owner, lease_expires_at = $expires\n\t\t\t\tWHERE seq = (SELECT seq FROM items WHERE ${DUE}\n\t\t\t\t\tORDER BY next_attempt_at, seq LIMIT 1)\n\t\t\t\tRETURNING ${COLUMNS}`,\n\t\t\t)\n\t\t\t.get({\n\t\t\t\towner: request.owner,\n\t\t\t\tnow: request.now,\n\t\t\t\texpires: request.now + request.leaseMs,\n\t\t\t});\n\t\treturn row ? itemOf(row) : undefined;\n\t}\n\n\tasync renew(id: string, owner: string, expiresAt: number): Promise<boolean> {\n\t\tcheckOwner(owner);\n\t\tcheckTime('expiresAt', expiresAt);\n\t\tconst { changes } = this.#open\n\t\t\t.query(\n\t\t\t\t'UPDATE items SET lease_expires_at = ? WHERE id = ? AND lease_owner = ?',\n\t\t\t)\n\t\t\t.run(expiresAt, id, owner);\n\t\treturn changes > 0;\n\t}\n\n\tasync complete(\n\t\tid: string,\n\t\towner: string,\n\t\tresult: AttemptResult,\n\t): Promise<QueueItem | undefined> {\n\t\tcheckOwner(owner);\n\t\tcheckResult(result);\n\t\tconst db = this.#open;\n\t\treturn db\n\t\t\t.transaction(() => {\n\t\t\t\tconst row = this.#row(id, owner);\n\t\t\t\tif (!row) return undefined;\n\t\t\t\tconst item = applyAttempt(itemOf(row), result);\n\t\t\t\tif (isDone(item)) {\n\t\t\t\t\tdb.query('DELETE FROM items WHERE id = ?').run(id);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#write(item);\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t})\n\t\t\t.immediate();\n\t}\n\n\tasync reschedule(id: string, at: number, owner?: string): Promise<boolean> {\n\t\tcheckTime('at', at);\n\t\tconst db = this.#open;\n\t\tif (owner === undefined) {\n\t\t\treturn (\n\t\t\t\tdb\n\t\t\t\t\t.query('UPDATE items SET next_attempt_at = ? WHERE id = ?')\n\t\t\t\t\t.run(at, id).changes > 0\n\t\t\t);\n\t\t}\n\t\tcheckOwner(owner);\n\t\tconst { changes } = db\n\t\t\t.query(\n\t\t\t\t`UPDATE items SET next_attempt_at = ?, lease_owner = NULL,\n\t\t\t\tlease_expires_at = NULL WHERE id = ? AND lease_owner = ?`,\n\t\t\t)\n\t\t\t.run(at, id, owner);\n\t\treturn changes > 0;\n\t}\n\n\tasync cancel(id: string): Promise<QueueItem | undefined> {\n\t\tconst db = this.#open;\n\t\treturn db\n\t\t\t.transaction(() => {\n\t\t\t\tconst row = this.#row(id);\n\t\t\t\tif (!row) return undefined;\n\t\t\t\tdb.query('DELETE FROM items WHERE id = ?').run(id);\n\t\t\t\treturn itemOf(row);\n\t\t\t})\n\t\t\t.immediate();\n\t}\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": "
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "1AE80C41E9F1FD2664756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
package/dist/text.d.ts
CHANGED
|
@@ -4,11 +4,17 @@ export declare function hasControl(text: string): boolean;
|
|
|
4
4
|
/** Each control character replaced by `by`. */
|
|
5
5
|
export declare function replaceControls(text: string, by: string): string;
|
|
6
6
|
/**
|
|
7
|
-
* Every control character (CR and LF included) as a space,
|
|
8
|
-
* as one, cut at `max` characters with
|
|
9
|
-
*
|
|
7
|
+
* Every control character (CR and LF included) as a space, a lone
|
|
8
|
+
* surrogate as U+FFFD, runs of space as one, cut at `max` characters with
|
|
9
|
+
* `...`, never inside a surrogate pair: what a reply leaves in an item,
|
|
10
|
+
* an event and a DSN.
|
|
10
11
|
*/
|
|
11
12
|
export declare function cleanText(text: string, max: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Text every store can keep: no NUL (PostgreSQL's `text` and `jsonb` hold
|
|
15
|
+
* none) and no lone surrogate. `cleanText`'s output always is.
|
|
16
|
+
*/
|
|
17
|
+
export declare const isStorable: (text: string) => boolean;
|
|
12
18
|
/** `cleanText`, then anything not printable ASCII as `?`: for a `message/delivery-status` field. */
|
|
13
19
|
export declare const asciiText: (text: string, max: number) => string;
|
|
14
20
|
//# sourceMappingURL=text.d.ts.map
|
package/dist/text.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAMlF,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKhD;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAMlF,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKhD;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D;AAaD;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,OACE,CAAC;AAE7C,oGAAoG;AACpG,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,KAAG,MACT,CAAC"}
|
package/docs/README.md
CHANGED
|
@@ -5,6 +5,6 @@ long one.
|
|
|
5
5
|
|
|
6
6
|
| Page | Read it when |
|
|
7
7
|
| --- | --- |
|
|
8
|
-
| [Guide](guide.md) | enqueuing, choosing a route (MX, a smarthost, per domain), tuning the retry schedule and the DSNs, running several workers, listening to events, testing with a fake clock and sender, or writing a store of your own |
|
|
8
|
+
| [Guide](guide.md) | enqueuing, choosing a route (MX, a smarthost, per domain), tuning the retry schedule and the DSNs, running several workers or instances on PostgreSQL or Redis, listening to events, testing with a fake clock and sender, or writing a store of your own |
|
|
9
9
|
| [Troubleshooting](troubleshooting.md) | the queue or a store threw a `QueueError`, the `error` event fired, or mail stays deferred |
|
|
10
10
|
| [Roadmap](roadmap.md) | wondering what is coming, and what is not planned |
|