feat(chat): implement sequence pre-allocation, versioned sync, and push worker
All checks were successful
Build Backend / build (push) Successful in 4m20s
Build Backend / build-docker (push) Successful in 1m7s

Introduce several performance and synchronization enhancements:
- Implement `SeqBufferManager` to allow sequence number pre-allocation via Redis Lua scripts, reducing atomic increment overhead.
- Add `PushWorker` to handle asynchronous message pushing using Redis Streams.
- Implement incremental conversation synchronization via `ConversationVersionLog` to allow clients to fetch only recent changes.
- Add support for Gzip compression in WebSocket communications to reduce bandwidth usage.
- Update dependency injection and configuration to support these new components.
This commit is contained in:
2026-05-17 23:38:04 +08:00
parent f63c795dcb
commit 6bf87fec46
26 changed files with 1450 additions and 82 deletions

View File

@@ -0,0 +1,94 @@
package ws
import (
"bytes"
"testing"
)
func TestCompressDecompressRoundTrip(t *testing.T) {
c := NewCompressor(6)
original := []byte(`{"type":"chat_message","payload":{"conversation_id":"conv1","message":"hello world"}}`)
compressed, err := c.Compress(original)
if err != nil {
t.Fatalf("Compress failed: %v", err)
}
if len(compressed) >= len(original) {
t.Logf("warning: compressed size (%d) >= original size (%d), but this can happen for small payloads", len(compressed), len(original))
}
if !IsCompressed(compressed) {
t.Fatal("IsCompressed should return true for gzip data")
}
decompressed, err := c.Decompress(compressed)
if err != nil {
t.Fatalf("Decompress failed: %v", err)
}
if !bytes.Equal(decompressed, original) {
t.Fatalf("round-trip mismatch: got %q, want %q", decompressed, original)
}
}
func TestIsCompressed(t *testing.T) {
if IsCompressed([]byte{}) {
t.Fatal("empty data should not be considered compressed")
}
if IsCompressed([]byte{0x00}) {
t.Fatal("0x00 should not be considered gzip magic byte")
}
if !IsCompressed([]byte{0x1F, 0x8B}) {
t.Fatal("gzip magic bytes should be detected")
}
}
func TestDecompressNonGzipData(t *testing.T) {
c := NewCompressor(6)
_, err := c.Decompress([]byte("not gzip data"))
if err == nil {
t.Fatal("expected error when decompressing non-gzip data")
}
}
func TestDefaultCompressor(t *testing.T) {
data := []byte("test data for default compressor")
compressed, err := DefaultCompressor.Compress(data)
if err != nil {
t.Fatalf("DefaultCompressor.Compress failed: %v", err)
}
decompressed, err := DefaultCompressor.Decompress(compressed)
if err != nil {
t.Fatalf("DefaultCompressor.Decompress failed: %v", err)
}
if !bytes.Equal(decompressed, data) {
t.Fatalf("DefaultCompressor round-trip mismatch")
}
}
func BenchmarkCompress(b *testing.B) {
c := NewCompressor(6)
data := bytes.Repeat([]byte(`{"type":"chat_message","payload":{"message":"hello"}}`), 10)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := c.Compress(data)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkDecompress(b *testing.B) {
c := NewCompressor(6)
data := bytes.Repeat([]byte(`{"type":"chat_message","payload":{"message":"hello"}}`), 10)
compressed, _ := c.Compress(data)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := c.Decompress(compressed)
if err != nil {
b.Fatal(err)
}
}
}