Skip to main content

SSE and realtime

Nova Print uses Server-Sent Events (text/event-stream) for live order comments, consolidated order feeds, customer-link chat/status, and admin notifications. Implementations: pos/sse.py (backend-main/pos/sse.py), customerlink/sse.py (backend-main/customerlink/sse.py), pos/notification_views.py (backend-main/pos/notification_views.py).

All streams are in-memory (defaultdict lists + locks). Code comments note Redis pub/sub would be needed for multi-process production fan-out.

Auth for EventSource​

Browsers' EventSource cannot set Authorization or X-POS-Access-Key. Pattern:

ClientQuery / header
POS?access_key= or header X-POS-Access-Key
Admin consolidated / notifications?token= (JWT access) — required on admin order + notification streams
Legacy per-order commentsaccess_key or token query or Authorization: Bearer
Public checkoutNo auth — pos_slug + link_code in path

Common optional cursor: ?last_event_time=<unix float>. New subscribers without a cursor get a 120s lookback (SSE_CONNECT_LOOKBACK_SECONDS) so reconnects do not miss events.

Heartbeats: roughly every 15s (event: heartbeat). Poll sleep is ~2s (order consolidated) or ~0.5s (customer-link global).

Endpoints​

POS / admin orders (pos/urls.py (backend-main/pos/urls.py))​

PathViewAuthEvents
/api/pos-orders/stream/POSOrdersSSEViewPOS access keySession pos_{id}: connected, new_comment, order_update, notification, heartbeat
/api/admin/orders/stream/AdminOrdersSSEView?token= JWTSession admin: same order event types
/api/orders/<order_id>/comments/stream/OrderCommentsSSEViewPOS key or JWTPer-order: connected, new_comment, order_update, heartbeat
/api/admin/notifications/stream/AdminNotificationsSSEView?token= JWTnotification, heartbeat

Publish helpers in pos/sse.py: notify_new_comment, notify_order_update, notify_pos_notification. Admin notifications: notify_admin in notification_views.py.

Consolidated streams replace opening one SSE connection per order.

PathViewAuthEvents
/api/customer-links/stream/GlobalCustomerLinkCommentsSSEViewPOS access keyAll links for POS; payload includes link_id
/api/customer-links/<link_id>/comments/stream/CustomerLinkCommentsSSEViewPOS access keySingle link
/api/checkout/<pos_slug>/<link_code>/comments/stream/CustomerLinkCommentsPublicSSEViewPublicSame link events; 410 if archived

Event types from customerlink/sse.py (backend-main/customerlink/sse.py):

event: nameWhen
connectedStream open
new_commentChat message (notify_new_link_comment)
status_changeLink status change
approval_changeDesign approval units snapshot
link_submittedOn link stream after submit
customer_link_submittedAlso pushed toward POS global awareness from notify_link_submission
heartbeatKeep-alive

Call sites include customerlink serializers/views (submit, step3, comments) and POS order/workflow code that fans out approval/status to checkout.

Client tips​

  • Prefer consolidated /api/pos-orders/stream/ and /api/customer-links/stream/ over per-resource streams.
  • Pass last_event_time from the last received event timestamp on reconnect.
  • Responses set Cache-Control: no-cache, X-Accel-Buffering: no, and permissive CORS headers for SSE.
  • Persist notifications via REST (/api/pos-notifications/, /api/admin/notifications/); SSE is the live push layer on top.