Pesan klien ke server
Pesan klien ke server
Mayoritas lalu lintas WebSocket OmniStream mengalir dari server ke klien (event broadcast). Namun klien juga dapat mengirim pesan ke server untuk dua keperluan: mengindikasikan bahwa user sedang mengetik dan menjaga koneksi tetap hidup lewat ping.
Halaman ini mendokumentasikan dua tipe pesan klien yang dikenali oleh ws-server. Pesan di luar tipe ini diabaikan (dengan warning log), sehingga Anda tidak perlu khawatir menambah noise jika sengaja mengirim payload eksperimental.
Kode parser ada di crates/ws-server/src/handler.rs::handle_socket dengan tipe ClientWsMessage.
Format umum
Semua pesan klien adalah JSON dengan field diskriminator type:
Code
Server memakai tagged enum Serde untuk parsing:
Code
typing
Memberi tahu sistem bahwa user sedang mengetik pada percakapan tertentu. Server meneruskan event ke channel Redis typing_indicators yang kemudian di-broadcast ke semua klien (lihat Event routing).
Payload
Code
Field conversation_id wajib ber-format UUID v4. Kegagalan parse menghasilkan warning di log server dan pesan diabaikan — koneksi tidak ditutup.
Semantik
- Kirim
typingsaat user mulai mengetik setelah kosong, atau pada setiap keystroke dengan throttle (rekomendasi: 1 pesan per 2 detik). - Tidak ada pesan
stop_typing. Implementasi saat ini hanya mengirim flagis_typing: true; frontend penerima menghapus indikator setelah4-5 detiktanpa update baru (timer-based). - Pastikan
conversation_idadalah percakapan yang memang sedang Anda buka. Kirim ke ID lain akan memicu typing palsu di sisi supervisor.
Contoh throttle frontend
Code
Apa yang terjadi setelah server menerima?
- Handler WebSocket mem-parse pesan menjadi
ClientWsMessage::Typing. - Server mengambil
agent_iddanagent_namedariAgentClaimsyang sudah ter-validate saat handshake. - Server mempublikasikan pesan ke Redis
typing_indicatorsdengan payload lengkap (lihat Event routing). - Subscriber menerima pesan dan mem-broadcast-nya ke semua koneksi WebSocket.
- Klien lain (termasuk tab milik agent pengirim) menerima event
typing_indicatorsdan memperbarui UI.
Tidak ada response dari server untuk pesan ini. Jangan menunggu acknowledgment.
ping
Pesan keepalive untuk menjaga koneksi melewati reverse proxy yang menutup koneksi idle. Server menerimanya sebagai no-op.
Payload
Code
Tidak ada field lain.
Semantik
- Kirim tiap
30 detik(atau lebih sering jika proxy Anda memiliki idle timeout <60 detik). - Tidak ada response
pong. Jika Anda membutuhkan bukti bahwa server masih hidup, andalkan event server yang mengalir secara normal atau WebSocket close event untuk deteksi kematian. - Frame WebSocket native ping/pong (opcode
0x9/0xA) juga berfungsi — Axum / Tungstenite menangani otomatis. Pesan JSON{"type":"ping"}adalah alternatif untuk klien yang tidak mudah mengirim control frame.
Contoh interval
Code
Apa yang tidak bisa dilakukan lewat WebSocket
WebSocket hanya untuk push event dan sinyal typing/ping. Tindakan berikut harus lewat REST API:
| Aksi | Cara |
|---|---|
| Kirim pesan ke customer | POST /api/messages |
| Assign percakapan | POST /api/conversations/:id/transfer |
| Resolve percakapan | PATCH /api/conversations/:id dengan status: "resolved" |
| Update presence manual (away/busy) | PATCH /api/auth/me |
Alasannya: API REST punya audit trail, rate limiting, dan middleware RBAC yang konsisten. WebSocket hanya dipakai untuk jalur real-time di mana latensi penting.
Error handling
- JSON invalid — server menulis warning ke log dan mengabaikan pesan. Koneksi tidak ditutup.
typetidak dikenal — sama seperti di atas: log warning, abaikan.conversation_idbukan UUID — sama: log warning, abaikan. Frontend tidak mendapat feedback eksplisit, jadi validasi di klien sebelum mengirim.- Koneksi mati (send error) — handler secara otomatis menghapus koneksi dari registry dan, jika ini koneksi terakhir, mempublikasikan presence
offline.
Troubleshooting
- Typing indicator muncul di supervisor tetapi tidak di agent pengirim sendiri — ini normal: typing di-broadcast ke semua tapi frontend biasanya menyembunyikan indikator untuk diri sendiri. Cek kode
TypingStoredifrontend/src/lib/stores/jika perlu. - Ping tidak mencegah reconnect loop — periksa
proxy_read_timeoutdi nginx. Nilai default 60s biasanya cukup, tetapi beberapa provider cloud mengatur lebih rendah. Anda juga bisa mengurangi interval ping ke 15s. - Server mengirim event tetapi klien tidak menerima — pastikan
ws.readyState === 1sebelum mengirim. Koneksi yang belumopenakan diam-diam mengabaikan pesan yang dikirim.
File terkait
- Parser dan handler:
crates/ws-server/src/handler.rs - Subscriber:
crates/ws-server/src/subscriber.rs - Publish typing dari handler:
crates/ws-server/src/handler.rs(fungsi publish ke Redis) - Enum ClientWsMessage:
crates/ws-server/src/handler.rs