CounterSseEndpoint.vala 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using Astralis;
  2. using Invercargill;
  3. using Invercargill.DataStructures;
  4. using Inversion;
  5. using Spry;
  6. /**
  7. * CounterSseEndpoint - Singleton SSE endpoint for counter updates
  8. *
  9. * Broadcasts counter value updates to all connected clients
  10. * when counter actions are triggered (Increment, Decrement, Reset)
  11. *
  12. * Uses the Astralis SseEndpoint pattern - NOT continuations.
  13. */
  14. public class CounterSseEndpoint : SseEndpoint {
  15. private AuroraState aurora_state;
  16. public CounterSseEndpoint(AuroraState aurora_state) {
  17. this.aurora_state = aurora_state;
  18. }
  19. /// Retry interval: clients should wait 2 seconds before reconnecting
  20. public override uint retry_interval { get { return 2000; } }
  21. /// Called when a new client connects - send current counter value
  22. public override async void new_connection(HttpContext http_context, RouteContext route_context, SseStream stream) {
  23. print(@"Counter SSE client connected (total: $(get_open_streams().length))\n");
  24. // Send current counter value to new client
  25. try {
  26. yield send_counter_update(stream);
  27. } catch (Error e) {
  28. print(@"Failed to send counter update: $(e.message)\n");
  29. }
  30. stream.disconnected.connect(() => {
  31. print(@"Counter SSE client disconnected\n");
  32. });
  33. }
  34. /// Increment counter and broadcast update
  35. public async void increment() {
  36. aurora_state.counter++;
  37. yield broadcast_counter_update();
  38. }
  39. /// Decrement counter and broadcast update
  40. public async void decrement() {
  41. aurora_state.counter--;
  42. yield broadcast_counter_update();
  43. }
  44. /// Reset counter and broadcast update
  45. public async void reset() {
  46. aurora_state.counter = 0;
  47. yield broadcast_counter_update();
  48. }
  49. /// Broadcast counter update to all connected clients
  50. private async void broadcast_counter_update() {
  51. try {
  52. string counter_html = build_counter_html();
  53. var counter_event = new SseEvent.with_type("counter-value", counter_html);
  54. yield broadcast_event(counter_event);
  55. } catch (Error e) {
  56. printerr(@"Failed to broadcast counter update: $(e.message)\n");
  57. }
  58. }
  59. /// Send counter update to a single stream (for new connections)
  60. private async void send_counter_update(SseStream stream) throws Error {
  61. string counter_html = build_counter_html();
  62. yield stream.send_event(new SseEvent.with_type("counter-value", counter_html));
  63. }
  64. /// Build the counter value HTML
  65. private string build_counter_html() {
  66. return aurora_state.counter.to_string();
  67. }
  68. }