lukaszb / cq Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Should be done in "implement usage first".
One way we can accomplish that is to add version
field to events and make unique constraint on 2 fields that identify entity at particular moment in time (entity's id and version).
There are two possible outcomes:
We are going to implement 1) approach with a custom exception.
I believe that cq
should be framework/tools agnostic, however I caught myself couple of times running from cq.models import Event
within my Django based app.
We should be able to query events in a much better manner. To be specific I would love to be able to query events with explicit ordering and filtering after doing simple library import.
Basically, I'd like to achieve something like:
import cq
for event in cq.query_events('User.StartedSession', limit=50):
print("{} | User {} logged in".format(event.ts, event.data['email']))
Or something like:
print(cq.query_events(ts="3 days")
which should show events from last 3 days.
cq.query_events
def query_events(*names, limit=100, order_by='-ts', **filters):
...
names
are not named arguments. Might be empty of course - in this case all events, regardless of their types, would be returnedlimit
results to first 100 by default. If None
given, all matching events are returnedorder_by
defaults to -ts
, meaning events would be ordered by date of creation, descending. Allows to change or disable order.filters
: For now it would probably suffice to filter by ts
param. It should be similar to what is possible with Django ORM: ts=datetime(2017, 3, 24)
(exact comparison) or ts__gte=datetime(2017, 3, 24)
(all events created after 2017-03-24) or ts="day"
(if string given, should be human readable and would be treated as "show me events from last day/week/month" or number of those like "2 weeks". I'd say this is optional, however I'd strongly advice to implement it as it would be mostly used in my opinion).Currently Repository.get_aggregate
method is not very efficient - it fetches all events that were used to create an aggregate. In order not to do that we want to introduce snapshots.
Logic behind the get_aggregate
should be changed as follow:
Storage.create_snapshot
methodEven if we would be working with entities most of the time probably it doesn't harm if we call them aggregates as this is more generic object. In this task we would also need to update all variable names.
This should be done just after public release but initial branch with travis config should be done before that.
Not sure anyone will even touch this without one. Suggest BSD or MIT.
now they only accept data but sometimes it would be necessary to for example take event's timestamp into account
Currently those are Django model instances. They should be translated in and out by the storage engine.
We need a method to re-run all events.
There are couple of gotchas:
saga
, though.register_user
command and it's handler not only updates user model projection but also sends out an e-mail with an activation link. We should make sure that running rehydration process won't invoke such handler actions (and still updates projections)Before writing any more code we should try to explain to users how to use this library.
We'd need to re-read it and make sure it's simple enough.
It's actually confusing right now. We are using metaclass and specially prepared Action
class that should be used to indicate a domain actions. This is unnecessary convoluted - we should fall back to simple strings when identifying domain events. In addition, this would help to handle events coming from external services (as they might not have action classes at all). We currently support both Action
class and strings.
Reference: https://github.com/lukaszb/ses/blob/0580d003067c0f559bdff4fcdb1d7394acefc535/ses/entities.py#L1
https://github.com/lukaszb/cq/blob/devel/cq/storages.py#L66
Signature of Storage.get_events
should be extended with required aggregate_type
param. Now, if aggregate id clashes with another aggregate type, an error would be thrown (there would be no mutator for found aggregate).
Let's imagine we have an User.Registered
event with email
and password
. After a while we decide that whenever we register an user we also want to apply a role for her. In such case we should upgrade a command that generates the event but then we would end up with old and new events that would have different set of data. To prevent that, we would simply recognise old events and upcast them to new version. This could looks something like:
cq.register_upcasters([
cq.upcaster(event='User.Registered', revision=1, method='accounts.upcasters.add_role'),
])
def add_role(event):
event.data['role'] = 'DEFAULT_USER'
We might use classes for upcasting too, like:
cq.register_upcasters([
accounts.upcasters.AddRole',
])
class AddRole(cq.Upcaster):
aggregate_type = 'User'
name = 'Register'
apply_on_revision = 1
def add_role(self, event):
event.data['role'] = 'DEFAULT_USER'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.