Replaying events

All events that implement Spatie\EventProjector\ShouldBeStored will be serialized and stored in the stored_events table. After your app has been doing its work for a while the stored_events table will probably contain some events.

When creating a new projector or reactor you’ll want to feed all stored events to that new projector or reactor. We call this process replaying events.

Events can be replayed to all projectors that were added to the projectionist with this artisan command:

 php artisan event-projector:replay

You can also specify projectors by using the --projector option. All stored events will be passed only to that projector.

  php artisan event-projector:replay --projector=App\\Projectors\\AccountBalanceProjector

You can use the projector option multiple times:

   php artisan event-projector:replay --projector=App\\Projectors\\AccountBalanceProjector --projector=App\\Projectors\\AnotherProjector

If your projector has a resetState method it will get called before replaying events. You can use that method to reset the state of your projector.

If you want to replay events starting from a certain event you can use the --from option when executing event-projector:replay. If you use this option the resetState on projectors will not get called. This package does not track which events have already been processed by which projectors. Be sure not to replay events to projectors that already have handled them.

If you are using your own event storage model then you will need to use the --store-event-model option when executing event-projector:replay to specify the model storing the events you want to replay.

php artisan event-projector:replay --stored-event-model=App\\Models\\AccountStoredEvent

Detecting event replays

If your projector contains an onStartingEventReplay method, we’ll call it right before the first event is replayed.

If it contains an onFinishedEventReplay method, we’ll call it right after all events have been replayed.

You can also detect the start and end of event replay by listening for the Spatie\EventProjector\Events\StartingEventReplay and Spatie\EventProjector\Events\FinishedEventReplay events.

Though, under normal circumstances, you don’t need to know this, you can detect if events are currently being replayed like this:

Spatie\EventProjector\Facades\Projectionist::isReplayingEvents(); // returns a boolean

Performing some work before and after replaying events

If your projector has a onStartingEventReplay method, it will get called right before the first event will be replayed. This can be handy to clean up any data your projector writes to. Here’s an example where we truncate the accounts table before replaying events:

namespace App\Projectors;

use App\Account;

// ...

class AccountBalanceProjector implements Projector
{
    use ProjectsEvents;

    // ...

    public function onStartingEventReplay()
    {
        Account::truncate();
    }
}

After all events are replayed, the onFinishedEventReplay method will be called, should your projector have one.

Models with timestamps

When using models with timestamps, it is important to keep in mind that the projector will create or update these models when replaying and the timestamps will not correspond to the event’s original timestamps. This will probably not be behavior you intended. To work around this you can use the stored event’s timestamps:

public function onAccountCreated(StoredEvent $storedEvent, AccountCreated $event) {
        Account::create(array_merge($event->accountAttributes, ['created_at' => $storedEvent->created_at, 'updated_at' => $storedEvent->created_at]));
}

What about reactors?

Reactors are used to handle side effects, like sending mails and such. You’ll only want reactors to do their work when an event is originally fired. You don’t want to send out mails when replaying events. That’s why reactors will never get called when replaying events.