feat(sync): add typed broadcast primitive

req: sync/004
This commit is contained in:
slhx agent
2026-07-13 22:54:12 +02:00
parent 98b00920b9
commit 87296632bc
5 changed files with 162 additions and 3 deletions
+20
View File
@@ -15,6 +15,7 @@ use hemx_axum::{
use hemx_kanban_example::ui::board::{self as board};
use hemx_kanban_example::ui::board_card as card_board;
use hemx_kanban_example::ui::{self, board as board_ui};
use hemx_sync::{Channel, SyncEffect};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::convert::Infallible;
@@ -498,6 +499,7 @@ async fn main() {
let ordinary_routes = Router::new()
.route("/", get(home).post(interact))
.route("/events", get(events))
.route("/sync/broadcast", get(sync_broadcast))
.route("/sync-demo", get(sync_demo))
.route("/sync.js", get(sync_js))
.route("/sync/context", get(sync_context))
@@ -579,6 +581,24 @@ async fn interact(
}
// req: push/001 req: push/003 req: examples/001
async fn sync_broadcast(Query(params): Query<BTreeMap<String, String>>) -> Response {
let Some(channel) = params
.get("channel")
.and_then(|channel| Channel::new(channel).ok())
else {
return (StatusCode::BAD_REQUEST, "missing or invalid sync channel").into_response();
};
if channel.as_str() != "board" {
return StatusCode::NOT_FOUND.into_response();
}
let batch = board::presence
.put(&Presence { count: 7 })
.into_batch(ui::BUILD_FINGERPRINT);
let broadcast = SyncEffect::broadcast(channel, batch);
let (_channel, effect_batch) = broadcast.into_parts();
sse(stream::iter([Ok::<_, Infallible>(effect_batch)]).boxed()).into_response()
}
async fn events(Query(params): Query<BTreeMap<String, String>>) -> impl IntoResponse {
if params.contains_key("once") {
let effect = board::presence.put(&Presence { count: 1 });