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

Savepoint Prevent Crash Bundle Laravel Package

dualmedia/savepoint-prevent-crash-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation
    composer require dualmedia/savepoint-prevent-crash-bundle
    
  2. Enable Bundle Add to config/bundles.php:
    DualMedia\DoctrineRetryBundle\DoctrineRetryBundle::class => ['all' => true],
    
  3. First Use Case
    • Scenario: You’re running a transaction with nested savepoints (e.g., in a Symfony controller or service) and encountering MariaDB/MySQL crashes on rollback.
    • Action: No additional code changes are needed—the bundle auto-injects middleware to handle rollbacks gracefully. Test by triggering a rollback in a transaction:
      $entityManager->beginTransaction();
      try {
          // Your logic here
          $entityManager->rollback(); // Now handled safely
      } catch (\Exception $e) {
          $entityManager->rollback(); // Still safe
      }
      

Implementation Patterns

Core Workflows

  1. Transaction Management

    • Pattern: Use savepoints for partial rollbacks in long-running transactions (e.g., multi-step workflows).
      $entityManager->beginTransaction();
      $entityManager->getConnection()->beginTransaction('savepoint_name');
      try {
          // Step 1: Save data
          $entityManager->flush();
          $entityManager->getConnection()->commit('savepoint_name');
      
          // Step 2: Save more data (may fail)
          $entityManager->getConnection()->beginTransaction('savepoint_name_2');
          // ... logic ...
          $entityManager->getConnection()->commit('savepoint_name_2');
      } catch (\Exception $e) {
          $entityManager->getConnection()->rollback('savepoint_name_2'); // Safe rollback
          $entityManager->rollback(); // Outer transaction
      }
      
    • Leverage: Combine with dualmedia/doctrine-retry-bundle for automatic retries on savepoint failures.
  2. Symfony Event Listeners

    • Pattern: Attach listeners to kernel.exception or doctrine.orm.post_flush to log/handle rollback crashes.
      // src/EventListener/RollbackCrashListener.php
      use DualMedia\DoctrineRetryBundle\Event\RollbackCrashEvent;
      
      public function onRollbackCrash(RollbackCrashEvent $event) {
          $this->logger->warning('Rollback crash detected', [
              'savepoint' => $event->getSavepointName(),
              'exception' => $event->getException(),
          ]);
      }
      
    • Register in services.yaml:
      services:
          App\EventListener\RollbackCrashListener:
              tags:
                  - { name: 'kernel.event_listener', event: 'dualmedia.doctrine_retry.rollback_crash' }
      
  3. Doctrine Event Subscribers

    • Pattern: Override postFlush or onFlush to inject custom savepoint logic.
      use Doctrine\ORM\Event\OnFlushEventArgs;
      
      public function onFlush(OnFlushEventArgs $args) {
          $entityManager = $args->getEntityManager();
          if ($entityManager->isTransactionActive()) {
              $entityManager->getConnection()->beginTransaction('custom_savepoint');
          }
      }
      

Integration Tips

  • With Doctrine Retry Bundle: Enable retries for savepoint operations in config/packages/dualmedia_doctrine_retry.yaml:
    doctrine_retry:
        enabled: true
        retry_on_savepoint_failure: true
    
  • Logging: Use Monolog to track savepoint activity:
    $this->logger->debug('Savepoint committed', ['savepoint' => 'savepoint_name']);
    
  • Testing: Mock rollback crashes in PHPUnit:
    $this->entityManager->getConnection()->setRollbackCrashMock(true);
    

Gotchas and Tips

Pitfalls

  1. MariaDB-Specific Behavior

    • Issue: The bundle targets MariaDB/MySQL’s quirks (e.g., Doctrine Issue #11230). PostgreSQL/SQLite users: This bundle is irrelevant—ignore or uninstall.
    • Fix: None needed; the bundle auto-detects DBMS and skips if not MariaDB/MySQL.
  2. Nested Savepoints

    • Issue: Deeply nested savepoints (e.g., >5 levels) may still crash due to MariaDB limits.
    • Workaround: Flatten savepoint hierarchy or increase max_nested_savepoints in your MariaDB config.
  3. Transaction Isolation

    • Issue: Savepoints don’t isolate transactions fully. Long-running savepoints may block others.
    • Tip: Use READ COMMITTED isolation level for savepoints:
      $connection->setTransactionIsolation(\PDO::TRANSACTION_READ_COMMITTED);
      
  4. Middleware Conflicts

    • Issue: Other middleware (e.g., Symfony’s TransactionMiddleware) may interfere.
    • Tip: Load this bundle after FrameworkBundle but before custom middleware in config/bundles.php.

Debugging

  • Enable Verbose Logging Add to config/packages/monolog.yaml:
    handlers:
        dualmedia:
            type: stream
            path: "%kernel.logs_dir%/doctrine_retry.log"
            level: debug
            channels: ["dualmedia"]
    
  • Check for Silent Failures The bundle suppresses crashes but logs them. Verify logs for:
    [DualMedia\DoctrineRetryBundle] Rollback crash detected for savepoint "name"
    

Extension Points

  1. Custom Rollback Handlers

    • Override the default handler by binding your own service to dualmedia.doctrine_retry.rollback_handler:
      services:
          App\Service\CustomRollbackHandler:
              tags:
                  - { name: 'dualmedia.doctrine_retry.rollback_handler' }
      
    • Implement DualMedia\DoctrineRetryBundle\Handler\RollbackHandlerInterface.
  2. Savepoint Naming Strategy

    • Default: Auto-generates names like sp_12345. Customize via a service:
      // src/Service/CustomSavepointNamer.php
      use DualMedia\DoctrineRetryBundle\Namer\SavepointNamerInterface;
      
      class CustomSavepointNamer implements SavepointNamerInterface {
          public function generateName(): string {
              return 'app_' . uniqid();
          }
      }
      
    • Register in services.yaml:
      DualMedia\DoctrineRetryBundle\:
          arguments:
              $savepointNamer: '@App\Service\CustomSavepointNamer'
      
  3. Database-Specific Tweaks

    • For MariaDB 10.4+, enable innodb_nested_rollback_depth in my.cnf:
      [mysqld]
      innodb_nested_rollback_depth = 10
      
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.
make-dev/orca
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