gplanchat / durable-bridge-temporal
Temporal journal EventStore + worker (gRPC only, no Temporal PHP SDK) for gplanchat/durable
Package info
github.com/gplanchat/durable-bridge-temporal
pkg:composer/gplanchat/durable-bridge-temporal
Requires
- php: >=8.2
- google/common-protos: ^4.9
- google/protobuf: ^4.31
- gplanchat/durable: ^0.1
- grpc/grpc: ^1.57
- symfony/config: ^7.0
- symfony/console: ^7.0
- symfony/dependency-injection: ^7.0
- symfony/http-kernel: ^7.0
- symfony/messenger: ^7.0
Suggests
- ext-grpc: Required for Temporal gRPC client and worker poll
This package is auto-updated.
Last update: 2026-05-08 09:50:24 UTC
README
gRPC bridge (without the official Temporal PHP SDK) to persist the Durable journal in a minimal Temporal workflow.
PHP namespace: Gplanchat\Bridge\Temporal.
Deployment invariant: when Temporal is enabled for Durable, the journal (EventStore) and application queues share the same Temporal connection (temporal://…). Access mode (journal receive-only vs application envelope) is selected via options.purpose (journal | application) or inferred (presence of inner ⇒ application). Schemes temporal-journal:// and temporal-application:// are still accepted and normalized to temporal://.
Requirements
- PHP ext-grpc
- A reachable Temporal frontend (e.g.
host:7233)
Components
| Class | Role |
|---|---|
TemporalJournalEventStore |
Implements Gplanchat\Durable\Store\EventStoreInterface |
TemporalTransportFactory |
Single temporal:// factory: journal (TemporalJournalTransport, receive-only) or application (TemporalApplicationTransport + inner) from purpose / inner |
TemporalJournalTransport |
Symfony Messenger receive-only transport (same temporal://… DSN, no inner by default); consumed with messenger:consume <transport_name> |
TemporalApplicationTransport |
Wraps a real Messenger transport (temporal://…?inner=… or options.inner) for Durable application messages |
TemporalBridgeBundle |
Registers the temporal:// Messenger factory |
Transport DSN (single scheme)
temporal://127.0.0.1:7233?namespace=default&journal_task_queue=durable-journal&tls=0
Query parameters: namespace, task_queue or journal_task_queue, workflow_type, workflow_task_queue, activity_task_queue, identity, tls (bool).
Journal (receive-only)
Without inner and without options.purpose=application, the transport is TemporalJournalTransport.
Application queues (inner)
temporal://127.0.0.1:7233?namespace=default&inner=in-memory://&workflow_task_queue=durable-workflows&activity_task_queue=durable-activities&tls=0
Or temporal://… without inner in the URL and options: { purpose: application, inner: 'in-memory://' } in Messenger config.
inner(required for application mode): DSN of the real Symfony Messenger transport (Redis, Doctrine, in-memory, etc.).workflow_task_queue/activity_task_queue: used for gRPC evolution; while the envelope delegates toinner, application traffic uses that inner transport.
Symfony
- In the monorepo the code lives under
src/Bridge/Temporal; in a split repo:composer require gplanchat/durable-bridge-temporal. - Register
Gplanchat\Bridge\Temporal\TemporalBridgeBundlein the kernel. framework.messenger.transports.<name>: 'temporal://…'(withoutinner, journal DSN — e.g.journal_task_queue=durable-journal).messenger:consume <name>(standard Symfony worker; poll and journal task handling are insideTemporalJournalTransport::get()).- Wire
EventStoreInterfacetoTemporalJournalEventStorewhere appropriate (explicit DI).
FrankenPHP worker
Same idea as messenger:consume: run the Messenger worker under FrankenPHP worker mode (or systemd) with messenger:consume <journal_transport> pointing at temporal://… without inner.
License
MIT — see LICENSE in this directory and WA004.
Further reading
- DUR019 — Temporal gRPC bridge and journal:
documentation/adr/DUR019-temporal-grpc-bridge-and-journal.md