Where it lands
Photon topics stream progress into the browser in the counter demo and anywhere Orbital binds subscriptions—live UI without treating the transport log as the system of record.Declare #[photon::topic] payloads and #[photon::subscribe] workers, boot Photon::builder().auto_registry(), and publish with publish_on. Durable subscriptions checkpoint last-delivered sequence per partition; keyed topics partition by field for filtered consume. Use mem for local/dev, sqlite for durable single-process, or broker adapters for fleet scale. Primary guide: docs.rs/uf-photon getting started (embedded vs brokered).
In the workspace
Photon topics stream progress into the browser in the counter demo and anywhere Orbital binds subscriptions—live UI without treating the transport log as the system of record.Code sample
From the upstream getting-started docs — see also all code recipes on Resources.
Photon topicPhoton
Typed topic + durable subscribe
use std::sync::Arc;
use photon::{subscribe, topic, JsonIdentityFactory, Photon};
use photon_core::Actor;
#[topic(name = "orders.created", keyed_by = "order_id")]
pub struct OrderCreated {
pub order_id: String,
pub amount_cents: u64,
}
#[subscribe(topic = "orders.created", durable = "billing")]
async fn on_order_created(actor: Box<dyn Actor>, event: OrderCreated) -> photon::Result<()> {
tracing::info!(actor = actor.label(), order = %event.order_id, cents = event.amount_cents);
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let photon = Photon::builder().auto_registry().build()?;
photon.start_executor(Arc::new(JsonIdentityFactory))?;
OrderCreated {
order_id: "ord-1".into(),
amount_cents: 9900,
}
.publish_on(&photon)
.await?;
Ok(())
}