@prosody-events/prosody 0.5.1 → 0.6.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.
- package/README.md +161 -57
- package/bindings.d.ts +302 -404
- package/bindings.js +168 -85
- package/index.d.ts +30 -962
- package/index.js +42 -1898
- package/lib/client.d.ts +232 -0
- package/lib/client.js +347 -0
- package/lib/context.d.ts +161 -0
- package/lib/context.js +86 -0
- package/lib/errors.d.ts +103 -0
- package/lib/errors.js +102 -0
- package/lib/logging.d.ts +75 -0
- package/lib/logging.js +99 -0
- package/lib/payload.d.ts +59 -0
- package/lib/state/bridge.js +103 -0
- package/lib/state/codec.js +206 -0
- package/lib/state/definitions.d.ts +233 -0
- package/lib/state/definitions.js +151 -0
- package/lib/state/deque.d.ts +75 -0
- package/lib/state/deque.js +77 -0
- package/lib/state/handle.d.ts +25 -0
- package/lib/state/handle.js +26 -0
- package/lib/state/iterator.js +66 -0
- package/lib/state/map.d.ts +94 -0
- package/lib/state/map.js +79 -0
- package/lib/state/published.d.ts +113 -0
- package/lib/state/published.js +147 -0
- package/lib/state/query.d.ts +85 -0
- package/lib/state/query.js +206 -0
- package/lib/state/set.d.ts +52 -0
- package/lib/state/set.js +54 -0
- package/lib/state/value.d.ts +33 -0
- package/lib/state/value.js +31 -0
- package/package.json +21 -20
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The double-ended-queue keyed-state handle.
|
|
3
|
+
* @module lib/state/deque
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { JsonValue } from "../payload";
|
|
7
|
+
import type { StateTransaction } from "./handle";
|
|
8
|
+
import type { PositionQueryOptions, ScanDirection } from "./query";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Typed handle over a double-ended-queue keyed-state collection, vended by
|
|
12
|
+
* `Context.state()`. Valid only within the handler invocation (attempt) that
|
|
13
|
+
* vended it. Every method opens its own per-operation trace span.
|
|
14
|
+
* A failed call rejects with a {@link PermanentStateError} or a
|
|
15
|
+
* {@link TransientStateError}. A write of a value with no JSON form rejects
|
|
16
|
+
* with a {@link TransientStateError}.
|
|
17
|
+
*/
|
|
18
|
+
export declare class DequeState<T = JsonValue> {
|
|
19
|
+
/** Vended only by {@link Context#state}; not constructible directly. */
|
|
20
|
+
private constructor(native: unknown);
|
|
21
|
+
/**
|
|
22
|
+
* Appends an element at the back. The item type excludes `null` and
|
|
23
|
+
* `undefined`, because a top-level `null` is not a storable element. At run
|
|
24
|
+
* time Prosody rejects JSON `null` with a {@link PermanentStateError}. A
|
|
25
|
+
* nested `null` is stored.
|
|
26
|
+
*/
|
|
27
|
+
push(item: NonNullable<T>): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Prepends an element at the front. The item type excludes `null`/`undefined`
|
|
30
|
+
* (via {@link !NonNullable}); see {@link DequeState#push}.
|
|
31
|
+
*/
|
|
32
|
+
unshift(item: NonNullable<T>): Promise<void>;
|
|
33
|
+
/** Removes and returns the back element, or null when empty. */
|
|
34
|
+
pop(): Promise<T | null>;
|
|
35
|
+
/** Removes and returns the front element, or null when empty. */
|
|
36
|
+
shift(): Promise<T | null>;
|
|
37
|
+
/** Returns the number of live elements. */
|
|
38
|
+
length(): Promise<number>;
|
|
39
|
+
/** Reports whether the deque holds no live elements. */
|
|
40
|
+
isEmpty(): Promise<boolean>;
|
|
41
|
+
/** Removes every element. */
|
|
42
|
+
clear(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Reads the element at `index`, like `Array.prototype.at`: a non-negative
|
|
45
|
+
* `index` counts from the front (`0` is the front), a negative `index` counts
|
|
46
|
+
* back from the end (`-1` is the back). Any out-of-range position — including
|
|
47
|
+
* every index on an empty deque — resolves to null. `index` must be a safe
|
|
48
|
+
* integer; a fractional, `NaN`, or infinite value is a caller mistake,
|
|
49
|
+
* rejected with a {@link TransientStateError} (it retries and stays visible).
|
|
50
|
+
*
|
|
51
|
+
* A non-negative `index` and `at(-1)` make a single read. Any other negative
|
|
52
|
+
* `index` is resolved against the current {@link DequeState#length}, so it
|
|
53
|
+
* makes an extra read.
|
|
54
|
+
*
|
|
55
|
+
* Under a TTL, an expired element reads as null. This is also true for an
|
|
56
|
+
* expired front or back element when live elements remain inside the deque.
|
|
57
|
+
*/
|
|
58
|
+
at(index: number): Promise<T | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Async iterator over the live elements in index order. Pass a direction or
|
|
61
|
+
* a {@link PositionQueryOptions} to select elements. Valid only within the handler
|
|
62
|
+
* invocation (attempt) that opened it; early exit from a `for await` loop
|
|
63
|
+
* closes the underlying cursor.
|
|
64
|
+
*/
|
|
65
|
+
values(
|
|
66
|
+
options?: ScanDirection | PositionQueryOptions,
|
|
67
|
+
): AsyncIterableIterator<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Forward iteration over the elements. Valid only within the handler
|
|
70
|
+
* invocation (attempt) that opened it.
|
|
71
|
+
*/
|
|
72
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface DequeState<T = JsonValue> extends StateTransaction {}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The double-ended-queue keyed-state handle.
|
|
3
|
+
* @module lib/state/deque
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { stateOp } = require("./bridge");
|
|
8
|
+
const { StateHandle } = require("./handle");
|
|
9
|
+
const { stateIterator } = require("./iterator");
|
|
10
|
+
const { dequePosition, positionQuery } = require("./query");
|
|
11
|
+
|
|
12
|
+
/** Typed handle over a double-ended-queue keyed-state collection. */
|
|
13
|
+
class DequeState extends StateHandle {
|
|
14
|
+
push(item) {
|
|
15
|
+
return stateOp((carrier) =>
|
|
16
|
+
this.native.pushBack(this.items.encode(item), carrier),
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
unshift(item) {
|
|
21
|
+
return stateOp((carrier) =>
|
|
22
|
+
this.native.pushFront(this.items.encode(item), carrier),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pop() {
|
|
27
|
+
return stateOp((carrier) => this.native.popBack(carrier)).then(
|
|
28
|
+
this.items.decode,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
shift() {
|
|
33
|
+
return stateOp((carrier) => this.native.popFront(carrier)).then(
|
|
34
|
+
this.items.decode,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
length() {
|
|
39
|
+
return stateOp((carrier) => this.native.len(carrier));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
isEmpty() {
|
|
43
|
+
return stateOp((carrier) => this.native.isEmpty(carrier));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
clear() {
|
|
47
|
+
return stateOp((carrier) => this.native.clear(carrier));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async at(index) {
|
|
51
|
+
if (index === -1) {
|
|
52
|
+
return this.items.decode(
|
|
53
|
+
await stateOp((carrier) => this.native.peekBack(carrier)),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const position = await dequePosition(index, () => this.length());
|
|
57
|
+
if (position === null) return null;
|
|
58
|
+
return this.items.decode(
|
|
59
|
+
await stateOp((carrier) => this.native.get(position, carrier)),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
values(options) {
|
|
64
|
+
const query = positionQuery(options);
|
|
65
|
+
return stateIterator(this.native.values(query), (item) =>
|
|
66
|
+
this.items.decode(item),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
[Symbol.asyncIterator]() {
|
|
71
|
+
return this.values();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
DequeState,
|
|
77
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The commit and rollback methods of every state handle, and their outcome.
|
|
3
|
+
* @module lib/state/handle
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The effect of `commit()` or `rollback()`. `"applied"` means the call wrote or
|
|
8
|
+
* discarded buffered operations. `"noOp"` means nothing was buffered.
|
|
9
|
+
*/
|
|
10
|
+
export type StoreOutcome = "applied" | "noOp";
|
|
11
|
+
|
|
12
|
+
/** The commit and rollback methods of every state handle. */
|
|
13
|
+
export interface StateTransaction {
|
|
14
|
+
/**
|
|
15
|
+
* Durably commits the buffered operations mid-handler (at-least-once). The
|
|
16
|
+
* committed changes survive a later rollback or a failed event. Resolves to
|
|
17
|
+
* `"applied"` when it wrote buffered operations, or `"noOp"`.
|
|
18
|
+
*/
|
|
19
|
+
commit(): Promise<StoreOutcome>;
|
|
20
|
+
/**
|
|
21
|
+
* Discards buffered uncommitted operations back to the committed floor.
|
|
22
|
+
* Resolves to `"applied"` when it discarded buffered operations, or `"noOp"`.
|
|
23
|
+
*/
|
|
24
|
+
rollback(): Promise<StoreOutcome>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base class of the keyed-state handles: commit and rollback.
|
|
3
|
+
* @module lib/state/handle
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { defineHidden, stateOp } = require("./bridge");
|
|
8
|
+
|
|
9
|
+
/** The base class of every keyed-state handle: commit and rollback. */
|
|
10
|
+
class StateHandle {
|
|
11
|
+
constructor(native, items) {
|
|
12
|
+
defineHidden(this, { native, items });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
commit() {
|
|
16
|
+
return stateOp((carrier) => this.native.commit(carrier));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
rollback() {
|
|
20
|
+
return stateOp((carrier) => this.native.rollback(carrier));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
StateHandle,
|
|
26
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapts a chunked native scan cursor to a JavaScript async iterator.
|
|
3
|
+
* @module lib/state/iterator
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { injectedCarrier, toStateError } = require("./bridge");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adapts a chunked native scan cursor to an async generator. Each native pull
|
|
11
|
+
* gets a fresh trace carrier and records no span. Each `next()` call takes the
|
|
12
|
+
* next item of the held chunk without an N-API call. A native `null` means
|
|
13
|
+
* the scan is done. The generator queues concurrent `next()` and `return()`
|
|
14
|
+
* calls, so no item is yielded twice and no close runs during a pull.
|
|
15
|
+
*
|
|
16
|
+
* The end of the scan, an early exit from a `for await` loop, and a pull or
|
|
17
|
+
* decode error all close the cursor. Every failure a caller sees goes through
|
|
18
|
+
* `toStateError`.
|
|
19
|
+
*
|
|
20
|
+
* Owned cursors stay fenced to their attempt. Published cursors stay valid
|
|
21
|
+
* with their reader.
|
|
22
|
+
* @param {object} cursor - The native scan cursor.
|
|
23
|
+
* @param {(item: *) => *} transform - Maps each raw item to the yielded value.
|
|
24
|
+
* @returns {AsyncGenerator<*>} The async iterator.
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
async function* stateIterator(cursor, transform) {
|
|
28
|
+
let failed = false;
|
|
29
|
+
try {
|
|
30
|
+
for (;;) {
|
|
31
|
+
const chunk = await cursor.nextChunk(injectedCarrier());
|
|
32
|
+
if (chunk === null) return;
|
|
33
|
+
for (let index = 0; index < chunk.length; index += 1) {
|
|
34
|
+
const item = chunk[index];
|
|
35
|
+
// Release consumed values even while the rest of a large chunk remains.
|
|
36
|
+
chunk[index] = undefined;
|
|
37
|
+
yield transform(item);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
failed = true;
|
|
42
|
+
throw toStateError(error);
|
|
43
|
+
} finally {
|
|
44
|
+
await close(cursor, failed);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Closes a native scan cursor. After a failure the close is best effort and
|
|
50
|
+
* never hides that error.
|
|
51
|
+
* @param {object} cursor - The native scan cursor.
|
|
52
|
+
* @param {boolean} quietly - Whether to ignore a close failure.
|
|
53
|
+
* @returns {Promise<void>} Resolves when the cursor is closed.
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
async function close(cursor, quietly) {
|
|
57
|
+
try {
|
|
58
|
+
await cursor.close();
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (!quietly) throw toStateError(error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
stateIterator,
|
|
66
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ordered-map keyed-state handle.
|
|
3
|
+
* @module lib/state/map
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { JsonValue } from "../payload";
|
|
7
|
+
import type { StateTransaction } from "./handle";
|
|
8
|
+
import type { KeyQueryOptions, ScanDirection } from "./query";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Typed handle over an ordered-map keyed-state collection, vended by
|
|
12
|
+
* `Context.state()`. Map keys are always `string`. Valid only within the
|
|
13
|
+
* handler invocation (attempt) that vended it. Every method opens its own
|
|
14
|
+
* per-operation trace span.
|
|
15
|
+
* A failed call rejects with a {@link PermanentStateError} or a
|
|
16
|
+
* {@link TransientStateError}. A write of a value with no JSON form rejects
|
|
17
|
+
* with a {@link TransientStateError}.
|
|
18
|
+
*/
|
|
19
|
+
export declare class MapState<V = JsonValue> {
|
|
20
|
+
/** Vended only by {@link Context#state}; not constructible directly. */
|
|
21
|
+
private constructor(native: unknown);
|
|
22
|
+
/** Reads the value for `key`, or null when the key is absent. */
|
|
23
|
+
get(key: string): Promise<V | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Reads several keys in one call. The result has one entry per key, in the
|
|
26
|
+
* order given, so `result[i]` is the value for `keys[i]`. An absent key reads
|
|
27
|
+
* as `null`. A repeated key gets an entry at each position. No other change
|
|
28
|
+
* to the state of this event occurs during the read.
|
|
29
|
+
*/
|
|
30
|
+
getMany(keys: readonly string[]): Promise<(V | null)[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Reports whether `key` currently has a stored value. It skips the value
|
|
33
|
+
* decode and the resolver. A message map answers with no Kafka fetch, so it
|
|
34
|
+
* can report `true` for a message that Kafka no longer holds. A cache miss
|
|
35
|
+
* still reads the store, but the call costs less than {@link MapState#get}.
|
|
36
|
+
*/
|
|
37
|
+
has(key: string): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Tests several keys for presence in one read. `result[i]` answers
|
|
40
|
+
* `keys[i]`. Like {@link MapState#has}, it skips the value decode.
|
|
41
|
+
*/
|
|
42
|
+
hasMany(keys: readonly string[]): Promise<boolean[]>;
|
|
43
|
+
/** Reports whether the map holds no live entries. */
|
|
44
|
+
isEmpty(): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Inserts or overwrites `key`. The value type excludes `null` and
|
|
47
|
+
* `undefined`, because a top-level `null` is not a storable value. At run
|
|
48
|
+
* time Prosody rejects JSON `null` with a {@link PermanentStateError}; use
|
|
49
|
+
* {@link MapState#delete} to remove an entry. A nested `null` is stored.
|
|
50
|
+
*/
|
|
51
|
+
set(key: string, value: NonNullable<V>): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Removes `key`.
|
|
54
|
+
*
|
|
55
|
+
* Unlike `Map#delete`, it returns no "was present" flag, because that flag
|
|
56
|
+
* needs a read on every delete.
|
|
57
|
+
*/
|
|
58
|
+
delete(key: string): Promise<void>;
|
|
59
|
+
/** Removes every entry. */
|
|
60
|
+
clear(): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Async iterator over the live `[key, value]` entries in key order. Pass a
|
|
63
|
+
* direction or a {@link KeyQueryOptions} to select entries. Valid only within the
|
|
64
|
+
* handler invocation (attempt) that opened it; early exit from a
|
|
65
|
+
* `for await` loop closes the underlying cursor.
|
|
66
|
+
*/
|
|
67
|
+
entries(
|
|
68
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
69
|
+
): AsyncIterableIterator<[string, V]>;
|
|
70
|
+
/**
|
|
71
|
+
* Async iterator over the live keys in key order. Takes the same options as
|
|
72
|
+
* {@link MapState#entries}. Skips the value decode and the resolver, so a message-backed map enumerates keys with zero Kafka
|
|
73
|
+
* fetches; it still reads presence, so it is not zero-I/O. Valid only within
|
|
74
|
+
* the handler invocation (attempt) that opened it; early exit from a
|
|
75
|
+
* `for await` loop closes the underlying cursor.
|
|
76
|
+
*/
|
|
77
|
+
keys(
|
|
78
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
79
|
+
): AsyncIterableIterator<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Async iterator over the live values in key order. Takes the same options
|
|
82
|
+
* as {@link MapState#entries}. Valid only within the handler invocation
|
|
83
|
+
* (attempt) that opened it; early exit from a `for await` loop closes the
|
|
84
|
+
* underlying cursor.
|
|
85
|
+
*/
|
|
86
|
+
values(options?: ScanDirection | KeyQueryOptions): AsyncIterableIterator<V>;
|
|
87
|
+
/**
|
|
88
|
+
* Forward iteration over `[key, value]` entries. Valid only within the
|
|
89
|
+
* handler invocation (attempt) that opened it.
|
|
90
|
+
*/
|
|
91
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<[string, V]>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface MapState<V = JsonValue> extends StateTransaction {}
|
package/lib/state/map.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ordered-map keyed-state handle.
|
|
3
|
+
* @module lib/state/map
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { stateOp } = require("./bridge");
|
|
8
|
+
const { StateHandle } = require("./handle");
|
|
9
|
+
const { stateIterator } = require("./iterator");
|
|
10
|
+
const { keyQuery } = require("./query");
|
|
11
|
+
|
|
12
|
+
/** Typed handle over an ordered-map keyed-state collection. */
|
|
13
|
+
class MapState extends StateHandle {
|
|
14
|
+
get(key) {
|
|
15
|
+
return stateOp((carrier) => this.native.get(key, carrier)).then(
|
|
16
|
+
this.items.decode,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getMany(keys) {
|
|
21
|
+
return stateOp((carrier) => this.native.getMany(keys, carrier)).then(
|
|
22
|
+
(items) => items.map(this.items.decode),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
has(key) {
|
|
27
|
+
return stateOp((carrier) => this.native.contains(key, carrier));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
hasMany(keys) {
|
|
31
|
+
return stateOp((carrier) => this.native.containsMany(keys, carrier));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
isEmpty() {
|
|
35
|
+
return stateOp((carrier) => this.native.isEmpty(carrier));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set(key, value) {
|
|
39
|
+
return stateOp((carrier) =>
|
|
40
|
+
this.native.set(key, this.items.encode(value), carrier),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
delete(key) {
|
|
45
|
+
return stateOp((carrier) => this.native.remove(key, carrier));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
clear() {
|
|
49
|
+
return stateOp((carrier) => this.native.clear(carrier));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
entries(options) {
|
|
53
|
+
const query = keyQuery(options);
|
|
54
|
+
return stateIterator(this.native.entries(query), ([key, item]) => [
|
|
55
|
+
key,
|
|
56
|
+
this.items.decode(item),
|
|
57
|
+
]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
keys(options) {
|
|
61
|
+
const query = keyQuery(options);
|
|
62
|
+
return stateIterator(this.native.keys(query), (key) => key);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
values(options) {
|
|
66
|
+
const query = keyQuery(options);
|
|
67
|
+
return stateIterator(this.native.entries(query), ([, item]) =>
|
|
68
|
+
this.items.decode(item),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
[Symbol.asyncIterator]() {
|
|
73
|
+
return this.entries();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
MapState,
|
|
79
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The read-only readers of published value, map, set, and deque collections.
|
|
3
|
+
*
|
|
4
|
+
* `ProsodyClient.state(subsystem, definition)` opens a reader. A reader reads
|
|
5
|
+
* the committed state of another consumer group, so every read takes the
|
|
6
|
+
* partition key. It is independent of subscription and stays valid while its
|
|
7
|
+
* client runs. A failed read rejects with a {@link TransientStateError} or a
|
|
8
|
+
* {@link PermanentStateError}, like a read through an owned handle. A reader
|
|
9
|
+
* error at open, such as a zero `readCache` TTL, rejects `state()` the same way.
|
|
10
|
+
* @module lib/state/published
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { JsonValue } from "../payload";
|
|
14
|
+
import type { PermanentStateError, TransientStateError } from "../errors";
|
|
15
|
+
import type {
|
|
16
|
+
KeyQueryOptions,
|
|
17
|
+
PositionQueryOptions,
|
|
18
|
+
ScanDirection,
|
|
19
|
+
} from "./query";
|
|
20
|
+
|
|
21
|
+
/** Per-collection cache override for published reads. */
|
|
22
|
+
export interface ReadCacheOptions {
|
|
23
|
+
/** Cache duration in milliseconds. */
|
|
24
|
+
ttlMs: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Read-only published value collection. */
|
|
28
|
+
export declare class PublishedValue<T = JsonValue> {
|
|
29
|
+
private constructor();
|
|
30
|
+
|
|
31
|
+
/** Reads the committed value for `key`, or null when it is absent. */
|
|
32
|
+
get(key: string): Promise<T | null>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Read-only published map collection. */
|
|
36
|
+
export declare class PublishedMap<V = JsonValue> {
|
|
37
|
+
private constructor();
|
|
38
|
+
|
|
39
|
+
/** Reads the committed value of `mapKey` for `key`, or null when absent. */
|
|
40
|
+
get(key: string, mapKey: string): Promise<V | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Reads several map keys in one call. The result has one entry per map key,
|
|
43
|
+
* in the order given, and an absent map key reads as null.
|
|
44
|
+
*/
|
|
45
|
+
getMany(key: string, mapKeys: readonly string[]): Promise<Array<V | null>>;
|
|
46
|
+
/** Reports whether the map for `key` holds `mapKey`. */
|
|
47
|
+
has(key: string, mapKey: string): Promise<boolean>;
|
|
48
|
+
/** Tests several map keys in one call. `result[i]` answers `mapKeys[i]`. */
|
|
49
|
+
hasMany(key: string, mapKeys: readonly string[]): Promise<boolean[]>;
|
|
50
|
+
/** Reports whether the map for `key` holds no entries. */
|
|
51
|
+
isEmpty(key: string): Promise<boolean>;
|
|
52
|
+
/** Iterates the selected `[mapKey, value]` entries in key order. */
|
|
53
|
+
entries(
|
|
54
|
+
key: string,
|
|
55
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
56
|
+
): AsyncIterableIterator<[string, V]>;
|
|
57
|
+
/** Iterates the selected map keys in key order. */
|
|
58
|
+
keys(
|
|
59
|
+
key: string,
|
|
60
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
61
|
+
): AsyncIterableIterator<string>;
|
|
62
|
+
/** Iterates the values of the selected entries in key order. */
|
|
63
|
+
values(
|
|
64
|
+
key: string,
|
|
65
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
66
|
+
): AsyncIterableIterator<V>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Read-only published set collection. */
|
|
70
|
+
export declare class PublishedSet {
|
|
71
|
+
private constructor();
|
|
72
|
+
|
|
73
|
+
/** Reports whether the set for `key` holds `member`. */
|
|
74
|
+
has(key: string, member: string): Promise<boolean>;
|
|
75
|
+
/** Tests several members in one call. `result[i]` answers `members[i]`. */
|
|
76
|
+
hasMany(key: string, members: readonly string[]): Promise<boolean[]>;
|
|
77
|
+
/** Reports whether the set for `key` holds no members. */
|
|
78
|
+
isEmpty(key: string): Promise<boolean>;
|
|
79
|
+
/** Iterates the selected members in order. */
|
|
80
|
+
keys(
|
|
81
|
+
key: string,
|
|
82
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
83
|
+
): AsyncIterableIterator<string>;
|
|
84
|
+
/** The same iterator as `keys`, as on the JavaScript `Set`. */
|
|
85
|
+
values(
|
|
86
|
+
key: string,
|
|
87
|
+
options?: ScanDirection | KeyQueryOptions,
|
|
88
|
+
): AsyncIterableIterator<string>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Read-only published deque collection. */
|
|
92
|
+
export declare class PublishedDeque<T = JsonValue> {
|
|
93
|
+
private constructor();
|
|
94
|
+
|
|
95
|
+
/** Reads the number of values in the deque for `key`. */
|
|
96
|
+
length(key: string): Promise<number>;
|
|
97
|
+
/** Reports whether the deque for `key` holds no values. */
|
|
98
|
+
isEmpty(key: string): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Reads the value at `index`, or null when the position is out of range.
|
|
101
|
+
* `0` is the front and `-1` is the back. A negative index other than `-1`
|
|
102
|
+
* also reads the length, so it makes two reads. Under a TTL, an expired
|
|
103
|
+
* element reads as null. This is also true for an expired front or back
|
|
104
|
+
* element when live elements remain inside the deque.
|
|
105
|
+
* @throws TransientStateError if `index` is not a safe integer.
|
|
106
|
+
*/
|
|
107
|
+
at(key: string, index: number): Promise<T | null>;
|
|
108
|
+
/** Iterates the selected values from the front. */
|
|
109
|
+
values(
|
|
110
|
+
key: string,
|
|
111
|
+
options?: ScanDirection | PositionQueryOptions,
|
|
112
|
+
): AsyncIterableIterator<T>;
|
|
113
|
+
}
|