Package: django-spark
==========================================django-spark - Event sourcing and handling==========================================.. image:: https://travis-ci.org/matthiask/django-spark.png?branch=master:target: https://travis-ci.org/matthiask/django-sparkVersion |release|This is not supposed to be real documentation; it's more a reminder formyself.The idea is that there are event sources and event handlers. Eventsources may create a stream of ``spark.api.Event`` instances, where eachevent must have a ``group`` and a ``key``. Additional data may be addedto the ``Event`` as well. Keys are globally unique -- events with thesame key are still only processed exactly once. Groups are used todetermine which handlers handle a certain event.Event handlers are functions which are called once per``spark.api.Event`` instance if the event's group matches the eventhandler's regex.Some usage example code=======================Given a challenge, create events for the challenge (the specifics do notmatter):.. code-block:: pythonfrom datetime import datefrom spark import apidef events_from_challenge(challenge):if not challenge.is_active:returnyield {"group": 'challenge_created',"key": 'challenge_created_%s' % challenge.pk,"context": {"challenge": challenge},}if (date.today() - challenge.start_date).days > 2:if challenge.donations.count() < 2:yield {"group": 'challenge_inactivity_2d',"key": 'challenge_inactivity_2d_%s' % challenge.pk,"context": {"challenge": challenge},}if (challenge.end_date - date.today()).days <= 2:yield {"group": 'challenge_ends_2d',"key": 'challenge_ends_2d_%s' % challenge.pk,"context": {"challenge": challenge},}if challenge.end_date < date.today():yield {"group": 'challenge_ended',"key": 'challenge_ended_%s' % challenge.pk,"context": {"challenge": challenge},}Send mails related to challenges (uses django-authlib's``render_to_mail``):.. code-block:: pythonfrom authlib.email import render_to_maildef send_challenge_mails(event):challenge = event["context"]["challenge"]render_to_mail(# Different mail text per event group:"challenges/mails/%s" % event["group"],{"challenge": challenge,},to=[challenge.user.email],).send(fail_silently=True)Register the handlers:.. code-block:: pythonclass ChallengesConfig(AppConfig):def ready(self):# Prevent circular imports:from spark import apiapi.register_group_handler(handler=send_challenge_mails,group=r'^challenge',)Challenge = self.get_model('Challenge')# All this does right now is register a post_save signal# handler which runs the challenge instance through# events_from_challenge:api.register_model_event_source(sender=Challenge,source=events_from_challenge,)Now, events are generated and handled directly in process.Alternatively, you might want to handle events outside therequest-response cycle. This can be achieved by only registering themodel event source e.g. in a management command, and then sending allmodel instances through all event sources, and directly processing thoseevents, for example like this:.. code-block:: pythonfrom spark import apiapi.register_model_event_source(...)# Copied from the process_spark_sources management command inside# this repositoryfor model, sources in api.MODEL_SOURCES.items():for instance in model.objects.all():for source in sources:api.process_events(api.only_new_events(source(instance)))- `Documentation <https://django-spark.readthedocs.io>`_- `Github <https://github.com/matthiask/django-spark/>`_