AlejoTaller’s realtime layer is deliberately split across two technologies. Appwrite Realtime handles operator-side collection subscriptions, giving the operator app live visibility into incoming orders. Pusher Channels handles customer-facing verification events, pushingDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/danielitoCode/AlejoTaller/llms.txt
Use this file to discover all available pages before exploring further.
sale:confirmed and sale:rejected notifications to Android and web clients the moment an operator acts on a sale. The two layers serve different roles, connect to different audiences, and are intentionally isolated from each other.
Two Realtime Layers
Layer 1 — Pusher Channels: customer verification events
Pusher is used for the most latency-sensitive step in the sale lifecycle: telling a waiting customer that their order has been confirmed or rejected. Every customer subscribes to a personal channel named after their user ID:| Event name | Meaning |
|---|---|
sale:confirmed | Operator verified the sale; order is accepted |
sale:rejected | Operator rejected the sale; order will not be processed |
PusherSaleRealtimePublisher:
Layer 2 — Appwrite Realtime: operator collection sync
The operator app (AlejoTallerScan) subscribes to changes on the Appwrite sales collection through theRealtimeSyncGateway interface. When a new sale arrives in Appwrite, the operator app is notified in real time without polling. The gateway also carries a promotion channel, allowing the customer apps to receive promotional notifications through the same subscription mechanism.
Why Pusher Instead of Direct Appwrite Realtime for Customers
Three concrete reasons justify routing customer verification events through Pusher rather than letting clients subscribe to Appwrite Realtime directly:-
Secret isolation. Pusher application secrets (app ID, key, secret) never leave the server. Embedding them in an APK or JavaScript bundle would expose them to extraction. The
alejo_publishermicroservice is the only process that holds Pusher signing credentials. - Timestamp signing reliability. Pusher’s HTTP API authentication uses server-side timestamps. A mobile device with a drifted or incorrect clock would produce invalid signatures when calling the Pusher REST API directly. Routing through a server-side function eliminates this failure mode entirely.
-
Auditability. Every publish event passes through
alejo_publisher, creating a single chokepoint that can be logged, rate-limited, and hardened independently of the clients.
The README explicitly documents this decision: “la operadora ya no firma directamente contra Pusher — la function
alejo_publisher se encarga de publicar, el flujo no continua si Appwrite no confirma el cambio esperado, menos fragilidad por reloj del dispositivo, secretos de Pusher fuera del APK.”Channel and Event Reference
PusherSaleRealtimePublisher:
RealTimeManagerImpl builds the channel name by appending the authenticated user ID to the configured channel prefix:
Domain Use Cases for Realtime (shared-sale)
The realtime behaviour on Android and the shared module is encapsulated in three dedicated use cases.SubscribeRealtimeSyncCaseUse
Sets up the Pusher subscription for a given user. It delegates toRealtimeSyncGateway, which is implemented by RealTimeManagerImpl (Android) using PusherManager:
InterpretSaleRealtimeEventCaseUse
Converts a rawSaleRealtimeEvent into a list of SaleRealtimeCommand objects that describe what the UI and notification layer should do:
SaleRealtimeCommand is a sealed interface with two implementations — InAppMessage and PushNotification — so callers can handle each independently.
UpdateSaleVerificationFromRealtimeCaseUse
Applies the realtime event result to the local Room (Android) database, keeping local state consistent with what the operator confirmed:if (currentSale.verified == nextState) return@runCatching prevents duplicate writes when the same event is received more than once — a meaningful safety net given that Pusher at-least-once delivery can result in duplicate events.
PusherSaleRealtimePublisher
The publisher microservice (alejo_publisher) instantiates a server-side Pusher SDK client and routes all publish calls through PusherSaleRealtimePublisher:
Immutable UI State Pattern
ViewModels on Android exposeStateFlow<T> — the UI layer collects the flow and re-renders automatically. No manual “refresh UI” calls are needed. The flow of a realtime event from Pusher to the screen looks like:
PusherManager.subscribe()receives the raw JSON payloadSaleEventProcessorparses the envelope into aSaleRealtimeEvent- The ViewModel calls
InterpretSaleRealtimeEventCaseUseandUpdateSaleVerificationFromRealtimeCaseUse SaleRepository.save()updates RoomSaleDao.getAllFlow()(a RoomFlow) emits the updated list- The ViewModel’s
StateFlow— derived from that Room flow — emits the new state - Jetpack Compose recomposes the affected screen
updateVerified writes a new SaleDTO to Dexie, a Svelte store subscribed to that Dexie query emits the updated array and the component re-renders.
The Publisher Microservice Role
alejo_publisher is an Express HTTP service deployed on Render. It has exactly one business endpoint:
Full Realtime Chain
The operator app only calls
alejo_publisher after Appwrite confirms the buy_state change. If the Appwrite write fails, the publisher is never called and no Pusher event fires. This prevents clients from receiving a confirmation event for a sale that was not actually persisted.