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.0.0.tar.gz (14.8 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.0.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for fractal_events-1.0.0.tar.gz
Algorithm Hash digest
SHA256 b27c6f5de1289b988021192d249fc84bfacb5d67672c05479ad8a50c6b22decf
MD5 7723dead1732fbd9b854a9abbe1e7e39
BLAKE2b-256 861c58876f351f960eb216619667c731ccb5ed0628990260d3bb718f617ec249

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for fractal_events-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ebee37ea3f590832a3abd927b5d72b0df00923a3c3cd9e72579bc0210198cfc2
MD5 477bc3603e4ed77dc9056d5fc68c0e78
BLAKE2b-256 d44ea6acd9b73c0d73cb81d46c4cb8efc7d9b44235454cc67960d97a7ce0d780

See more details on using hashes here.

Release history Release notifications | RSS feed

1.1.0

2 files

This release

1.0.0 This release

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