You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An optional parameter to `EventStore.read()` that allows for cursor-based pagination of events.
28
+
It has two parameters:
29
+
-`backwards` a flag that, if set to `true`, returns the events in descending order (default: `false`)
30
+
-`from` an optional [SequenceNumber](#SequenceNumber) to start streaming events from (depending on the `backwards` flag this is either a _minimum_ or _maximum_ sequence number of the resulting stream)
31
+
32
+
```
33
+
ReadOptions {
34
+
from?: SequenceNumber
35
+
backwards: bool
24
36
}
25
37
```
26
38
27
-
## StreamQuery
39
+
###StreamQuery
28
40
29
-
The `StreamQuery` describes constraints that must be matched by [Event](#Event)s in the [EventStore](#EventStore).
41
+
The `StreamQuery` describes constraints that must be matched by [Event](#Event)s in the [EventStore](#EventStore)
42
+
It effectively allows for filtering events by their [type](#EventType) and/or [tags](#Tags)
30
43
31
-
* It _MAY_ contain a set of [StreamQuery Criteria](#StreamQuery-Criterion)
44
+
* It _MAY_ contain a set of [StreamQuery Criteria](#StreamQuery-Criterion) – a `StreamQuery` with an empty criteria set is considered a "wildcard" query, i.e. it matches all events
32
45
33
-
**Note:** All criteria of a StreamQuery are merged into a *logical disjunction*, so the example below matches all events, that match the first **OR** the second criterion.
46
+
> [!NOTE]
47
+
> All criteria of a StreamQuery are merged into a *logical disjunction*, so events match the query if they match the first **OR** the second criterion...
34
48
35
-
#### Potential serialization format
49
+
###StreamQuery Criterion
36
50
37
-
```json
38
-
{
39
-
"version": "1.0",
40
-
"criteria": [{
41
-
"type": "EventTypes",
42
-
"properties": {
43
-
"event_types": ["EventType1", "EventType2"]
44
-
}
45
-
}, {
46
-
"type": "Tags",
47
-
"properties": {
48
-
"tags": ["foo:bar", "baz:foos"],
49
-
}
50
-
}, {
51
-
"type": "EventTypesAndTags",
52
-
"properties": {
53
-
"event_types": ["EventType2", "EventType3"],
54
-
"tags": ["foo:bar", "foo:baz"],
55
-
}
56
-
}]
57
-
}
58
-
```
51
+
Each criterion of a [StreamQuery](#StreamQuery) allows to target events by their [type](#EventType) and/or [tags](#Tags)
59
52
53
+
> [!NOTE]
54
+
> event type filters of a single criterion are merged into a *logical disjunction*, so events match the criterion if they match **ANY** of the specified types
55
+
> tags are merged into a *logical conjunction*, so events match the criterion if they are tagged with **ALL** specified tags
60
56
61
-
##StreamQuery Criterion
57
+
#### Example StreamQuery
62
58
63
-
In v1 the only supported criteria types are:
59
+
The following example query would match events that are either...
60
+
- ...of type `EventType1`**OR**`EventType2`
61
+
- ...tagged `foo:bar`**AND**`baz:foos`
62
+
- ...of type `EventType2`**OR**`EventType3`**AND** tagged `foo:bar`**AND**`foo:baz`
64
63
65
-
*`Tags` – allows to target one or more [Tags](#Tags)
66
-
*`EventTypes` – allows to target one or more [EventType](#EventType)s
67
-
*`EventTypesAndTags` – allows to target one or more [Tags](#Tags) and one or more [EventType](#EventType)s
64
+
```json
65
+
{
66
+
"criteria": [
67
+
{
68
+
"event_types": ["EventType1", "EventType2"]
69
+
},
70
+
{
71
+
"tags": ["foo:bar", "baz:foos"]
72
+
},
73
+
{
74
+
"event_types": ["EventType2", "EventType3"],
75
+
"tags": ["foo:bar", "foo:baz"]
76
+
}
77
+
]
78
+
}
79
+
```
68
80
69
-
## SequenceNumber
81
+
###SequenceNumber
70
82
71
83
When an [Event](#Event) is appended to the [EventStore](#EventStore) a `SequenceNumber` is assigned to it.
72
84
@@ -77,8 +89,7 @@ It...
77
89
*_CAN_ contain gaps
78
90
*_SHOULD_ have a reasonably high maximum value (depending on programming language and environment)
79
91
80
-
81
-
## EventStream
92
+
### EventStream
82
93
83
94
When reading from the [EventStore](#EventStore) an `EventStream` is returned.
84
95
@@ -89,94 +100,92 @@ It...
89
100
* Individual [EventEnvelope](#EventEnvelope) instances _MAY_ be converted during iteration for performance optimization
90
101
* Batches of events _MAY_ be loaded from the underlying storage at once for performance optimization
91
102
92
-
## EventEnvelope
103
+
###EventEnvelope
93
104
94
105
Each item in the [EventStream](#EventStream) is an `EventEnvelope` that consists of the underlying event and metadata, like the [SequenceNumber](#SequenceNumber) that was added during the `append()` call.
95
106
107
+
It...
108
+
* It _MUST_ contain the [SequenceNumber](#SequenceNumber)
109
+
* It _MUST_ contain the [Event](#Event)
110
+
* It _CAN_ include more fields, like timestamps or metadata
111
+
112
+
#### EventEnvelope example
113
+
96
114
```json
97
115
{
98
116
"event": {
99
-
"id": "15aaa216-4179-46d9-999a-75516e21a1c6",
100
117
"type": "SomeEventType",
101
-
"data": "{\"some\":\"data\"}"
118
+
"data": "{\"some\":\"data\"}",
102
119
"tags": ["type1:value1", "type2:value2"]
103
120
},
104
-
"sequence_number": 1234
121
+
"sequence_number": 1234,
122
+
"recorded_at": "2024-12-10 14:02:40"
105
123
}
106
124
```
107
125
108
-
## Events
126
+
###Events
109
127
110
128
A set of [Event](#Event) instances that is passed to the `append()` method of the [EventStore](#EventStore)
111
129
112
130
It...
113
131
*_MUST_ not be empty
114
132
*_MUST_ be iterable, each iteration returning an [Event](#Event)
115
133
116
-
## Event
134
+
###Event
117
135
118
-
* It _MUST_ contain a globally unique [EventId](#EventId)
119
136
* It _MUST_ contain an [EventType](#EventType)
120
137
* It _MUST_ contain [EventData](#EventData)
121
138
* It _MAY_ contain [Tags](#Tags)
139
+
* It _MAY_ contain further fields, like metadata
122
140
123
141
#### Potential serialization format
124
142
125
143
```json
126
144
{
127
-
"id": "15aaa216-4179-46d9-999a-75516e21a1c6",
128
145
"type": "SomeEventType",
129
-
"data": "{\"some\":\"data\"}"
146
+
"data": "{\"some\":\"data\"}",
130
147
"tags": ["key1:value1", "key1:value2"]
131
148
}
132
149
```
133
150
134
-
## EventId
135
-
136
-
String based globally unique identifier of an [Event](#Event)
137
-
138
-
* It _MUST_ satisfy the regular expression `^[\w\-]{1,100}$`
139
-
* It _MAY_ be implemented as a [UUID](https://www.ietf.org/rfc/rfc4122.txt)
140
-
141
-
## EventType
151
+
### EventType
142
152
143
-
String based type of an event
153
+
String based type of the event
144
154
145
155
* It _MUST_ satisfy the regular expression `^[\w\.\:\-]{1,200}$`
146
156
147
-
## EventData
157
+
###EventData
148
158
149
159
String based, opaque payload of an [Event](#Event)
150
160
151
161
* It _SHOULD_ have a reasonable large enough maximum length (depending on language and environment)
152
162
* It _MAY_ contain [JSON](https://www.json.org/)
153
163
* It _MAY_ be serialized into an empty string
154
164
155
-
## Tags
165
+
###Tags
156
166
157
167
A set of [Tag](#Tag) instances.
158
168
159
169
* It _MUST_ contain at least one [Tag](#Tag)
160
-
* It _MAY_ contain multiple [Tag](#Tag)s with the same value
161
-
* It _SHOULD_ not contain muliple [Tag](#Tag)s with the same key/value pair
170
+
* It _SHOULD_ not contain multiple [Tag](#Tag)s with the same value
162
171
163
-
## Tag
172
+
###Tag
164
173
165
-
A `Tag` can add domain specific metadata (usually the ids of an entity or concept of the core domain) to an event allowing for custom partitioning
174
+
A `Tag` can add domain specific metadata to an event allowing for custom partitioning
166
175
167
-
**NOTE:** If the `value` is not specified, all tags of the given `key` will match (wildcard)
176
+
> [!NOTE]
177
+
> Usually a tag represents a concept of the domain, e.g. the type and id of an entity like `product:p123`
168
178
169
-
* It _MUST_ contain a `key` that satisfies the regular expression `^[a-zA-Z0-9\-\_]{1,50}$`
170
-
* It _CAN_ contain a `value` that satisfies the regular expression `^[a-zA-Z0-9\-\_]{1,50}$`
179
+
* It _MUST_ satisfy the regular expression `/^[[:alnum:]\-\_\:]{1,150}`
171
180
172
-
## AppendCondition
181
+
###AppendCondition
173
182
174
183
* It _MUST_ contain a [StreamQuery](#StreamQuery)
175
184
* It _MUST_ contain a [ExpectedHighestSequenceNumber](#ExpectedHighestSequenceNumber)
176
185
177
-
## ExpectedHighestSequenceNumber
186
+
###ExpectedHighestSequenceNumber
178
187
179
-
Can _either_be an instance of [SequenceNumber](#SequenceNumber)
188
+
Can _either_represent an instance of [SequenceNumber](#SequenceNumber)
180
189
Or one of:
181
190
*`NONE` – No event must match the specified [StreamQuery](#StreamQuery)
182
191
*`ANY` – Any event matches (= wildcard [AppendCondition](#AppendCondition))
0 commit comments