micro-module/enqueue-fs
Filesystem-backed Enqueue transport for PHP that stores messages as files, enabling lightweight queues without an external broker. Ideal for local development, testing, and small workloads needing simple, durable message passing.
Minimal steps:
composer require micro-module/enqueue-fs enqueue/enqueue
var/queue). This directory is your queue — messages are persisted as files.Context / TransportFactory classes (namespace MicroModule\EnqueueFs\...). Like every Enqueue transport, the integration surface is a trio: createContext(), createTransport(), createDestination().use Enqueue\Fs\FsConnectionFactory;
$context = (new FsConnectionFactory('file://'.__DIR__.'/var/queue'))->createContext();
$queue = $context->createQueue('emails');
$context->createProducer()->send($queue, $context->createMessage('hello'));
⚠️ Before relying on it: this package has 0 stars, 0 dependents, and no visible release cadence beyond Oct 2024. Treat the README/source as the only authority; there is no community to lean on. Verify the exact namespace and factory signature from
vendor/micro-module/enqueue-fs/srcafter install — do not assume from Enqueue's ownenqueue/fspackage, which this mirrors but is not identical to.As of 0.10.21 the package no longer depends on
enqueue/dsn; DSN parsing now comes frommicro-module/dsn. Runcomposer show micro-module/dsn enqueue/dsnafter install and confirm which DSN classes are actually autoloaded before type-hinting or extending anything DSN-related (see Gotchas).
1. Producer/consumer split
Producers write message files into the spool; consumers poll and ack() to remove them. Typical worker loop:
$consumer = $context->createConsumer($queue);
while (true) {
if ($message = $consumer->receive(5000)) { // ms timeout
try {
handle($message->getBody());
$consumer->acknowledge($message);
} catch (\Throwable $e) {
$consumer->reject($message, true); // requeue
}
}
}
2. Laravel integration
Bind the Context as a singleton in a service provider; register a FsConnector alongside Laravel's queue connectors so Queue::push()/queue:work use the filesystem transport. Store the spool under storage/app/queue and add it to .gitignore and to your deploy cleanup script.
3. Symfony integration
Register the transport factory as a service and expose it via enqueue.transport.fs config. Use messenger:consume-style workers or Enqueue's Client command.
4. Test isolation
For unit/integration tests, point the factory at a sys_get_temp_dir() path per test case and delete it in tearDown(). This gives you realistic async behaviour (serialization, worker loop) without mocking the transport.
5. Cron-driven workers
Because there's no long-lived broker connection, a one-shot worker (receive until empty, then exit) invoked by cron/systemd timer is a natural fit. Keep jobs idempotent — see gotchas.
6. Keep DSN construction in one place
Now that the DSN parser is a separate MicroModule dependency (0.10.21+), centralise DSN strings in config (config/queue.php, .env) rather than building them inline across the codebase. If you later swap transports or the DSN library shifts namespaces again, you change one string instead of grepping for new FsConnectionFactory(.
rename()/flock() on message files before running more than one worker. When in doubt, run a single worker per spool directory.enqueue/redis or AMQP instead — the Enqueue abstractions let you swap transports without touching handler code.flock, atomic renames, and file mtime behave inconsistently over NFS. Keep the spool on local disk.dead/ subdirectory yourself.root-owned file from a misconfigured cron job will silently stall consumers.ls -la var/queue and cat a message file to inspect the payload — far easier than rabbitmqctl. Use this to triage stuck jobs when first integrating.content_type, message_id). Keep payloads JSON-serializable; avoid closures/resources. Verify round-trip in a test before wiring into business logic.enqueue/dsn was replaced by micro-module/dsn. Two things can bite you:
enqueue/dsn, you may end up with two DSN implementations installed — different class names, same conceptual role. Don't rely on transitive enqueue/dsn being absent just because this package dropped it; check composer why enqueue/dsn.Enqueue\Dsn\Dsn or catches its exception classes is now decoupled from this package's DSN parsing. Confirm whether micro-module/dsn ships a compatible/aliased type or a distinct one — a mismatch surfaces at runtime (argument type errors), not at composer install.FsConnectionFactory you're unaffected; the risk is concentrated in code that touches DSN objects directly.composer.json (e.g. "micro-module/enqueue-fs": "0.10.21" or a tight ~0.10.21 range), and if you extend it, prefer writing a thin wrapper (your own MessageBus service) rather than calling the transport directly everywhere — that gives you an escape hatch to swap to Redis/AMQP later. Given the enqueue/dsn → micro-module/dsn swap landed in a patch release, assume other dependency-level changes may arrive the same way; a loose ^0.10 constraint is riskier than it looks.Context interface is the seam: you can decorate the transport (logging, metrics, retries) in a wrapper class without touching the package.enqueue/* version constraint matches your project's Enqueue version; the transport interface has moved between major versions and a mismatch fails at runtime, not install time. After upgrading to 0.10.21+, also run composer update --dry-run and a smoke test of FsConnectionFactory DSN parsing — that's the exact code path the dependency swap touches.How can I help you explore Laravel packages today?