@anabranch/eventlog 0.1.3 → 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/README.md +8 -8
- package/esm/adapter.d.ts +83 -62
- package/esm/adapter.d.ts.map +1 -1
- package/esm/adapter.js +0 -9
- package/esm/errors.d.ts +2 -7
- package/esm/errors.d.ts.map +1 -1
- package/esm/errors.js +9 -21
- package/esm/eventlog.d.ts +74 -92
- package/esm/eventlog.d.ts.map +1 -1
- package/esm/eventlog.js +93 -113
- package/esm/in-memory.d.ts +15 -34
- package/esm/in-memory.d.ts.map +1 -1
- package/esm/in-memory.js +139 -167
- package/esm/index.d.ts +8 -8
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,26 +10,26 @@ consumer resumption.
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
|
-
import { createInMemory, EventLog } from
|
|
13
|
+
import { createInMemory, EventLog } from '@anabranch/eventlog'
|
|
14
14
|
|
|
15
|
-
const connector = createInMemory()
|
|
16
|
-
const log = await EventLog.connect(connector).run()
|
|
15
|
+
const connector = createInMemory()
|
|
16
|
+
const log = await EventLog.connect(connector).run()
|
|
17
17
|
|
|
18
18
|
// Append an event
|
|
19
|
-
await log.append(
|
|
19
|
+
await log.append('users', { type: 'created', userId: 123 }).run()
|
|
20
20
|
|
|
21
21
|
// Consume events with cursor-based resumption
|
|
22
22
|
const { successes, errors } = await log
|
|
23
|
-
.consume(
|
|
23
|
+
.consume('users', 'my-processor', { batchSize: 10 })
|
|
24
24
|
.withConcurrency(5)
|
|
25
25
|
.map(async (batch) => {
|
|
26
26
|
for (const event of batch.events) {
|
|
27
|
-
await handleEvent(event.data)
|
|
27
|
+
await handleEvent(event.data)
|
|
28
28
|
}
|
|
29
29
|
// Manual commit for at-least-once delivery
|
|
30
|
-
await log.commit(batch.topic, batch.consumerGroup, batch.cursor).run()
|
|
30
|
+
await log.commit(batch.topic, batch.consumerGroup, batch.cursor).run()
|
|
31
31
|
})
|
|
32
|
-
.partition()
|
|
32
|
+
.partition()
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Installation
|
package/esm/adapter.d.ts
CHANGED
|
@@ -1,96 +1,117 @@
|
|
|
1
|
+
import { Promisable } from 'anabranch';
|
|
2
|
+
import { EventLogConsumeFailed } from './errors.js';
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Implement this interface to create drivers for specific event stores.
|
|
5
|
-
* The EventLog class wraps adapters with Task/Stream semantics.
|
|
6
|
-
*
|
|
7
|
-
* For connection lifecycle management, use EventLogConnector which produces adapters.
|
|
8
|
-
* The adapter's close() method releases the connection rather than terminating it.
|
|
4
|
+
* A single event in the event log.
|
|
9
5
|
*/
|
|
10
|
-
/** A single event in the log. */
|
|
11
6
|
export interface Event<T = unknown> {
|
|
12
|
-
/** Unique
|
|
7
|
+
/** Unique identifier for this event. */
|
|
13
8
|
id: string;
|
|
14
|
-
/**
|
|
9
|
+
/** The topic this event belongs to. */
|
|
15
10
|
topic: string;
|
|
16
|
-
/**
|
|
11
|
+
/** The event data payload. */
|
|
17
12
|
data: T;
|
|
18
|
-
/** Partition key for ordering guarantees */
|
|
13
|
+
/** Partition key for ordering guarantees. */
|
|
19
14
|
partitionKey: string;
|
|
20
|
-
/**
|
|
21
|
-
sequenceNumber:
|
|
22
|
-
/**
|
|
15
|
+
/** Monotonically increasing sequence number within the topic. Represented as a string to support bigint while remaining serializable. */
|
|
16
|
+
sequenceNumber: string;
|
|
17
|
+
/** Unix timestamp in milliseconds when the event was created. */
|
|
23
18
|
timestamp: number;
|
|
24
|
-
/** Optional metadata
|
|
19
|
+
/** Optional metadata associated with the event. */
|
|
25
20
|
metadata?: Record<string, unknown>;
|
|
26
21
|
}
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
/**
|
|
23
|
+
* A batch of events delivered to a consumer.
|
|
24
|
+
*/
|
|
25
|
+
export interface EventBatch<T = unknown, Cursor = string> {
|
|
26
|
+
/** The topic this batch was received from. */
|
|
30
27
|
topic: string;
|
|
31
|
-
/**
|
|
28
|
+
/** The consumer group that received this batch. */
|
|
32
29
|
consumerGroup: string;
|
|
33
|
-
/** Events in this batch */
|
|
30
|
+
/** Events in this batch. */
|
|
34
31
|
events: Event<T>[];
|
|
35
|
-
/** Cursor position
|
|
36
|
-
cursor:
|
|
32
|
+
/** Cursor representing the position after this batch. Use for manual commits. */
|
|
33
|
+
cursor: Cursor;
|
|
34
|
+
/**
|
|
35
|
+
* Commit this batch's cursor to mark progress.
|
|
36
|
+
*
|
|
37
|
+
* After processing events successfully, call this to save the cursor position.
|
|
38
|
+
* On restart, the consumer will resume from this position.
|
|
39
|
+
*/
|
|
40
|
+
commit(): Promise<void>;
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
|
-
*
|
|
43
|
+
* Low-level adapter interface for event log implementations.
|
|
44
|
+
*
|
|
45
|
+
* Adapters handle the actual communication with the underlying event store
|
|
46
|
+
* (in-memory, Kafka, etc.). Use connectors to create adapter instances.
|
|
40
47
|
*/
|
|
41
|
-
export interface EventLogAdapter {
|
|
42
|
-
/**
|
|
48
|
+
export interface EventLogAdapter<Cursor = string> {
|
|
49
|
+
/**
|
|
50
|
+
* Append an event to a topic.
|
|
51
|
+
*/
|
|
43
52
|
append<T>(topic: string, data: T, options?: AppendOptions): Promise<string>;
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
getCursor(topic: string, consumerGroup: string): Promise<
|
|
54
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Consume events from a topic.
|
|
55
|
+
*/
|
|
56
|
+
consume<T>(topic: string, consumerGroup: string, onBatch: (batch: EventBatch<T, Cursor>) => Promisable<void>, onError: (error: EventLogConsumeFailed) => Promisable<void>, options?: ConsumeOptions<Cursor>): {
|
|
57
|
+
close: () => Promise<void>;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Get the last committed cursor for a consumer group.
|
|
61
|
+
*/
|
|
62
|
+
getCursor(topic: string, consumerGroup: string): Promise<Cursor | null>;
|
|
63
|
+
/**
|
|
64
|
+
* Commit a cursor for a consumer group.
|
|
65
|
+
*/
|
|
66
|
+
commitCursor(topic: string, consumerGroup: string, cursor: Cursor): Promise<void>;
|
|
67
|
+
/** Close the adapter and release resources. */
|
|
55
68
|
close(): Promise<void>;
|
|
56
69
|
}
|
|
57
|
-
/** Options for appending
|
|
70
|
+
/** Options for appending events. */
|
|
58
71
|
export interface AppendOptions {
|
|
59
|
-
/**
|
|
72
|
+
/** Key for partitioning and ordering. Events with the same key are ordered. */
|
|
60
73
|
partitionKey?: string;
|
|
61
|
-
/**
|
|
74
|
+
/** Custom metadata to attach to the event. */
|
|
62
75
|
metadata?: Record<string, unknown>;
|
|
63
|
-
/**
|
|
76
|
+
/** Custom timestamp in milliseconds. Defaults to Date.now(). */
|
|
64
77
|
timestamp?: number;
|
|
65
78
|
}
|
|
66
|
-
/** Options for listing events. */
|
|
67
|
-
export interface ListOptions {
|
|
68
|
-
/** Starting sequence number (inclusive) */
|
|
69
|
-
fromSequenceNumber?: number;
|
|
70
|
-
/** Maximum number of events to return */
|
|
71
|
-
limit?: number;
|
|
72
|
-
/** Filter by partition key */
|
|
73
|
-
partitionKey?: string;
|
|
74
|
-
}
|
|
75
79
|
/** Options for consuming events. */
|
|
76
|
-
export interface ConsumeOptions {
|
|
77
|
-
/**
|
|
80
|
+
export interface ConsumeOptions<Cursor = string> {
|
|
81
|
+
/** Abort signal to cancel consumption. */
|
|
78
82
|
signal?: AbortSignal;
|
|
79
|
-
/**
|
|
80
|
-
cursor?:
|
|
81
|
-
/**
|
|
83
|
+
/** Cursor to resume from. If null, starts from the beginning. */
|
|
84
|
+
cursor?: Cursor | null;
|
|
85
|
+
/** Maximum number of events per batch. Defaults to adapter-specific value. */
|
|
82
86
|
batchSize?: number;
|
|
87
|
+
/** Maximum number of batches to buffer. Defaults to adapter-specific value.
|
|
88
|
+
* When the buffer is full, new batches will be dropped and onError will be called with an EventLogConsumeFailed error.
|
|
89
|
+
* @default Infinity
|
|
90
|
+
*/
|
|
91
|
+
bufferSize?: number;
|
|
83
92
|
}
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Factory for creating event log connections.
|
|
95
|
+
*
|
|
96
|
+
* Connectors manage connection lifecycle and produce adapter instances.
|
|
97
|
+
* Use connectors in production code to properly manage resources.
|
|
98
|
+
*/
|
|
99
|
+
export interface EventLogConnector<Cursor = string> {
|
|
100
|
+
/**
|
|
101
|
+
* Connect to the event log.
|
|
102
|
+
*/
|
|
103
|
+
connect(signal?: AbortSignal): Promise<EventLogAdapter<Cursor>>;
|
|
104
|
+
/**
|
|
105
|
+
* End the connector and release all resources.
|
|
106
|
+
*
|
|
107
|
+
* After calling end(), all adapters created by this connector become
|
|
108
|
+
* invalid and subsequent connect() calls will fail.
|
|
109
|
+
*/
|
|
89
110
|
end(): Promise<void>;
|
|
90
111
|
}
|
|
91
|
-
/**
|
|
112
|
+
/** Configuration options for event log implementations. */
|
|
92
113
|
export interface EventLogOptions {
|
|
93
|
-
/** Default partition key
|
|
114
|
+
/** Default partition key for events without explicit keys. */
|
|
94
115
|
defaultPartitionKey?: string;
|
|
95
116
|
}
|
|
96
117
|
//# sourceMappingURL=adapter.d.ts.map
|
package/esm/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/esm/adapter.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Event log adapter interface for event-sourced systems.
|
|
3
|
-
*
|
|
4
|
-
* Implement this interface to create drivers for specific event stores.
|
|
5
|
-
* The EventLog class wraps adapters with Task/Stream semantics.
|
|
6
|
-
*
|
|
7
|
-
* For connection lifecycle management, use EventLogConnector which produces adapters.
|
|
8
|
-
* The adapter's close() method releases the connection rather than terminating it.
|
|
9
|
-
*/
|
|
10
1
|
export {};
|
package/esm/errors.d.ts
CHANGED
|
@@ -10,13 +10,8 @@ export declare class EventLogAppendFailed extends Error {
|
|
|
10
10
|
name: string;
|
|
11
11
|
constructor(topic: string, message: string, cause?: unknown);
|
|
12
12
|
}
|
|
13
|
-
/** Error thrown when
|
|
14
|
-
export declare class
|
|
15
|
-
name: string;
|
|
16
|
-
constructor(topic: string, sequenceNumber: number, message: string, cause?: unknown);
|
|
17
|
-
}
|
|
18
|
-
/** Error thrown when listing events fails. */
|
|
19
|
-
export declare class EventLogListFailed extends Error {
|
|
13
|
+
/** Error thrown when consuming events fails. */
|
|
14
|
+
export declare class EventLogConsumeFailed extends Error {
|
|
20
15
|
name: string;
|
|
21
16
|
constructor(topic: string, message: string, cause?: unknown);
|
|
22
17
|
}
|
package/esm/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACxC,IAAI,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACxC,IAAI,SAA6B;gBAC9B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C;AAED,mDAAmD;AACnD,qBAAa,oBAAqB,SAAQ,KAAK;IACpC,IAAI,SAAyB;gBAC1B,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG5D;AAED,gDAAgD;AAChD,qBAAa,qBAAsB,SAAQ,KAAK;IACrC,IAAI,SAA0B;gBAC3B,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG5D;AAED,mDAAmD;AACnD,qBAAa,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,SAA+B;gBAE1C,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO;CAOlB;AAED,gDAAgD;AAChD,qBAAa,uBAAwB,SAAQ,KAAK;IACvC,IAAI,SAA4B;gBAEvC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO;CAOlB;AAED,+DAA+D;AAC/D,qBAAa,mBAAoB,SAAQ,KAAK;IACnC,IAAI,SAAwB;gBACzB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAG7C"}
|
package/esm/errors.js
CHANGED
|
@@ -8,7 +8,7 @@ export class EventLogConnectionFailed extends Error {
|
|
|
8
8
|
enumerable: true,
|
|
9
9
|
configurable: true,
|
|
10
10
|
writable: true,
|
|
11
|
-
value:
|
|
11
|
+
value: 'EventLogConnectionFailed'
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -20,31 +20,19 @@ export class EventLogAppendFailed extends Error {
|
|
|
20
20
|
enumerable: true,
|
|
21
21
|
configurable: true,
|
|
22
22
|
writable: true,
|
|
23
|
-
value:
|
|
23
|
+
value: 'EventLogAppendFailed'
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
/** Error thrown when
|
|
28
|
-
export class
|
|
29
|
-
constructor(topic, sequenceNumber, message, cause) {
|
|
30
|
-
super(`Failed to get event ${sequenceNumber} from ${topic}: ${message}`, { cause });
|
|
31
|
-
Object.defineProperty(this, "name", {
|
|
32
|
-
enumerable: true,
|
|
33
|
-
configurable: true,
|
|
34
|
-
writable: true,
|
|
35
|
-
value: "EventLogGetFailed"
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/** Error thrown when listing events fails. */
|
|
40
|
-
export class EventLogListFailed extends Error {
|
|
27
|
+
/** Error thrown when consuming events fails. */
|
|
28
|
+
export class EventLogConsumeFailed extends Error {
|
|
41
29
|
constructor(topic, message, cause) {
|
|
42
|
-
super(`Failed to
|
|
30
|
+
super(`Failed to consume events from ${topic}: ${message}`, { cause });
|
|
43
31
|
Object.defineProperty(this, "name", {
|
|
44
32
|
enumerable: true,
|
|
45
33
|
configurable: true,
|
|
46
34
|
writable: true,
|
|
47
|
-
value:
|
|
35
|
+
value: 'EventLogConsumeFailed'
|
|
48
36
|
});
|
|
49
37
|
}
|
|
50
38
|
}
|
|
@@ -56,7 +44,7 @@ export class EventLogCommitCursorFailed extends Error {
|
|
|
56
44
|
enumerable: true,
|
|
57
45
|
configurable: true,
|
|
58
46
|
writable: true,
|
|
59
|
-
value:
|
|
47
|
+
value: 'EventLogCommitCursorFailed'
|
|
60
48
|
});
|
|
61
49
|
}
|
|
62
50
|
}
|
|
@@ -68,7 +56,7 @@ export class EventLogGetCursorFailed extends Error {
|
|
|
68
56
|
enumerable: true,
|
|
69
57
|
configurable: true,
|
|
70
58
|
writable: true,
|
|
71
|
-
value:
|
|
59
|
+
value: 'EventLogGetCursorFailed'
|
|
72
60
|
});
|
|
73
61
|
}
|
|
74
62
|
}
|
|
@@ -80,7 +68,7 @@ export class EventLogCloseFailed extends Error {
|
|
|
80
68
|
enumerable: true,
|
|
81
69
|
configurable: true,
|
|
82
70
|
writable: true,
|
|
83
|
-
value:
|
|
71
|
+
value: 'EventLogCloseFailed'
|
|
84
72
|
});
|
|
85
73
|
}
|
|
86
74
|
}
|
package/esm/eventlog.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { AppendOptions, ConsumeOptions,
|
|
3
|
-
import { EventLogAppendFailed, EventLogCloseFailed, EventLogCommitCursorFailed, EventLogConnectionFailed,
|
|
1
|
+
import { Channel, Task } from 'anabranch';
|
|
2
|
+
import type { AppendOptions, ConsumeOptions, EventBatch, EventLogAdapter, EventLogConnector } from './adapter.js';
|
|
3
|
+
import { EventLogAppendFailed, EventLogCloseFailed, EventLogCommitCursorFailed, EventLogConnectionFailed, EventLogConsumeFailed, EventLogGetCursorFailed } from './errors.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Event log wrapper with Task/Stream semantics for event-sourced systems.
|
|
6
|
+
*
|
|
7
|
+
* Provides high-level methods for appending events, consuming streams,
|
|
8
|
+
* and managing cursors. All operations return Tasks for composable error
|
|
9
|
+
* handling.
|
|
6
10
|
*
|
|
7
11
|
* @example Basic usage
|
|
8
12
|
* ```ts
|
|
@@ -12,35 +16,34 @@ import { EventLogAppendFailed, EventLogCloseFailed, EventLogCommitCursorFailed,
|
|
|
12
16
|
* const log = await EventLog.connect(connector).run();
|
|
13
17
|
*
|
|
14
18
|
* // Append an event
|
|
15
|
-
* const eventId = await log.append("users", {
|
|
16
|
-
*
|
|
17
|
-
* // Get a specific event
|
|
18
|
-
* const event = await log.get("users", 0).run();
|
|
19
|
-
*
|
|
20
|
-
* // List events
|
|
21
|
-
* const events = await log.list("users").run();
|
|
22
|
-
*
|
|
23
|
-
* await log.close().run();
|
|
24
|
-
* ```
|
|
19
|
+
* const eventId = await log.append("users", { userId: 123 }).run();
|
|
25
20
|
*
|
|
26
|
-
*
|
|
27
|
-
* ```ts
|
|
21
|
+
* // Consume events as a stream
|
|
28
22
|
* const { successes, errors } = await log
|
|
29
|
-
* .consume("users", "my-
|
|
23
|
+
* .consume("users", "my-processor")
|
|
30
24
|
* .withConcurrency(5)
|
|
31
25
|
* .map(async (batch) => {
|
|
32
26
|
* for (const event of batch.events) {
|
|
33
|
-
* await
|
|
27
|
+
* await processEvent(event.data);
|
|
34
28
|
* }
|
|
35
|
-
* // Explicitly commit after successful processing!
|
|
36
|
-
* await log.commit(batch.topic, batch.consumerGroup, batch.cursor).run();
|
|
37
29
|
* })
|
|
38
30
|
* .partition();
|
|
31
|
+
*
|
|
32
|
+
* await log.close().run();
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Manual cursor management
|
|
36
|
+
* ```ts
|
|
37
|
+
* // Get current cursor position
|
|
38
|
+
* const cursor = await log.getCommittedCursor("users", "my-processor").run();
|
|
39
|
+
*
|
|
40
|
+
* // Save cursor after processing
|
|
41
|
+
* await log.commit("users", "my-processor", batch.cursor).run();
|
|
39
42
|
* ```
|
|
40
43
|
*/
|
|
41
|
-
export declare class EventLog {
|
|
44
|
+
export declare class EventLog<Cursor = string> {
|
|
42
45
|
private readonly adapter;
|
|
43
|
-
constructor(adapter: EventLogAdapter);
|
|
46
|
+
constructor(adapter: EventLogAdapter<Cursor>);
|
|
44
47
|
/**
|
|
45
48
|
* Connect to an event log via a connector.
|
|
46
49
|
*
|
|
@@ -49,9 +52,11 @@ export declare class EventLog {
|
|
|
49
52
|
* const log = await EventLog.connect(createInMemory()).run();
|
|
50
53
|
* ```
|
|
51
54
|
*/
|
|
52
|
-
static connect(connector: EventLogConnector): Task<EventLog
|
|
55
|
+
static connect<Cursor = string>(connector: EventLogConnector<Cursor>): Task<EventLog<Cursor>, EventLogConnectionFailed>;
|
|
53
56
|
/**
|
|
54
|
-
*
|
|
57
|
+
* Close the event log connection.
|
|
58
|
+
*
|
|
59
|
+
* After closing, no further operations can be performed on this instance.
|
|
55
60
|
*
|
|
56
61
|
* @example
|
|
57
62
|
* ```ts
|
|
@@ -62,110 +67,87 @@ export declare class EventLog {
|
|
|
62
67
|
/**
|
|
63
68
|
* Append an event to a topic.
|
|
64
69
|
*
|
|
65
|
-
*
|
|
66
|
-
* ```ts
|
|
67
|
-
* const eventId = await log.append("users", { action: "created", userId: 123 }).run();
|
|
68
|
-
* ```
|
|
70
|
+
* Returns the event ID which can be used for logging or correlation.
|
|
69
71
|
*
|
|
70
|
-
* @example
|
|
72
|
+
* @example
|
|
71
73
|
* ```ts
|
|
72
|
-
* const eventId = await log.append("
|
|
73
|
-
*
|
|
74
|
+
* const eventId = await log.append("users", { action: "created" }).run();
|
|
75
|
+
*
|
|
76
|
+
* // With options
|
|
77
|
+
* await log.append("orders", order, {
|
|
78
|
+
* partitionKey: order.userId,
|
|
79
|
+
* metadata: { source: "checkout" },
|
|
74
80
|
* }).run();
|
|
75
81
|
* ```
|
|
76
82
|
*/
|
|
77
83
|
append<T>(topic: string, data: T, options?: AppendOptions): Task<string, EventLogAppendFailed>;
|
|
78
84
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* ```ts
|
|
83
|
-
* const event = await log.get("users", 0).run();
|
|
84
|
-
* if (event) {
|
|
85
|
-
* console.log(event.data);
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
get<T>(topic: string, sequenceNumber: number): Task<Event<T> | null, EventLogGetFailed>;
|
|
90
|
-
/**
|
|
91
|
-
* List events in a topic with optional filtering and pagination.
|
|
85
|
+
* Consume events from a topic as a stream.
|
|
92
86
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* ```
|
|
87
|
+
* Returns a Channel that yields batches of events. Each batch includes
|
|
88
|
+
* a cursor that can be committed to mark progress. Use stream methods
|
|
89
|
+
* like `withConcurrency()`, `map()`, and `partition()` for processing.
|
|
97
90
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* fromSequenceNumber: 100,
|
|
102
|
-
* limit: 50,
|
|
103
|
-
* }).run();
|
|
104
|
-
* ```
|
|
91
|
+
* Batches are delivered asynchronously as they become available. Use
|
|
92
|
+
* `take()` to limit iterations or pass an AbortSignal in options to
|
|
93
|
+
* cancel consumption.
|
|
105
94
|
*
|
|
106
|
-
* @example
|
|
95
|
+
* @example
|
|
107
96
|
* ```ts
|
|
108
|
-
* const
|
|
109
|
-
* partitionKey: "user-123",
|
|
110
|
-
* }).run();
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
list<T>(topic: string, options?: ListOptions): Task<Event<T>[], EventLogListFailed>;
|
|
114
|
-
/**
|
|
115
|
-
* Consume events from a topic as a Source for streaming.
|
|
97
|
+
* const ac = new AbortController();
|
|
116
98
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* data loss when using concurrent processing.
|
|
120
|
-
*
|
|
121
|
-
* @example Basic consumption
|
|
122
|
-
* ```ts
|
|
123
|
-
* const { successes, errors } = await log
|
|
124
|
-
* .consume("users", "processor-1")
|
|
125
|
-
* .withConcurrency(5)
|
|
99
|
+
* await log.consume("users", "processor-1", { signal: ac.signal })
|
|
100
|
+
* .withConcurrency(10)
|
|
126
101
|
* .map(async (batch) => {
|
|
127
102
|
* for (const event of batch.events) {
|
|
128
|
-
* await
|
|
103
|
+
* await processUser(event.data);
|
|
129
104
|
* }
|
|
130
|
-
* await
|
|
105
|
+
* await batch.commit(); // Mark progress
|
|
131
106
|
* })
|
|
132
107
|
* .partition();
|
|
108
|
+
*
|
|
109
|
+
* ac.abort(); // Stop consumption
|
|
133
110
|
* ```
|
|
134
111
|
*
|
|
135
|
-
* @example
|
|
112
|
+
* @example Resume from a saved cursor
|
|
136
113
|
* ```ts
|
|
137
|
-
* const
|
|
138
|
-
* const
|
|
139
|
-
* .consume("users", "processor-1", { cursor: lastCursor })
|
|
140
|
-
* .tap(async (batch) => {
|
|
141
|
-
* for (const event of batch.events) {
|
|
142
|
-
* console.log(event);
|
|
143
|
-
* }
|
|
144
|
-
* })
|
|
145
|
-
* .partition();
|
|
114
|
+
* const cursor = await log.getCommittedCursor("users", "processor-1").run();
|
|
115
|
+
* const stream = log.consume("users", "processor-1", { cursor });
|
|
146
116
|
* ```
|
|
147
117
|
*/
|
|
148
|
-
consume<T>(topic: string, consumerGroup: string, options?: ConsumeOptions):
|
|
118
|
+
consume<T>(topic: string, consumerGroup: string, options?: ConsumeOptions<Cursor>): Channel<EventBatch<T, Cursor>, EventLogConsumeFailed>;
|
|
149
119
|
/**
|
|
150
|
-
* Commit a cursor
|
|
120
|
+
* Commit a cursor to mark progress for a consumer group.
|
|
121
|
+
*
|
|
122
|
+
* This is for administrative use cases where you can't commit in-band, preferably when you're
|
|
123
|
+
* not actively consuming events. For example, you might want to skip ahead after a downtime or reset to the beginning for reprocessing.
|
|
124
|
+
* Do prefer to commit in-band, i.e. after processing each batch, by calling `batch.commit()`.
|
|
125
|
+
*
|
|
126
|
+
* After processing events, commit the cursor to resume from that position
|
|
127
|
+
* on the next run. Cursors are obtained from `batch.cursor` in the consume
|
|
128
|
+
* stream or from `getCommittedCursor()`.
|
|
151
129
|
*
|
|
152
130
|
* @example
|
|
153
131
|
* ```ts
|
|
154
|
-
* await log.commit("users", "processor-1", cursor).run();
|
|
132
|
+
* await log.commit("users", "processor-1", batch.cursor).run();
|
|
155
133
|
* ```
|
|
156
134
|
*/
|
|
157
|
-
commit(topic: string, consumerGroup: string, cursor:
|
|
135
|
+
commit(topic: string, consumerGroup: string, cursor: Cursor): Task<void, EventLogCommitCursorFailed>;
|
|
158
136
|
/**
|
|
159
|
-
* Get the committed cursor
|
|
137
|
+
* Get the last committed cursor for a consumer group.
|
|
138
|
+
*
|
|
139
|
+
* Returns null if no cursor has been committed yet. Use this to resume
|
|
140
|
+
* consumption from the last processed position.
|
|
160
141
|
*
|
|
161
142
|
* @example
|
|
162
143
|
* ```ts
|
|
163
144
|
* const cursor = await log.getCommittedCursor("users", "processor-1").run();
|
|
164
145
|
* if (cursor) {
|
|
165
|
-
*
|
|
146
|
+
* // Resume from saved position
|
|
147
|
+
* const stream = log.consume("users", "processor-1", { cursor });
|
|
166
148
|
* }
|
|
167
149
|
* ```
|
|
168
150
|
*/
|
|
169
|
-
getCommittedCursor(topic: string, consumerGroup: string): Task<
|
|
151
|
+
getCommittedCursor(topic: string, consumerGroup: string): Task<Cursor | null, EventLogGetCursorFailed>;
|
|
170
152
|
}
|
|
171
153
|
//# sourceMappingURL=eventlog.d.ts.map
|
package/esm/eventlog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventlog.d.ts","sourceRoot":"","sources":["../src/eventlog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"eventlog.d.ts","sourceRoot":"","sources":["../src/eventlog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,QAAQ,CAAC,MAAM,GAAG,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC;IAE7D;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,EAC5B,SAAS,EAAE,iBAAiB,CAAC,MAAM,CAAC,GACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAanD;;;;;;;;;OASG;IACH,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC;IAaxC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,CAAC,EACN,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,aAAa,GACtB,IAAI,CAAC,MAAM,EAAE,oBAAoB,CAAC;IAcrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,OAAO,CAAC,CAAC,EACP,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAsDxD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,IAAI,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAezC;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,CAChB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GACpB,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,uBAAuB,CAAC;CAchD"}
|