Skip to content

Latest commit

 

History

History
182 lines (124 loc) · 5.41 KB

Specification.md

File metadata and controls

182 lines (124 loc) · 5.41 KB

EventStore

Reading

Expects a StreamQuery and an optional starting SequenceNumber and returns an EventStream.

Note: The EventStore should also allow for backwards iteration on the EventStream in order to support cursor based pagination.

Writing

Expects a set of Events and an AppendCondition and returns the last appended SequenceNumber.

Potential API

EventStore {

  read(query: StreamQuery, from?: SequenceNumber): EventStream
  
  readBackwards(query: StreamQuery, from?: SequenceNumber): EventStream
  
  append(events: Events, condition: AppendCondition): SequenceNumber
  
}

StreamQuery

The StreamQuery describes constraints that must be matched by Events in the EventStore.

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.

Potential serialization format

{
    "version": "1.0",
    "criteria": [{
        "type": "EventTypes",
        "properties": {
            "event_types": ["EventType1", "EventType2"]
        }
    }, {
        "type": "Tags",
        "properties": {
            "tags": ["foo:bar", "baz:foos"],
        }
    }, {
        "type": "EventTypesAndTags",
        "properties": {
            "event_types": ["EventType2", "EventType3"],
            "tags": ["foo:bar", "foo:baz"],
        }
    }]
}

StreamQuery Criterion

In v1 the only supported criteria types are:

  • Tags – allows to target one or more Tags
  • EventTypes – allows to target one or more EventTypes
  • EventTypesAndTags – allows to target one or more Tags and one or more EventTypes

SequenceNumber

When an Event is appended to the EventStore a SequenceNumber is assigned to it.

It...

  • MUST be unique for one EventStore
  • MUST be monotonic increasing
  • MUST have an allowed minimum value of 1
  • CAN contain gaps
  • SHOULD have a reasonably high maximum value (depending on programming language and environment)

EventStream

When reading from the EventStore an EventStream is returned.

It...

  • It MUST be iterable
  • It MUST return an EventEnvelope for every iteration
  • It CAN include new events if they occur during iteration
  • Individual EventEnvelope instances MAY be converted during iteration for performance optimization
  • Batches of events MAY be loaded from the underlying storage at once for performance optimization

EventEnvelope

Each item in the EventStream is an EventEnvelope that consists of the underlying event and metadata, like the SequenceNumber that was added during the append() call.

{
    "event": {
        "id": "15aaa216-4179-46d9-999a-75516e21a1c6",
        "type": "SomeEventType",
        "data": "{\"some\":\"data\"}"
        "tags": ["type1:value1", "type2:value2"]
    },
    "sequence_number": 1234
}

Events

A set of Event instances that is passed to the append() method of the EventStore

It...

  • MUST not be empty
  • MUST be iterable, each iteration returning an Event

Event

Potential serialization format

{
    "id": "15aaa216-4179-46d9-999a-75516e21a1c6",
    "type": "SomeEventType",
    "data": "{\"some\":\"data\"}"
    "tags": ["key1:value1", "key1:value2"]
}

EventId

String based globally unique identifier of an Event

  • It MUST satisfy the regular expression ^[\w\-]{1,100}$
  • It MAY be implemented as a UUID

EventType

String based type of an event

  • It MUST satisfy the regular expression ^[\w\.\:\-]{1,200}$

EventData

String based, opaque payload of an Event

  • It SHOULD have a reasonable large enough maximum length (depending on language and environment)
  • It MAY contain JSON
  • It MAY be serialized into an empty string

Tags

A set of Tag instances.

  • It MUST contain at least one Tag
  • It MAY contain multiple Tags with the same value
  • It SHOULD not contain muliple Tags with the same key/value pair

Tag

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

NOTE: If the value is not specified, all tags of the given key will match (wildcard)

  • It MUST contain a key that satisfies the regular expression ^[a-zA-Z0-9\-\_]{1,50}$
  • It CAN contain a value that satisfies the regular expression ^[a-zA-Z0-9\-\_]{1,50}$

AppendCondition

ExpectedHighestSequenceNumber

Can either be an instance of SequenceNumber Or one of: