adding sse for the landing page to update turnament stats for everyone
This commit is contained in:
parent
c61bcedb3a
commit
af4dbdea91
5 changed files with 63 additions and 7 deletions
|
|
@ -64,7 +64,7 @@ async fn main() -> Result<(), rocket::Error> {
|
|||
|
||||
let rocket = rocket::build()
|
||||
.manage(state)
|
||||
.mount("/", routes![healthz, login, logout, events])
|
||||
.mount("/", routes![healthz, login, logout, events, public_events])
|
||||
.mount("/persons", routes::persons::routes())
|
||||
.mount("/tournament", routes::tournaments::routes());
|
||||
|
||||
|
|
@ -157,3 +157,25 @@ fn events(_user: AuthUser, state: &State<AppState>) -> EventStream![Event + '_]
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/events/public")]
|
||||
fn public_events(state: &State<AppState>) -> EventStream![Event + '_] {
|
||||
let mut receiver = state.event_sender.subscribe();
|
||||
|
||||
EventStream! {
|
||||
loop {
|
||||
match receiver.recv().await {
|
||||
Ok(event) => {
|
||||
match &event {
|
||||
AppEvent::TournamentUpserted { .. } | AppEvent::TournamentDeleted { .. } => {
|
||||
yield Event::json(&event);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
Err(RecvError::Closed) => break,
|
||||
Err(RecvError::Lagged(_)) => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ export type AppEvent =
|
|||
| { type: 'tournament_upserted'; tournament: TournamentInfo }
|
||||
| { type: 'tournament_deleted'; tournament_id: number };
|
||||
|
||||
export function listenToEvents(onEvent: (event: AppEvent) => void) {
|
||||
export function listenToEvents(onEvent: (event: AppEvent) => void, endpoint = '/api/events') {
|
||||
let stopped = false;
|
||||
let source: EventSource | null = null;
|
||||
|
||||
function connect() {
|
||||
if (stopped) return;
|
||||
source = new EventSource('/api/events');
|
||||
source = new EventSource(endpoint);
|
||||
source.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data) as AppEvent;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,16 @@ export type TournamentEvent =
|
|||
| { type: 'tournament_upserted'; tournament: TournamentInfo }
|
||||
| { type: 'tournament_deleted'; tournament_id: number };
|
||||
|
||||
type TournamentEventOptions = {
|
||||
endpoint?: string;
|
||||
};
|
||||
|
||||
export function listenToTournamentEvents(
|
||||
onUpsert: (tournament: TournamentInfo) => void,
|
||||
onDelete: (tournamentId: number) => void
|
||||
onDelete: (tournamentId: number) => void,
|
||||
options: TournamentEventOptions = {}
|
||||
) {
|
||||
const endpoint = options.endpoint ?? '/api/events';
|
||||
return listenToEvents((event) => {
|
||||
if (event.type === 'tournament_upserted') {
|
||||
onUpsert(event.tournament);
|
||||
|
|
@ -17,5 +23,5 @@ export function listenToTournamentEvents(
|
|||
if (event.type === 'tournament_deleted') {
|
||||
onDelete(event.tournament_id);
|
||||
}
|
||||
});
|
||||
}, endpoint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,9 @@
|
|||
}
|
||||
|
||||
onMount(() => {
|
||||
const stop = listenToTournamentEvents(upsertTournament, removeTournament);
|
||||
const stop = listenToTournamentEvents(upsertTournament, removeTournament, {
|
||||
endpoint: '/api/public-events'
|
||||
});
|
||||
return () => {
|
||||
stop();
|
||||
};
|
||||
|
|
|
|||
26
web/src/routes/api/public-events/+server.ts
Normal file
26
web/src/routes/api/public-events/+server.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import type { RequestHandler } from './$types';
|
||||
import { proxyRequest } from '$lib/server/backend';
|
||||
|
||||
export const GET: RequestHandler = async (event) => {
|
||||
const { response, setCookies } = await proxyRequest(event, '/events/public', {
|
||||
method: 'GET'
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (contentType) {
|
||||
headers.set('content-type', contentType);
|
||||
} else {
|
||||
headers.set('content-type', 'text/event-stream');
|
||||
}
|
||||
for (const cookie of setCookies) {
|
||||
headers.append('set-cookie', cookie);
|
||||
}
|
||||
headers.set('cache-control', 'no-cache');
|
||||
|
||||
return new Response(response.body, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers
|
||||
});
|
||||
};
|
||||
Loading…
Reference in a new issue