Skip to main content

Fractal Events

Fractal Events is event sourcing for the Fractal stack: events, a publisher that fans them out to projectors, an event store to keep them in, and the projectors that print them, persist them, or turn them back into commands.

PyPI Version Build Status

Installation

pip install fractal-events

Background

An event says something already happened: this road was added. A command asks for something to happen. Keeping those apart is what makes the write side of an application replayable — events are facts, and facts can be stored, re-read and projected onto as many things as you like without any of those things knowing about each other.

That is what this package is: the fact, the fan-out, and somewhere to keep the facts.

Publishing

from fractal_events import EventPublisher, PrintEventProjector

publisher = EventPublisher([PrintEventProjector()])
publisher.publish_event(RoadAddedEvent(command=command, road_id="1"))

Events published together share one stream id; separate calls get separate ones. Every projector sees every event — the publisher does not filter, and projectors do not know about each other.

Projectors

  • PrintEventProjector — writes each event as one JSON line. Useful in development, and the cheapest possible audit trail.
  • EventStoreProjector — commits each event to an EventStore.
  • CommandBusProjector — maps events back onto commands, or onto Processes.

Mapping events back to commands

from fractal_events import CommandBusProjector, EventCommandMapper


class RebuildOnRoadAdded(EventCommandMapper):
    def mappers(self):
        return {RoadAddedEvent: [lambda e: RebuildCommand(road_id=e.road_id)]}


projector = CommandBusProjector(
    lambda: context.command_bus,
    [RebuildOnRoadAdded()],
)

Give this projector a lenient bus. Fan-out legitimately produces commands this particular deployment has no handler for — that is normal, not broken. A CommandBus() is strict and will raise; construct it as CommandBus(strict=False) for a projector, so a miss is logged rather than thrown. A strict bus is right for a service call, where a missing handler does mean the application is wired wrong.

Mapping events to Processes

Process mappers run a stateful workflow instead of dispatching a command. They need fractal-processes (pip install fractal-processes), which is imported only when a process mapper actually fires, and they need an application context:

projector = CommandBusProjector(
    lambda: context.command_bus,
    [],
    process_mappers=[BuildRoadWorkflow()],
    context_func=lambda: context,
)

context_func is injected rather than imported. The application context lives a layer above this package, and importing it here would point the middle of the stack at the top for one constructor call. Leaving it out while passing process mappers raises at construction time, not on whichever event happens to arrive first.

Event stores

Four flavours, differing only in how an event is stored and read back:

store stored as needs
ObjectEventStore the event object itself an in-memory repository
DictEventStore asdict(event) the event classes, to rebuild them
JsonEventStore a JSON string the event classes, plus an encoder
PickleEventStore a pickle

All of them take an EventStoreRepository, so where the messages actually land is a fractal-repositories concern rather than this package's.

Reading back an event whose class is no longer mapped raises EventNotMappedError rather than skipping it — a gap in a replayed stream is worse than a loud failure.

Development

make dev-install
make test
make lint
make format

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fractal_events-1.1.0.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fractal_events-1.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file fractal_events-1.1.0.tar.gz.

File metadata

  • Download URL: fractal_events-1.1.0.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.34.2

File hashes

Hashes for fractal_events-1.1.0.tar.gz
Algorithm Hash digest
SHA256 48edbc31602578816240de4e4027097689d2ccb05753191c764cf41f7e2edb3f
MD5 d6b1d59c6b80a97706c9ac9a5af7a0b8
BLAKE2b-256 3336320ac50e1be08ea98011406d5452e9f782d5b98fc3921a76e21677d286b5

See more details on using hashes here.

File details

Details for the file fractal_events-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for fractal_events-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8fbf3fd0015bdfd5e28675fb49461002c9ef584a703532f47d798b19b21c7395
MD5 d5d006673cad20d8ad8af37ce4e3772b
BLAKE2b-256 5859a96fd796479aa7c6efab722ba4829ad9c5c32fe1b7c8342eb1e1c45be239

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page