feat: add message reliability foundation
All checks were successful
CI / test (push) Successful in 23s
All checks were successful
CI / test (push) Successful in 23s
- implement idempotent message creation via client_message_id - add persistent delivered/read receipts - expose /messages/status and wire websocket receipt events - update web client to send client ids and auto-ack delivered/read
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { attachFile, requestUploadUrl, sendMessage, uploadToPresignedUrl } from "../api/chats";
|
||||
import { attachFile, requestUploadUrl, sendMessageWithClientId, uploadToPresignedUrl } from "../api/chats";
|
||||
import { useAuthStore } from "../store/authStore";
|
||||
import { useChatStore } from "../store/chatStore";
|
||||
import { buildWsUrl } from "../utils/ws";
|
||||
@@ -28,6 +28,13 @@ export function MessageComposer() {
|
||||
};
|
||||
}, [previewUrl]);
|
||||
|
||||
function makeClientMessageId(): string {
|
||||
if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return `msg-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
}
|
||||
|
||||
function getWs(): WebSocket | null {
|
||||
if (!accessToken || !activeChatId) {
|
||||
return null;
|
||||
@@ -44,7 +51,7 @@ export function MessageComposer() {
|
||||
if (!activeChatId || !text.trim()) {
|
||||
return;
|
||||
}
|
||||
const message = await sendMessage(activeChatId, text.trim(), "text");
|
||||
const message = await sendMessageWithClientId(activeChatId, text.trim(), "text", makeClientMessageId());
|
||||
prependMessage(activeChatId, message);
|
||||
setText("");
|
||||
const ws = getWs();
|
||||
@@ -61,7 +68,7 @@ export function MessageComposer() {
|
||||
try {
|
||||
const upload = await requestUploadUrl(file);
|
||||
await uploadToPresignedUrl(upload.upload_url, upload.required_headers, file, setUploadProgress);
|
||||
const message = await sendMessage(activeChatId, upload.file_url, messageType);
|
||||
const message = await sendMessageWithClientId(activeChatId, upload.file_url, messageType, makeClientMessageId());
|
||||
await attachFile(message.id, upload.file_url, file.type || "application/octet-stream", file.size);
|
||||
prependMessage(activeChatId, message);
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user