TASK
Implementation
The event store is optimized for writes, not queries. A projection solves this: it listens to the event stream and maintains a denormalized read model that is fast to query. When the event schema changes or a new view is needed, the projection can be rebuilt from scratch.
Implement a node that manages named projections:
// Create a new projection with an initial empty state
{ "type": "create", "msg_id": 1,
"name": "user-listing", "initial_state": [] }
-> { "type": "projection_created", "in_reply_to": 1,
"name": "user-listing", "version": 0 }
// Apply one event to a projection
{ "type": "update", "msg_id": 2,
"projection": "user-listing",
"event": {"event_type": "UserCreated",
"event_data": {"id": "user-123", "name": "John"}} }
-> { "type": "projection_updated", "in_reply_to": 2,
"projection": "user-listing", "version": 1,
"state": [{"id": "user-123", "name": "John"}] }
// Rebuild projection from scratch using a list of past events
{ "type": "rebuild", "msg_id": 3,
"projection": "user-listing",
"events": [{"event_type": "UserCreated", "event_data": {"id": "user-123"}}] }
-> { "type": "projection_rebuilt", "in_reply_to": 3,
"projection": "user-listing",
"events_processed": 1, "version": 1 }The projection version increments by 1 for every event applied. Rebuilding resets the version to 0 and replays all supplied events.
Sample Test Cases
Create listing projectionTimeout: 5000ms
Input
{
"src": "projector",
"dest": "projection",
"body": {
"type": "create",
"msg_id": 1,
"name": "user-listing",
"initial_state": []
}
}Expected Output
{"type": "projection_created", "in_reply_to": 1, "name": "user-listing", "version": 0}Update projection with eventTimeout: 5000ms
Input
{
"src": "eventstore",
"dest": "projection",
"body": {
"type": "update",
"msg_id": 1,
"projection": "user-listing",
"event": {
"event_type": "UserCreated",
"event_data": {
"id": "user-123",
"name": "John"
}
}
}
}Expected Output
{"type": "projection_updated", "in_reply_to": 1, "projection": "user-listing", "version": 1, "state": [{"id": "user-123", "name": "John"}]}Hints
Hint 1▾
A projection is a named read model built by consuming events one at a time
Hint 2▾
create initializes a projection with an empty state and version 0
Hint 3▾
update applies one event to the projection and increments its version
Hint 4▾
rebuild replays a list of events from scratch onto the projection
Hint 5▾
Each update/rebuild step should merge event_data into the projection state
OVERVIEW
Theoretical Hub
Concept overview coming soon
Key Concepts
projectionsread modelsevent-driven denormalizationrebuildversioned projection
main.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
import sys
import json
def main():
# Your implementation here
for line in sys.stdin:
msg = json.loads(line)
print(json.dumps(msg), flush=True)
if __name__ == "__main__":
main()