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

Resetter Bundle Laravel Package

swoole-bundle/resetter-bundle

Resetter bundle for Swoole Bundle that clears Symfony service and container state between requests in long-running workers, preventing state from leaking across requests so applications stay consistent under Swoole.

View on GitHub
Deep Wiki
Context7

Getting Started

The resetter bundle is small and purpose-built: it ships a handful of ResetterInterface implementations (DBAL connection, Redis/\Redis, Memcached, PDO, possibly HTTP client) and wires them into a central service you call between "units of work" — an HTTP request handled by Swoole, or a message consumed by a Messenger worker. Nothing here changes your application behavior on a normal FPM request; it is only relevant once a process outlives a single request.

As of 2.1.1 the package is past 1.0 and actively patched (the DBAL resetter was just hardened — see Gotchas), so a ^2.1 constraint is reasonable, but re-read the DBAL resetter source on each minor bump: the reset semantics there are still being refined.

Minimal steps:

  1. composer require symfony-swoole/resetter-bundle:^2.1 (the repo is symfony-swoole/resetter-bundle; confirm the published Composer name and the bundle alias before trusting the README).
  2. Register ResetterBundle in config/bundles.php (Flex may not know this one — verify, because the bundle's alias may differ from the repo name).
  3. Confirm what it actually registered:
    php bin/console debug:container --tag=kernel.reset
    php bin/console debug:container --tag=resetter.resetter   # tag name may vary
    
    If you see no entries, the bundle's compiler pass did not find the services it expects (see Gotchas).
  4. First real use case: a Messenger worker. Add a reset call at the end of each message, either through the bundle's own listener or manually in your worker loop:
    foreach ($this->bus->pull() as $envelope) {
        $this->bus->dispatch($envelope);
        $this->resetter->reset();   // service id: check debug:container
    }
    

Where to look first: the bundle's DependencyInjection/ directory and any *.xml/*.php service file, then Resetter/Dbal/. Everything the bundle does is visible there — there is no runtime magic beyond tags and one compiler pass. If the README is thin, the service definitions are your documentation, and for connection semantics the DBAL resetter class is authoritative.

Implementation Patterns

Use the tagged-resetter aggregator, not individual services. The value of the package is that it collects resetters behind one interface so you can extend the list without changing call sites. Inject the aggregator (commonly a Resetter or ChainResetter service) and call reset() once.

Custom resetter for your own stateful service. Anything that caches per-request data — a tenant context, a request-scoped ID generator, an auth token holder, a ClockMock-style mutable state — should implement the package's resetter interface (or Symfony's ResetInterface if the bundle's aggregator accepts it) and be tagged:

final class TenantContextResetter implements ResetterInterface
{
    public function __construct(private TenantContext $context) {}

    public function reset(): void
    {
        $this->context->clear();
    }
}
services:
    App\Resetter\TenantContextResetter:
        tags: ['resetter.resetter']   # verify tag name in the bundle source

Doctrine specifically. Resetting the DBAL connection is not the same as resetting the EntityManager. The common, safe pattern for long-running workers is: on reset, if the EM is open, call $em->clear() (or reset()/close() depending on your Doctrine version) before the connection is reset/reconnected. Since 2.1.1 the bundle's DBAL resetter will unwind leftover transaction nesting for you and, if a level cannot be rolled back, close the connection outright — but that is a safety net, not a licence to reset mid-transaction. If the bundle only resets the connection, add your own EM resetter alongside it.

Integration with Symfony Messenger. Use the resetter via a WorkerListener/middleware rather than in consume() directly, so that retried and failed messages also pass through it. Keep retry logic (Doctrine's RetryableException handling) inside the same boundary as the reset, otherwise a deadlock retry can reuse a stale connection. Post-2.1.1 a leftover transaction after an exception is cleaned up by the resetter, which makes the "reset after a failed message" path noticeably safer than before.

Integration with Swoole. Under the Swoole bundle, reset after the response is emitted and before the coroutine is recycled. The reset must not touch coroutine-local state owned by the Swoole runtime — only your connections and caches. If you have any Swoole\Coroutine\Channel or connection pool, let the pool handle its own pooling and reset only the PDO/Redis handles the app holds.

Reset granularity. Prefer "reset everything cheap" per message over conditional resets. A boolean $dirty flag that skips resets is the most common way stale state leaks in; it is also unnecessary — the reset itself should be cheap and idempotent. The 2.1.1 fix makes the DBAL resetter's no-op-ness harder: it now actively walks transaction nesting levels instead of assuming flatness, so do not try to replicate that logic in your own resetter.

Gotchas and Tips

  • Read the bundle source before deploying. In particular, verify the tag name it uses in its compiler/extension — a mismatch between the bundle's expected tag and what you configure will silently produce an empty aggregator, and reset() will be a no-op. A quick debug:container after install catches this.
  • Transaction handling changed in 2.1.1 — know what it does and what it doesn't. The DBAL resetter now discards every nesting level of a leftover transaction (not just the top one), and closes a connection it cannot roll back. Practical consequences:
    • Nested transactions left open by a failed message no longer wedge the connection on the next message — good news for Messenger retry paths.
    • A connection may now come back closed rather than reset. Anything holding that handle — an open EntityManager, a repository, a service that captured Connection — must tolerate a lazy reconnect, or you must reset the EM after the connection resetter runs.
    • The "cannot be rolled back" branch means you can see a closed connection where previous versions silently returned a half-broken one. If you have code asserting $connection->isConnected() after reset, re-check it.
    • This is still a cleanup of last resort. Reset only when your unit of work is complete and committed (or rolled back); never rely on the resetter to undo an in-flight transaction.
  • EntityManager vs connection ordering. Resetting the connection under an open EntityManager leaves it thinking the connection is alive — and after 2.1.1 the connection may literally be closed, which turns that stale belief into an immediate failure. Order: $em->clear() → connection reset → (optionally) $em->isOpen() check and reopen. Add your own resetter if the bundle doesn't cover this.
  • reset() should be idempotent and exception-safe. A resetter that throws on a half-closed connection will kill the worker. The DBAL resetter now swallows the un-rollbackable case by closing, but other resetters (Redis, Memcached, HTTP) have no such guard: wrap each call in try/catch and log-and-reconnect rather than propagate.
  • Redis clients. \Redis and Predis have different reset semantics. Predis's disconnect() leaves you with a stale client unless you reconnect lazily; phpredis needs close() and a fresh connect(). Check which one the packaged resetter targets, or write yours.
  • Log handlers and buffered state. Monolog BufferHandler/FingersCrossedHandler and Symfony's profiler will accumulate across a long-lived worker. If you run the bundle in dev with the profiler enabled, memory grows regardless of connection resets — disable the profiler in any long-running process.
  • kernel.reset overlap. Symfony's own services_resetter also operates on the kernel.reset tag. If you use both, reset ordering matters, and with 2.1.1's connection-closing behaviour double-resetting a connection is less obviously harmless than it used to be. Pick one mechanism per process; use this bundle's tag for the app-specific resetters and let the framework handle the rest, or don't enable both.
  • Configuration quirks. Check whether the extension has an enable flag or a service-list option (resetters: [...]) before assuming all resetters are on. Also check whether the bundle respects %kernel.debug% — some bundles skip wiring in debug, which produces the confusing "works in prod, silent no-op in dev" failure.
  • Version pinning. Pin to ^2.1 and let patch releases in: 2.1.1 is a pure robustness fix to the DBAL resetter with no API change, which is exactly the kind of patch you want. Still read the changelog on minor bumps — the DBAL resetter's reset semantics are the moving part in this package, and a 2.2 could change constructor signatures without deprecation.
  • Extension point if coverage is thin. If the bundle lacks a resetter you need, register your own under the same tag. That's the supported extension path — there is no need to fork; the tag-based aggregator is the contract.
  • Testing the reset. Write an integration test that runs two consecutive units of work in one process (a short Messenger worker loop is the easiest harness) and asserts that state from the first does not leak into the second. Since 2.1.1, add a second case: throw mid-transaction inside the first unit (including a nested/savepoint transaction), swallow the exception, reset, and assert the second unit can write — that path exercises exactly the code the patch touched. A unit test of a single resetter won't catch a missing tag.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log