Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Snapshotter Laravel Package

prooph/snapshotter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require prooph/snapshotter
    

    Add to composer.json under require-dev if using for testing.

  2. First Use Case: Snapshot Creation Define a snapshot for an aggregate root (e.g., Order):

    use Prooph\Snapshotter\AggregateSnapshot;
    
    class OrderSnapshot extends AggregateSnapshot
    {
        public function __construct(
            string $aggregateId,
            int $version,
            string $state,
            int $totalItems,
            float $totalPrice
        ) {
            parent::__construct($aggregateId, $version, $state);
            $this->totalItems = $totalItems;
            $this->totalPrice = $totalPrice;
        }
    }
    
  3. Register Snapshot in Event Store Configure the snapshotter in your EventStore setup:

    $snapshotter = new Prooph\Snapshotter\Snapshotter(
        $eventStore,
        new Prooph\Snapshotter\Metadata\SnapshotMetadataFactory(),
        new Prooph\Snapshotter\Serializer\JsonSerializer()
    );
    
  4. Trigger Snapshot on Aggregate Use the Snapshotter in your aggregate root:

    $this->snapshotter->takeSnapshot(
        new OrderSnapshot(
            $this->aggregateId(),
            $this->version(),
            'confirmed',
            $this->totalItems(),
            $this->totalPrice()
        )
    );
    

Implementation Patterns

Workflow: Snapshot-Driven Rehydration

  1. Check for Snapshots on Load

    $snapshot = $snapshotter->getSnapshot($aggregateId);
    if ($snapshot) {
        $this->reconstructFromSnapshot($snapshot);
    }
    
  2. Conditional Snapshot Triggering Use version-based or event-based triggers:

    if ($this->version() % 10 === 0) {
        $this->snapshotter->takeSnapshot($snapshot);
    }
    

Integration with Prooph CQRS

  • Event Store Integration Pair with prooph/event-store for seamless snapshot storage/retrieval:

    $eventStore->load($aggregateId, $snapshotter);
    
  • Command Handling Use snapshots to optimize command processing:

    if ($snapshot && $snapshot->version() >= $expectedVersion) {
        return $snapshot->state(); // Skip replay
    }
    

Serialization Strategies

  • Custom Serializers Implement Prooph\Snapshotter\Serializer\SnapshotSerializerInterface for domain-specific formats (e.g., XML, Avro):
    class CustomSerializer implements SnapshotSerializerInterface
    {
        public function serialize($snapshot): string { ... }
        public function unserialize(string $serialized): object { ... }
    }
    

Gotchas and Tips

Pitfalls

  1. Version Mismatch

    • Snapshots must match the aggregate’s current version. Always validate:
      if ($snapshot->version() !== $this->version()) {
          throw new \RuntimeException("Snapshot version mismatch");
      }
      
  2. Serialization Errors

    • Non-serializable properties (e.g., closures, resources) will break snapshot storage. Use __serialize()/__unserialize() or exclude them.
  3. Concurrency Issues

    • Snapshots are not atomic with event appends. Use EventStore::appendToStream() with snapshots in a single transaction if possible.

Debugging

  • Inspect Stored Snapshots Query the event store directly:

    php artisan prooph:events:list --stream=order-123
    

    Look for SnapshotCreated events.

  • Enable Logging Configure the Snapshotter to log snapshot operations:

    $snapshotter->setLogger(new Monolog\Logger('snapshotter'));
    

Extension Points

  1. Metadata Customization Extend SnapshotMetadata for additional metadata (e.g., timestamps, user IDs):

    class ExtendedMetadata extends SnapshotMetadata
    {
        public function setTakenAt(\DateTimeInterface $dateTime): self { ... }
    }
    
  2. Snapshot Validation Implement Prooph\Snapshotter\SnapshotValidatorInterface to enforce business rules:

    class OrderSnapshotValidator implements SnapshotValidatorInterface
    {
        public function validate($snapshot): void
        {
            if ($snapshot->totalPrice < 0) {
                throw new \InvalidArgumentException("Price cannot be negative");
            }
        }
    }
    
  3. Performance Tuning

    • Batch Snapshots: For high-throughput systems, batch snapshot creation/retrieval.
    • Lazy Loading: Load snapshots only when needed (e.g., in read models).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
baks-dev/finances
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager