Weave 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

Symfony Lock Doctrine Migrations Bundle Laravel Package

marein/symfony-lock-doctrine-migrations-bundle

A Symfony bundle that integrates the Lock component with Doctrine Migrations, using locks to prevent concurrent migration runs. Keeps deployments safe across multiple servers or containers by ensuring only one process executes migrations at a time.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Know what you're installing first. This is a Symfony bundle (Marein\SymfonyLockDoctrineMigrationsBundle\MareinSymfonyLockDoctrineMigrationsBundle), not a Laravel package. There is no service provider, no config/*.php publish tag, and no Artisan integration. If your app is Laravel, you cannot composer require this and get value — skip to the pattern in Implementation Patterns below and reimplement the idea with Cache::lock().
  • If you are on Symfony + doctrine/doctrine-migrations-bundle: composer require marein/symfony-lock-doctrine-migrations-bundle plus symfony/lock. Flex auto-registers it; otherwise add the bundle to config/bundles.php.
  • Open first: bin/console config:dump-reference marein_lock_doctrine_migrations. The docs are sparse, this command is the source of truth for option names on your installed version. Then look at how the migration executor is decorated — that tells you whether anything in your app already hooks the migrate command.
  • First use case: a rolling deploy or CI job where two or more callers run bin/console doctrine:migrations:migrate --no-interaction simultaneously. The bundle makes the second caller wait (or bail) instead of racing on the doctrine_migration_versions table. Prove it in staging with two concurrent replicas before it ever matters in production.

Implementation Patterns

  • Default wiring. Empty config means the executor is decorated with a lock from Symfony's default lock factory. Fine for a single host, effectively useless across containers.

  • Explicit shared store — the only production-safe setup. flock/semaphore are host-local, so point at Redis, a PDO store, or Postgres advisory locks:

    framework:
        lock:
            migrations: '%env(REDIS_DSN)%'
    
    marein_lock_doctrine_migrations:
        lock: 'lock.migrations'
    
  • Deploy-pipeline pattern. Keep doctrine_migrations: config for paths/namespace/table untouched — this bundle only wraps execution. Invoke bin/console doctrine:migrations:migrate --no-interaction --allow-no-migration from your release script and let the lock serialize it.

  • Choose blocking vs fail-fast deliberately. Blocking = second deploy waits for the first to finish (usually right). Fail-fast = second deploy aborts; catch the lock-acquiring exception in your release script and exit non-zero so the orchestrator retries.

  • Laravel-side equivalent, which is what you'll actually ship. Key the lock on the connection so parallel migrations against different databases don't block each other:

    $lock = Cache::lock('doctrine-migrations:'.config('database.default'), 300);
    
    if (! $lock->get()) {
        $this->error('Another deployment is migrating.');
        return 1;
    }
    
    try {
        Artisan::call('migrate', ['--force' => true]);
    } finally {
        $lock->release();
    }
    

    Note Laravel's own migrate command already guards against concurrent runs in newer versions — verify before adding the wrapper.

  • Extension point: because the bundle decorates rather than replaces the executor, any custom MigrationExecutor or Doctrine event subscriber you already have keeps working. Hook lifecycle via onMigrationsMigrated; don't try to wrap the bundle's internals.

Gotchas and Tips

  • Wrong framework is the #1 error. The Bundle class, DependencyInjection/Configuration.php, and framework.lock are all Symfony-specific. This will never autoload usefully in Laravel.
  • Host-local lock stores silently do nothing. flock and semaphore work only per-machine; in Docker/Kubernetes you get zero protection. If your "safe migrations" setup uses the default store across replicas, you have not solved anything.
  • TTL must exceed your slowest migration. If the lock expires mid-run, a second process starts migrating concurrently. Also confirm the lock is released reliably when a migration throws.
  • Don't lock on the database you're migrating. With a PDO/DB store, dropping or recreating the schema can invalidate the lock mid-run. Use Redis for those cases.
  • Debugging a stuck deploy: inspect the store directly (redis-cli keys '*migration*'), or use the Symfony profiler's Lock panel in dev. A stale key is almost always a SIGKILLed process, not a bundle bug — add a scheduled check that no lock stays held after a failed deploy.
  • Copy-paste config errors are easy. Re-run config:dump-reference on your installed version instead of trusting snippets; option names are stable but documentation is thin.
  • Version alignment (1.0.4). Maintenance-only: PHP 8.4 added to CI, dependency constraints widened and tested, a compose.yaml for local testing. No breaking changes, no deprecations, safe from 1.0.3. But the widened constraints mean Composer may now resolve symfony/lock / doctrine/migrations combinations the maintainer's CI never exercised — treat composer.lock as the contract, and gate any bump of those two packages on a staging two-replica concurrency test.
  • Bus factor. Eight stars, single maintainer, low cadence. The whole behaviour is roughly thirty lines of code in your deploy script — keep that documented so removing the dependency is a same-day call, not a migration project.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel