NAME

EventStore::Tiny - A minimal event sourcing framework.

ATTENTION: as of version 0.6 there is an API change regarding serialization which breaks existing applications that use serialization as well as their existing event stores.

CPAN version Travis CI tests Codecov test coverage Coveralls test coverage CPANTS kwalitee score

CPAN testers reports CPAN testers matrix GitHub repository GitHub issue tracker

SYNOPSIS

    use EventStore::Tiny;

    my $store = EventStore::Tiny->new;

    # Register event type
    $store->register_event(UserAdded => sub {
        my ($state, $data) = @_;

        # Use $data to inject the new user into the given $state
        $state->{users}{$data->{id}} = {
            name => $data->{name},
        };
    });

    # ...

    # Store an event instance represented by type and data
    $store->store_event(UserAdded => {id => 17, name => 'Bob'});

    # ...

    # Work with the current state snapshot generated by event application
    say 'His name is ' . $store->snapshot->state->{users}{17}{name}; # Bob

DESCRIPTION

In Event Sourcing, the state of a system is calculated as the application of a stream of events representing each change of the system. This framework is a minimal approach to use these mechanics in simple perl systems and offers these features:

  • Flexible snapshots (high-resolution timestamps) and event substreams.

  • Customizable event logging.

  • Simple storage solution for events in the file system.

  • Transparent snapshot caching mechanism to improve performance.

The internal state of the system needs to be represented by a simple (nested) hash and all events need to operate on this hash only (by side-effect).

REFERENCE

EventStore::Tiny implements the following attributes and methods, grouped by topic.

CONSTRUCTION AND PERSISTENCE

new

    my $store = EventStore::Tiny->new(init_data => {answer = 42});

Standard constructor. Understands all attributes as arguments. For most use cases, these are the sensible arguments:

init_data

A hashref representing the initial state. Default: {}

slack

See "SLACK MODE" below. Default: 0

cache_distance

The number of events after a new snapshot is cached for accellerated access. 0 means the cache is updated after each event. undef means the system does not use any caching. Default: 0

logger

A subref (callback) which will be called each time an event is applied to the state. The callback gets this event as its only argument. Default: "log_cb" in EventStore::Tiny::Logger

import_events

    $store->import_events($filename);

Loads events from a file which was written by "export_events" before. It replaces an existing event stream in $store. Note: before using the resulting events, the event types need to be registered as the transformations are only referenced.

export_events

    $store->export_events($filename);

Serializes the event stream to the file system. It can be imported back via "import_events" later.

EVENT SOURCING WORKFLOW

register_event

    $store->register_event(ConnectionRemoved => sub {
        my ($state, $data) = @_;
        # Change $state depending on $data (by side-effect)
    });

Stores an event type in the system by name and action on the $state. Events of this type can be added later to the event store by setting concrete $data with "store_event".

store_event

    $store->store_event(ConnectionRemoved => {id => 42});

Stores a concrete instance of an event type in the event store. The instance is defined by its event type name and a hash of data used by the subref the event uses to manipulate the state.

snapshot

    my $state1    = $store->snapshot->state;

    my $snapshot  = $store->snapshot(1234217421);
    my $state2    = $snapshot->state;
    my $timestamp = $snapshot->timestamp; # 1234217421

Returns a EventStore::Tiny::Snapshot object which basically consists of the corresponding state of the system (represented by a hashref) and the timestamp of the last used event. Snapshots are selected by the given argument timestamp, which returns the current snapshot at the given time. If no timestamp is given, the snapshot represents the last state of the system.

INTROSPECTION

event_names

    my $types = $store->event_names;

Returns an arrayref containing all event type names of registered events, sorted by name.

events

    my $event_stream = $store->events;

Returns the internal EventStore::Tiny::EventStream object that stores all concrete events (EventStore::Tiny::Event instances). Should be manipulated by "store_event" only. Events should never be changed or removed.

trans_store

    my $transformation_store = $store->trans_store

Returns the internal EventStore::Tiny::TransformationStore object that stores all transformation subroutines that events refer to. Should be manipulated by "register_event" only. The transformation store should never be changed or removed.

init_state

    my $state = $store->init_state;

Returns a cloned copy of the ininitial state all events are applied on, which was defined by "init_data" as a hashref.

SLACK MODE

By default, EventStore::Tiny is in strict mode. That means, that all "snapshot" data is cloned to prevent the internal state from illegal modification. However, if you really know what you're doing, you can activate "slack" mode to get references to the internal (cached) state. This improves performance a lot, but has also the downside that it can break your data consistence. You really have to make sure, that you modify your data with events only!

OTHER

is_correct_snapshot

    if ($store->is_correct_snapshot($snapshot)) {
        # ...
    }

Checks if a given EventStore::Tiny::Snapshot instance is a valid snapshot of our "events" event store. Mostly used for testing.

REPOSITORY AND ISSUE TRACKER

EventStore::Tiny's source repository is hosted on GitHub together with an issue tracker.

COPYRIGHT AND LICENSE

Copyright (c) 2018 Mirko Westermeier (@memowe, mirko@westermeier.de)

Released under the MIT License (see LICENSE.txt for details).

CONTRIBUTORS