Chat Application: message, delivery ও offline sync
Chat Application
এই পাঠের সূচিপত্র
এই পাঠে যা শিখবেন
- Durable message এবং realtime delivery আলাদা করা
- Conversation order ও receipt semantics নির্ধারণ
- Offline sync এবং cross-server fan-out design
সমস্যা দিয়ে শুরু
Mobile user message পাঠানোর পরে network চলে গেল। Sender delivered দেখছেন, receiver পাননি। Requirements: one-to-one এবং ছোট group chat, durable history, realtime delivery, reconnect sync। End-to-end encryption ও massive broadcast প্রথম scope-এর বাইরে বলুন, পরে extension হিসেবে ভাবুন। Server accepted, recipient device received এবং user read—এই তিনটি state একসঙ্গে delivered নামে দেখালে product expectation ভুল হয়।
সহজ করে বুঝি
WebSocket live connection ধরে, কিন্তু message durability storage-এ থাকে। Message API authenticated sender ও conversation membership যাচাই করে। Client-generated operation ID retry dedupe করতে পারে। Per-conversation order server sequence বা durable ordering key দিয়ে define করুন; global total order সাধারণত দরকার নেই। Pub/Sub different gateway-তে connected recipient খুঁজে event পাঠায়, offline history-এর replacement নয়। Presence approximate lease হতে পারে।
পরিচিত একটি উপমা
চিঠি post office-এ জমা, বাসায় পৌঁছানো এবং recipient পড়া তিন ধাপ। Messenger দৌড়ে খবর দিলেও post office-এর durable record না থাকলে হারানো চিঠি ফেরত খোঁজা যায় না। Receipt-এর ভাষা সেই আলাদা promise প্রকাশ করবে।
নকশাটি দেখুন
Diagram লোড হচ্ছে…
Diagram-এর text flow দেখুন
flowchart LR S[Sender] --> A[Authenticated message API] A --> D[(Messages and membership)] A --> O[Durable delivery event] O --> B[Pub Sub backbone] B --> G[Recipient gateway] G --> R[Online device] R --> K[Delivered or read receipt] X[Reconnecting device] --> D
API membership দেখে message persist করে। Commit-এর পরে delivery event publish হয়। Backbone gateway-তে পৌঁছায়; online device acknowledgment দিলে delivery state বদলায়। Reconnect client last seen sequence নিয়ে database history পড়ে gap পূরণ করে। Pub/Sub event হারালেও durable history থেকে sync সম্ভব। Group receipt storage member count অনুযায়ী বড় হতে পারে।
PHP ও Laravel-এ প্রয়োগ
ধরা যাক দিনে ১০ লাখ message, average প্রায় ১২ write QPS; group fan-out এবং peak multiplier আলাদা। POST /conversations/{id}/messages, GET /messages?after=sequence; messages-এ conversation_id, sender_id, client_message_id unique scope, body, sequence। নিচের controller fragment membership আগে authorized, body validated, client_message_id scoped unique constraint আছে। এটি sequence allocation বা realtime delivery-এর পূর্ণ implementation নয়।
use App\Models\Message;
$message = Message::query()->firstOrCreate([
'conversation_id' => $conversation->id,
'sender_id' => $request->user()->id,
'client_message_id' => $request->validated('client_message_id'),
], [
'body' => $request->validated('body'),
]);
return response()->json(['id' => $message->id], 201);সুবিধা, সীমাবদ্ধতা ও trade-off
Persistent socket low-latency push দেয়, connection capacity এবং backpressure দরকার। Database-first acceptance latency বাড়াতে পারে, কিন্তু accepted message durable হয়। Per-conversation ordering hot group-এ bottleneck হতে পারে। Read receipts privacy-sensitive; user setting ও multiple device aggregation ঠিক করুন। Presence exact guarantee না দিয়ে last active বা approximate state বলা বেশি সৎ।
সাধারণ ভুল
- WebSocket send success-কে recipient read বলা।
- Redis Pub/Sub-কে একমাত্র message history বানানো।
- Private channel membership authorization বাদ দেওয়া।
আরও একটু গভীরে
Duplicate creation race database unique constraint দিয়ে সামলান; same client ID-তে changed body এলে conflict policy দিন। Outbox publish gap সামলাতে পারে। Message edits/deletes versioned event হলে offline client convergence সহজ হয়। Attachment authorization এবং malware scanning আলাদা workflow। Gateway slow client-এর outbound buffer bounded রাখুন; backlog পূর্ণ হলে reconnect sync route দেখান।
মনে রাখুন
Chat-এর reliability durable history ও reconnect sync-এ; realtime push এবং receipt আলাদা delivery promise।
নিজে চেষ্টা করুন
Message commit-এর পরে gateway crash scenario লিখুন। Sender retry এবং recipient reconnect-এ duplicate না দেখানোর protocol দিন। তিন device-এ read receipt aggregate করার দুটি policy তুলনা করুন।
নিজের বোঝা যাচাই করুন
1. Socket write মানে delivered?
শুধু local transport accept হতে পারে। Recipient acknowledgment এবং read action আলাদা signal।
2. Order global চাই?
সাধারণ chat-এ conversation-level order যথেষ্ট। Global order coordination ও latency অযথা বাড়ায়।
3. Pub/Sub হারালে message হারাবে?
Durable database history ও cursor sync থাকলে gap পূরণ করা যায়। Pub/Sub একমাত্র storage হলে ঝুঁকি।
4. Client ID কেন?
Retry-তে একই logical message চেনা যায়। Server unique constraint ও payload conflict policy দিয়ে enforce করুন।
5. Presence exact?
Network disconnect detection delayed হতে পারে। Heartbeat/lease-based approximate state হিসেবে product semantics নির্ধারণ করুন।
আরও পড়ুন
এই পাঠের কুইজ
এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।
এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।
জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।
অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।