Replaying events | laravel-event-sourcing | Spatie

 SPATIE

  Laravel Event Sourcing
=========================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-event-sourcing](https://spatie.be/docs/laravel-event-sourcing/v7)  Advanced-usage  Replaying events

 Version   v7   v6   v5   v4   v3   v2   v1

 Other versions for crawler [v7](https://spatie.be/docs/laravel-event-sourcing/v7) [v6](https://spatie.be/docs/laravel-event-sourcing/v6) [v5](https://spatie.be/docs/laravel-event-sourcing/v5) [v4](https://spatie.be/docs/laravel-event-sourcing/v4) [v3](https://spatie.be/docs/laravel-event-sourcing/v3) [v2](https://spatie.be/docs/laravel-event-sourcing/v2) [v1](https://spatie.be/docs/laravel-event-sourcing/v1)

- [ Introduction ](https://spatie.be/docs/laravel-event-sourcing/v7/introduction)
- [ Support us ](https://spatie.be/docs/laravel-event-sourcing/v7/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-event-sourcing/v7/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-event-sourcing/v7/installation-setup)
- [ Questions and issues ](https://spatie.be/docs/laravel-event-sourcing/v7/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-event-sourcing/v7/changelog)
- [ Upgrading ](https://spatie.be/docs/laravel-event-sourcing/v7/upgrading)
- [ Resources and alternatives ](https://spatie.be/docs/laravel-event-sourcing/v7/resources-and-alternatives)
- [ About us ](https://spatie.be/docs/laravel-event-sourcing/v7/about-us)

Getting familiar with event sourcing
------------------------------------

- [ Introduction ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/introduction)
- [ The traditional application ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/the-traditional-application)
- [ Using projectors to transform events ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/using-projectors-to-transform-events)
- [ Using aggregates to make decisions based on the past ](https://spatie.be/docs/laravel-event-sourcing/v7/getting-familiar-with-event-sourcing/using-aggregates-to-make-decisions-based-on-the-past)

Using projectors
----------------

- [ Writing your first projector ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/writing-your-first-projector)
- [ Creating and registering projectors ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/creating-and-configuring-projectors)
- [ Making sure events get handled in the right order ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/making-sure-events-get-handled-in-the-right-order)
- [ Thinking in events ](https://spatie.be/docs/laravel-event-sourcing/v7/using-projectors/thinking-in-events)

Using reactors
--------------

- [ Writing your first reactor ](https://spatie.be/docs/laravel-event-sourcing/v7/using-reactors/writing-your-first-reactor)
- [ Creating and configuring reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/using-reactors/creating-and-configuring-reactors)

Using aggregates
----------------

- [ Writing your first aggregate ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/writing-your-first-aggregate)
- [ Creating and configuring aggregates ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/creating-and-configuring-aggregates)
- [ Testing aggregates ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/testing-aggregates)
- [ Snapshots ](https://spatie.be/docs/laravel-event-sourcing/v7/using-aggregates/snapshots)

Advanced usage
--------------

- [ Preparing events ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/preparing-events)
- [ Replaying events ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/replaying-events)
- [ Storing metadata ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/storing-metadata)
- [ Handling exceptions ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/handling-exceptions)
- [ Discovering projectors and reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/discovering-projectors-and-reactors)
- [ Using your own event storage model ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-storage-model)
- [ Using your own event storage repository ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-storage-repository)
- [ Using your own event serializer ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-serializer)
- [ Using aliases for stored event classes ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/using-aliases-for-stored-event-classes)
- [ Adding and Removing Projectors and Reactors ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/adding-and-removing-projectors-and-reactors)
- [ Aggregate Partials ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/aggregate-partials)
- [ Event Queries ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/event-queries)
- [ Commands ](https://spatie.be/docs/laravel-event-sourcing/v7/advanced-usage/commands)

 Replaying events
================

###  On this page

1. [ Detecting event replays ](#content-detecting-event-replays)
2. [ Performing some work before and after replaying events ](#content-performing-some-work-before-and-after-replaying-events)
3. [ Models with timestamps ](#content-models-with-timestamps)
4. [ What about reactors? ](#content-what-about-reactors)
5. [ Want to know more? ](#content-want-to-know-more)

All [events](/docs/laravel-event-sourcing/v7/advanced-usage/preparing-events/) that implement `Spatie\EventSourcing\ShouldBeStored` will be [serialized](/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-serializer) 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](/docs/laravel-event-sourcing/v7/using-projectors/writing-your-first-projector/) you'll want to feed all stored events to that new projector. We call this process replaying events.

Events can be replayed to [all projectors that were added to the projectionist](/docs/laravel-event-sourcing/v7/using-projectors/creating-and-configuring-projectors/) with this artisan command:

```
php artisan event-sourcing:replay
```

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

```
 php artisan event-sourcing:replay App\\Projectors\\AccountBalanceProjector
```

You can use the projector argument multiple times:

```
 php artisan event-sourcing:replay App\\Projectors\\AccountBalanceProjector 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 run the replay for a specific aggregate, the specified uuid will be passed as a parameter.

```
public function resetState(?string $aggregateUuid = null): void
{
    // reset your projector
}
```

If you want to replay events starting from a certain event you can use the `--from` option when executing `event-sourcing: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](/docs/laravel-event-sourcing/v7/advanced-usage/using-your-own-event-storage-model/) then you will need to use the `--stored-event-model` option when executing `event-sourcing:replay` to specify the model storing the events you want to replay.

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

If you only want to reply events for a specific aggregate only, you can use the `--aggregate-uuid` option.

```
php artisan event-sourcing:replay --aggregate-uuid=12345678-1234-1234-1234-1234567890ab
```

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\EventSourcing\Events\StartingEventReplay` and `Spatie\EventSourcing\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\EventSourcing\Facades\Projectionist::isReplaying(); // 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 extends Projector
{
    // ...

    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 behaviour you intended. To work around this you can use the stored event's timestamps:

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

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.

Want to know more?
------------------------------------------------------------------------------------------------------------

Our course, [Event Sourcing in Laravel](https://event-sourcing-laravel.com/) covers this topic in depth:

- 6. [Projectors in Depth](https://event-sourcing-laravel.com/projectors-in-depth)
- 16. Event Versioning
- 20. Deployment Strategies
