enqueue/dsn
Enqueue DSN is a small PHP library for parsing Data Source Name strings into structured connection configuration for the Enqueue messaging abstraction, making it easy to configure transports like AMQP, Redis, and others from a single URL.
enqueue/dsn is a narrow, stateless parsing utility: it turns DSN strings (amqp://user:pass@host:5672/%2f, redis://:[email protected]:6379/0) into structured connection parameters. Architecturally it is a leaf dependency — no framework coupling, no I/O, no shared state. For a Laravel/PHP stack that already brokers async work through Enqueue transports, it fills a real gap: consistent, tested DSN handling instead of bespoke parse_url() + regex code scattered across config and CLI commands.
The TPM-level framing matters here: this is not an architectural decision, it is a build-vs-buy decision on ~100 lines of parsing logic. The correct question is not "does this belong in our architecture?" (it does not change it) but "do we want to own DSN grammar in-house, or delegate it to a small, MIT-licensed dependency?" The opportunity score (56) and zero dependents suggest the package is functional but not ecosystem-critical — it will not shape the architecture either way.
Scope caveat worth surfacing early: the repository is the enqueue-dev monorepo (queues, broadcasting, WebSockets, Symfony/Laravel/Magento bindings), while this package is only the DSN parser. Stakeholders conflating the two will over-estimate what adoption buys them.
High, with low ceremony. A single Composer require, no service provider, no config publication, no migrations. Integration is a two-line change at the call site:
use Enqueue\Dsn\Dsn;
$parsed = Dsn::parse(config('queue.connections.rabbitmq.dsn'));
Realistic integration points in a Laravel codebase:
.env into discrete host/port/user/vhost values at boot or during config:cache.The blocker is API surface ambiguity. Source material references both Enqueue\Dsn\Dsn::parse() and Enqueue\Dsn\ParsedDsn::parse(), plus a new Dsn($dsn)->parse() instance form. These are mutually inconsistent. Feasibility is high; confidence is not, until someone reads the actual tagged source. That is a one-hour spike, not a design phase.
Overall low-to-moderate, with one non-obvious risk: scope creep on the abstraction. The dependency is trivial; the temptation to build a full "multi-broker connection abstraction" on top of it is not. Guard the boundary — this package parses strings, it does not manage connections.
| Risk | Likelihood | Impact | TPM disposition |
|---|---|---|---|
| Stale/unsupported package (no active maintainer for the DSN component) | Medium | Low | Accept; fork vendored copy if it becomes load-bearing |
Incorrect API assumption from docs (Dsn vs ParsedDsn vs static) |
Medium | Low | Gate: verify against installed source before design sign-off |
| Misleading signal from monorepo release dates (2026 tag ≠ DSN package touched) | Medium | Low | Treat "release recency" as repo-level, not package-level |
| Unsupported schemes (SQS, Kafka, Pulsar, custom) | Medium | Medium | Enumerate required schemes in Phase 0; extend or wrap |
| Parsing edge cases (IPv6 literals, percent-encoded vhosts, sentinel) | Low | Medium | Explicit test matrix in the PR, not after |
| Team treats it as a strategic dependency / vendor lock-in narrative | Low | Medium | Frame in the ADR as a utility, not a platform bet |
queue.php connection arrays, DSN parsing may be a solution without a problem.Native PHP 7.1+ / Composer; nothing Laravel-specific is required or provided. It sits below the framework: config layer, service providers, and artisan commands consume it; the framework does not know it exists. Complements, rather than competes with, Laravel's queue system — Laravel handles the connection, enqueue/dsn handles the string. Overlap with parse_url() and Symfony's Url component is real; the differentiator is broker-specific grammar (vhosts, sentinel, scheme defaults), which generic URL parsers get wrong.
DsnParser service or config helper. No direct use Enqueue\Dsn\... outside that boundary. This is the single most important step for reversibility.queue:show-config artisan command.amqp, amqps, redis, redis+sentinel, generic tcp://. Weak or absent on SQS, Kafka, custom. This is the deciding compatibility axis — resolve in Phase 1.Phase 1 (spike, ~1 day) → Phase 2 (wrapper + tests, ~2 days) → Phase 3 (config + CLI adoption, ~2 days) → Phase 4 (user-input validation, if in scope). Total realistic effort: under two engineer-weeks, which is the strongest argument for or against — if the estimate balloons, the package is being asked to do too much. Decision gate after Phase 1: if the scheme matrix does not fit, stop and hand-roll; do not extend the package before the wrapper exists.
Near-zero steady state. Pure function, no runtime dependencies, no background processes, no config to drift. The maintenance cost is latent, not ongoing: it is the risk of an unpatched edge case surfacing years from now with no upstream to fix it. Mitigation is cheap — vendor or fork on adoption, or keep the wrapper thin enough that replacement is trivial. Budget effectively nothing in the run rate; budget a half-day of contingency in the risk register.
Weakest dimension. No active maintainer on the DSN component, no SLA, no security response path, no community forum of meaningful size (zero dependents is the tell). Internal support is therefore first-line and only-line: the owning team must be able to read and patch the parser. That is a reasonable ask at ~100 LOC. Documentation in the repo is minimal and partly inaccurate; plan to write a short internal note with verified examples as part of the integration PR.
Irrelevant at scale — parsing is O(1), allocation is negligible, execution is stateless and safe under concurrency. It will not appear on a performance profile or a capacity plan. The only scaling consideration is call frequency: parse once at config resolution or at connection setup, not per job dispatch. Enforce that in the wrapper so it cannot be reintroduced later.
| Scenario | User-visible impact | Mitigation |
|---|---|---|
| Malformed DSN | Exception at boot / connection failure | Catch in wrapper, fail fast with a clear message naming the offending config key |
| Unsupported scheme | Silent misparse or generic fallback | Allowlist schemes explicitly; reject unknowns rather than defaulting |
Percent-encoding mismatch (vhost %2f) |
Wrong queue namespace, silent message loss | Assert decoded values in tests against real broker expectations |
| Upstream abandoned mid-incident | No fix available | Fork already vendored; wrapper isolates the swap |
| Dependency treated as a platform layer | Over-engineering, unnecessary coupling | ADR states scope: string parsing only |
The highest-severity failure is not a crash — it is a silent misparse producing a worker connected to the wrong vhost or queue. Prefer loud failure over permissive parsing everywhere in the wrapper.
Low. One method, one return shape, a two-line example in the onboarding doc. Effective for a mid-level Laravel developer in under an hour, most of which is reading the wrapper rather than the package. The real onboarding cost is the DSN grammar itself (what a vhost is, why %2f matters, what sentinel addresses look like) — that knowledge belongs in the wrapper's docblock and is worth writing once. Add a three-case test matrix to the repo template: valid broker DSN, edge-case DSN (IPv6 / no credentials / encoded vhost), invalid DSN. That is the complete onboarding artifact.
TPM recommendation: adopt narrowly behind an application-owned wrapper, contingent on the Phase 1 spike confirming API and scheme coverage; otherwise hand-roll. Frame it to stakeholders as a utility consolidation, not a platform decision — and reserve the architectural conversation for the queue strategy, where it actually belongs.
How can I help you explore Laravel packages today?