Expand description
Pub/sub event pipeline facade.
Typed topics, durable subscriptions with checkpoints, and the same API in single-process and
multi-node deployments. Enable the runtime feature for the full stack (Photon, backends,
executor). Photon uses pluggable storage adapters
(mem, sqlite, nats, fluvio, kafka) behind StoragePort and Quark inventory for
topic/handler discovery. Payloads are encrypted before append; storage stays opaque. Canonical
business data remains in your datastore — the transport log is for event delivery, not system
of record.
§Features
- Typed topics and handlers —
topic/subscriberegister via Quark inventory - Same API everywhere —
publish_on/start_executorwhether you run one process or many - Pluggable storage —
mem,sqlite, or broker adapters (nats,kafka,fluvio) - Durable subscriptions — checkpointed replay after restart on durable adapters
- Host-owned crypto —
PHOTON_TRANSPORT_KEYencrypts envelopes before they hit storage
Typed pub/sub over a persistent event log — pick embedded or brokered topology.
§Getting started
You always publish and subscribe the same way (OrderCreated { … }.publish_on(&photon),
#[subscribe], Photon::start_executor). What changes is whether events stay in one
process or cross a broker to another binary.
§Choose a topology
- Mode 1 — Embedded — one process owns publish and
handlers. Start here (
memorsqlite). - Mode 2 — Brokered — publisher binary(ies) and worker binary(ies) share a broker. Photon does not ship a separate server binary; each process embeds Photon against the same adapter.
| Topology | Adapter | Features | When to use |
|---|---|---|---|
| Embedded | InProcStoragePort (default) | runtime,mem | Local / tests |
| Embedded durable | SqliteStoragePort | runtime,sqlite | Single host, restart-safe |
| Brokered | NATS / Kafka / Fluvio | runtime + nats/kafka/fluvio | Multi-process / fleet |
Adapter builders and env vars: config.
After you pick a mode, continue with declare topics.
§Mode 1 — Embedded (one binary)
This process publishes and runs handlers. There is no second binary and no external broker.
Your app ──publish / #[subscribe]──► Photon ──StoragePort──► mem | sqlitePrerequisites: Cargo features runtime + mem (or sqlite), and PHOTON_TRANSPORT_KEY
(base64 of 32 bytes). See config.
In-memory (default — PhotonBuilder installs InProcStoragePort when you omit
storage_port):
use std::sync::Arc;
use photon::{JsonIdentityFactory, Photon};
let photon = Photon::builder().auto_registry().build()?;
photon.start_executor(Arc::new(JsonIdentityFactory))?;
// Prefer EventType { … }.publish_on(&photon).awaitSQLite — durable single-process (write-through + in-memory live fanout):
use std::sync::Arc;
use photon::{JsonIdentityFactory, Photon, SqliteStoragePort};
let port = Arc::new(SqliteStoragePort::open("/var/lib/photon/events.db").await?);
let photon = Photon::builder()
.storage_port(port)
.auto_registry()
.build()?;
photon.start_executor(Arc::new(JsonIdentityFactory))?;Runnable: cargo run -p uf-photon --example embedded_mem --features runtime,mem.
Then jump to declare topics.
§Mode 2 — Brokered (publisher + worker binaries)
Use this when multiple processes (or hosts) must share the same topic log. mem and sqlite
cannot fan out across processes — wire a broker adapter instead.
Publisher binary ──publish_on──► Photon ──StoragePort──► broker (NATS / Kafka / Fluvio)
Worker binary ──start_executor / #[subscribe]──► Photon ──same broker──►§What you create
| Piece | Purpose |
|---|---|
| Shared topics | Same #[topic] types (shared crate or both binaries compile them) |
| Publisher binary | [[bin]] that publishes; typically no start_executor |
| Worker binary | [[bin]] with #[subscribe] handlers; must call start_executor |
| Broker | NATS / Kafka / Fluvio cluster your ops team runs |
| Shared env | Same PHOTON_TRANSPORT_KEY + broker URL (e.g. PHOTON_NATS_URL) on every process |
§Shared setup (both binaries)
- Enable
runtimeplus one broker feature (natsis the usual first choice). - Build the same storage port against the same cluster — pick a builder below.
- Call
.auto_registry()when using macros. - Keep the
Photonhandle forpublish_on/subscribe_on.
| Adapter | Feature | Builder (publisher + worker examples) |
|---|---|---|
| NATS | nats | NatsStoragePortBuilder |
| Kafka | kafka | KafkaStoragePortBuilder |
| Fluvio | fluvio | FluvioStoragePortBuilder |
Env index: config. NATS sketches follow; swap the builder for Kafka/Fluvio.
§Publisher binary
Wire the broker port, declare topics, publish. Skip Photon::start_executor unless this
process also handles events.
use std::sync::Arc;
use photon::{Photon, NatsStoragePort, ReplayCursor};
let port = Arc::new(
NatsStoragePort::builder()
.from_env_defaults()
.replay_cursor(ReplayCursor::StreamSeq)
.sync_ack(true)
.build()
.await?,
);
let photon = Photon::builder()
.storage_port(port)
.auto_registry()
.build()?;
// OrderCreated { … }.publish_on(&photon).await?;§Worker binary
Same storage port wiring as the publisher, plus #[subscribe] handlers and
Photon::start_executor:
use std::sync::Arc;
use photon::{JsonIdentityFactory, Photon, NatsStoragePort, ReplayCursor};
let port = Arc::new(
NatsStoragePort::builder()
.from_env_defaults()
.replay_cursor(ReplayCursor::StreamSeq)
.sync_ack(true)
.build()
.await?,
);
let photon = Photon::builder()
.storage_port(port)
.auto_registry()
.build()?;
photon.start_executor(Arc::new(JsonIdentityFactory))?;§Run both
- Start the broker.
- Start worker(s) first so subscriptions are ready.
- Start one or more publishers.
Then continue with declare topics.
§3. Declare topics and handlers
topic— typed event struct + inventory registration; generatespublish_on/subscribe_onsubscribe— inventory-registered handler; requiresPhoton::start_executoron workersprelude— common imports (Event,SubscribeOpts,Photon, macros)
Attribute tables: config. Runnable: keyed_topic, consumer_group, subscribe_v2.
§4. Publish and subscribe
After topic, the macro generates typed methods on your event struct. Prefer those over
raw Photon::publish / Photon::subscribe.
Publish — publish_on with an explicit Photon handle:
OrderCreated {
order_id: "ord-1".into(),
amount_cents: 9900,
}
.publish_on(&photon)
.await?;Typed stream — subscribe_on (no #[subscribe] / executor required):
use futures::StreamExt;
use photon::SubscribeOpts;
let opts = SubscribeOpts::default_ephemeral();
let mut stream = OrderCreated::subscribe_on(&photon, opts).await?;
if let Some(Ok(envelope)) = stream.next().await {
let _payload = envelope.payload; // OrderCreated
}Inventory handlers — #[subscribe] + Photon::start_executor (Mode 1 / Mode 2 workers).
Optional sugar after configure: .publish() / .subscribe() without a handle.
Raw topic-name API (advanced): Photon::subscribe.
Runnable: embedded_mem (publish_on + #[subscribe]), keyed_topic (subscribe_on),
manual_subscribe (raw Photon::subscribe).
§5. Run the executor and reclaim
Photon::start_executor— dispatch inventory-registered#[subscribe]handlers (Mode 1 and Mode 2 workers)Photon::reclaim_transport— retention sweep past the safe watermark- Optional ops telemetry:
OpsLogviaPhotonBuilder::ops_log(example:telemetry_ops_log)
§Notes
- Transport key: boot fails closed without a valid
PHOTON_TRANSPORT_KEY(seeconfig). - Durable multi-process: use a broker adapter;
memdoes not cross process boundaries. - Lab topologies: testkit / bench
PHOTON_TOPOLOGYvalues are harness labels — not the Mode 1 / Mode 2 product choices above. - Custom adapters: implement
StoragePortand pass it toPhotonBuilder::storage_port. Advanced delivery traits live behind that port.
§Architecture
Application → Photon (macros + Photon runtime) → storage port → delivery backend Typed API (#[topic], publish_on / publish, #[subscribe])
│
v
Photon runtime
│
v
StoragePort ──► mem (InProcStoragePort)
──► sqlite (SqliteStoragePort)
──► nats / fluvio / kafka (broker crates)
──► custom implementationFull option reference: config. Macro expansion: repository docs/macro-expansion.md.
Re-exports§
pub use quark::inventory;
Modules§
- backend
- Backend implementations and assembly context for Photon.
- backend_
instrumentation - Backend instrumentation (L0 publish telemetry + ops log helpers).
- checkpoint
- Checkpoint coalescing for durable subscriptions.
- config
- Photon configuration reference
- consumer_
group - Consumer group coordination: shard assignment and leases.
- delivery
- Handler delivery: backpressure and dead-letter queue.
- delivery_
mode - Topic delivery mode and virtual shard configuration.
- descriptor
- Topic descriptor for auto-registration.
- error
- Error types for Photon.
- event
- Event envelope encryption.
- handler_
ctx - Delivery metadata injectable into
#[photon::subscribe]handlers (v2). - handler_
descriptor - Handler descriptor for
#[photon::subscribe]inventory registration. - handler_
registry - Registry of
#[photon::subscribe]handlers discovered via inventory. - host
- Host-facing runtime wiring (executor bootstrap).
- instrumentation
- Photon platform observability via injected
photon_telemetry::OpsLog. - models
- In-memory models for Photon entities.
- prelude
- Common imports for application code using typed topics and the runtime handle.
- registry
- Topic registry for discovering and looking up registered topics.
- runtime_
parts - Host-facing runtime wiring helpers (Integrating the host).
- shard_
router - Virtual shard routing for consumer-group topics.
- storage
- Storage adapter port — one implementation per
--storagetier (mem,sqlite,nats,fluvio,kafka).
Macros§
- actor_
downcast_ methods - Re-export identity port traits and JSON stubs from
photon_core. Expands the standardActorAnydowncast method bodies.
Structs§
- Admin
Backend Summary - Storage adapter capabilities surfaced for admin UIs.
- Admin
Checkpoint Summary - Last committed sequence for a subscription/topic partition.
- Admin
Handler Summary - Inventory entry for a
#[photon::subscribe]handler. - Admin
Snapshot - Point-in-time ops introspection snapshot (read-only).
- Admin
Topic Summary - Topic catalog entry from the compile-time
TopicRegistry. - Backend
Capabilities - Capabilities advertised by a storage port (surfaced via
crate::backend::GenericPhotonBackend). - Backend
Context - Shared builder context for storage adapter install fns.
- Console
OpsLog - stderr/stdout structured lines (default dev adapter).
- Envelope
- Event envelope with decoded payload.
- Event
- Published event with payload and metadata.
- Fluvio
Config - Resolved Fluvio adapter settings (no env lookups at append time).
- Fluvio
Storage Port - Fluvio-backed storage port.
- Fluvio
Storage Port Builder - Builder for
super::port::FluvioStoragePort. - Generic
Photon Backend - Unified backend — all storage adapters install this wrapping their port.
- Group
Opts - Options specific to consumer-group subscriptions.
- Handler
Ctx - Delivery metadata for a single handler invocation.
- Handler
Descriptor - Descriptor for a
#[photon::subscribe]handler (inventory + executor dispatch). - Handler
Registry - Registry of inventory-submitted subscription handlers.
- InProc
Storage Port - In-process storage for the
memadapter tier. - Json
Actor - Re-export identity port traits and JSON stubs from
photon_core. Actor label derived from publish-timeactor_json(System.operationwhen present). - Json
Identity Factory - Re-export identity port traits and JSON stubs from
photon_core. ReconstructsJsonActorfrom JSON captured at publish time. - Kafka
Config - Resolved Kafka adapter settings (no env lookups at append time).
- Kafka
Storage Port - Kafka-backed storage port.
- Kafka
Storage Port Builder - Builder for
super::port::KafkaStoragePort. - Nats
Config - Resolved NATS adapter settings (no env lookups at append time).
- Nats
Storage Port - NATS JetStream-backed storage port.
- Nats
Storage Port Builder - Builder for
super::port::NatsStoragePort. - NoOps
Log - Zero-cost no-op (benchmark
telemetry=offand minimal CI). - Photon
- Main Photon runtime handle.
- Photon
Builder - Builder for constructing
Photonruntimes. - Photon
Runtime State - Shared storage port, executor services, and handler dispatch controller.
- Shard
Config - Virtual shard settings for
DeliveryMode::ConsumerGrouptopics. - Sqlite
Storage Port - Embedded
SQLitestorage for thesqliteadapter tier. - Subscribe
Opts - Options for subscribing to a topic.
- Subscription
- Subscription handler registration.
- Subscription
Handle - Placeholder for future subscription lifecycle control (cancel, pause).
- Topic
Descriptor - Descriptor for a registered topic (from
#[photon::topic]macro). - Topic
Metadata - Topic metadata stored in the registry.
- Topic
Registry - Registry of all topics discovered via
#[photon::topic]. - Transport
Crypto - Symmetric payload encryption (XChaCha20-Poly1305).
Enums§
- Delivery
Mode - How publishes on a topic are routed to subscribers.
- Fluvio
Replay Cursor - How durable replay and checkpoints map to Fluvio offsets.
- Identity
Error - Re-export identity port traits and JSON stubs from
photon_core. Errors fromcrate::IdentityFactory::reconstruct. - Kafka
Replay Cursor - How durable replay and checkpoints map to Kafka offsets.
- Photon
Error - Errors that can occur in Photon operations.
- Replay
Cursor - How durable replay and checkpoints map to
JetStream. - Subscription
Mode - Subscription mode.
Constants§
- FLUVIO_
ENDPOINT_ ENV - Environment variable for Fluvio SC endpoint.
- FLUVIO_
MAX_ INFLIGHT_ ENV - Environment variable for max in-flight publishes per port.
- FLUVIO_
PREFIX_ ENV - Environment variable for topic name prefix.
- FLUVIO_
REPLAY_ CURSOR_ ENV - Environment variable for replay cursor mode.
- FLUVIO_
REPLICAS_ ENV - Environment variable for topic replication factor.
- FLUVIO_
RETENTION_ ENV - Environment variable for Fluvio topic retention.
- FLUVIO_
SYNC_ ACK_ ENV - Environment variable for synchronous publish ack (
1/0). - FLUVIO_
TOPIC_ SHARDS_ ENV - Environment variable for topic shard count (bench/scripts fallback).
- KAFKA_
BROKERS_ ENV - Environment variable for Kafka bootstrap brokers.
- KAFKA_
MAX_ INFLIGHT_ ENV - Environment variable for max in-flight publishes per port.
- KAFKA_
PREFIX_ ENV - Environment variable for topic name prefix.
- KAFKA_
REPLAY_ CURSOR_ ENV - Environment variable for replay cursor mode.
- KAFKA_
REPLICAS_ ENV - Environment variable for topic replication factor.
- KAFKA_
RETENTION_ ENV - Environment variable for Kafka topic retention.
- KAFKA_
SYNC_ ACK_ ENV - Environment variable for synchronous publish ack (
1/0). - KAFKA_
TOPIC_ SHARDS_ ENV - Environment variable for topic shard count (bench/scripts fallback).
- MAX_
INFLIGHT_ ENV - Environment variable for max in-flight publishes per port.
- NATS_
RETENTION_ ENV - Environment variable for
JetStreamstream retention. - NATS_
STREAM_ ENV - Environment variable for
JetStreamstream name. - NATS_
STREAM_ SHARDS_ ENV - Environment variable for stream shard count (bench/scripts fallback).
- NATS_
URL_ ENV - Environment variable for NATS server URL.
- REPLAY_
CURSOR_ ENV - Environment variable for replay cursor mode.
- SQLITE_
PATH_ ENV - Environment variable for the
SQLitedatabase file path. - SYNC_
ACK_ ENV - Environment variable for synchronous publish ack (
1/0).
Traits§
- Actor
- Re-export identity port traits and JSON stubs from
photon_core. Opaque actor handle for handler execution. - Identity
Factory - Re-export identity port traits and JSON stubs from
photon_core. Reconstruct handler identity from captured actor JSON (handler boundary only). - OpsLog
- Structured ops metrics/events for publish, drain, DLQ, checkpoints.
- Photon
Backend - Backend for publish/subscribe delivery and checkpoint persistence.
- Storage
Port - Storage adapter contract — append, subscribe, checkpoints, and optional retention.
Functions§
- collect_
admin_ snapshot - Build a full admin snapshot for the given runtime (async checkpoint reads).
- configure
- Configure the default Photon instance used by macro-generated convenience helpers
(
Type::publish()/Type::subscribe()). - consumer_
group_ for - Stable group id alias (NATS deliver-subject analogue).
- default
- Clone of the process-wide Photon set by
configure, if any. - durable_
consumer_ name - Build a Kafka-safe durable consumer group id for a keyed subscription.
- fluvio_
consumer_ group_ for - Stable group id alias (NATS deliver-subject analogue).
- fluvio_
durable_ consumer_ name - Build a Fluvio-safe durable consumer id for a keyed subscription.
- fluvio_
endpoint_ from_ env - Read Fluvio endpoint from the environment.
- install_
ops_ log - Install the process-wide ops log (typically at server boot before Photon runtime).
- kafka_
brokers_ from_ env - Read Kafka brokers from the environment.
- ops_log
- Resolved ops log —
NoOpsLoguntilinstall_ops_log. - resolve_
photon_ remote_ base_ url - Origin + path prefix before
/api/photon(no trailing slash). - sqlite_
path_ from_ env - Resolve database path from
PATH_ENV, or a unique file under the system temp dir.
Type Aliases§
- Embedded
Backend - Back-compat alias for the default in-process
memtierGenericPhotonBackend. - Result
- Result type alias for Photon operations.