feat: implement Redis-based message bus and awareness management

- Added RedisMessageBus for message distribution using Redis Pub/Sub.
- Introduced LocalMessageBus as a no-op implementation for single-server mode.
- Created messagebus interface for abstraction of message distribution.
- Implemented awareness management methods: SetAwareness, GetAllAwareness, DeleteAwareness, and ClearAllAwareness.
- Added logger utility for structured logging with zap.
- Refactored SniffYjsClientIDs and MakeYjsDeleteMessage functions for improved readability.
This commit is contained in:
M1ngdaXie
2026-02-04 22:00:55 -08:00
parent 70a406c73c
commit 0f4cff89a2
7 changed files with 1136 additions and 333 deletions

View File

@@ -0,0 +1,80 @@
package messagebus
import (
"context"
)
// MessageBus abstracts message distribution across server instances
type MessageBus interface {
// Publish sends a message to a specific room channel
// data must be preserved as-is (binary safe)
Publish(ctx context.Context, roomID string, data []byte) error
// Subscribe listens to messages for a specific room
// Returns a channel that receives binary messages
Subscribe(ctx context.Context, roomID string) (<-chan []byte, error)
// Unsubscribe stops listening to a room
Unsubscribe(ctx context.Context, roomID string) error
// SetAwareness caches awareness data for a client in a room
SetAwareness(ctx context.Context, roomID string, clientID uint64, data []byte) error
// GetAllAwareness retrieves all cached awareness for a room
GetAllAwareness(ctx context.Context, roomID string) (map[uint64][]byte, error)
// DeleteAwareness removes awareness cache for a client
DeleteAwareness(ctx context.Context, roomID string, clientID uint64) error
ClearAllAwareness(ctx context.Context, roomID string) error
// IsHealthy returns true if message bus is operational
IsHealthy() bool
// Close gracefully shuts down the message bus
Close() error
}
// LocalMessageBus is a no-op implementation for single-server mode
type LocalMessageBus struct{}
func NewLocalMessageBus() *LocalMessageBus {
return &LocalMessageBus{}
}
func (l *LocalMessageBus) Publish(ctx context.Context, roomID string, data []byte) error {
return nil // No-op for local mode
}
func (l *LocalMessageBus) Subscribe(ctx context.Context, roomID string) (<-chan []byte, error) {
ch := make(chan []byte)
close(ch) // Immediately closed channel
return ch, nil
}
func (l *LocalMessageBus) Unsubscribe(ctx context.Context, roomID string) error {
return nil
}
func (l *LocalMessageBus) SetAwareness(ctx context.Context, roomID string, clientID uint64, data []byte) error {
return nil
}
func (l *LocalMessageBus) GetAllAwareness(ctx context.Context, roomID string) (map[uint64][]byte, error) {
return nil, nil
}
func (l *LocalMessageBus) DeleteAwareness(ctx context.Context, roomID string, clientID uint64) error {
return nil
}
func (l *LocalMessageBus) ClearAllAwareness(ctx context.Context, roomID string) error {
return nil
}
func (l *LocalMessageBus) IsHealthy() bool {
return true
}
func (l *LocalMessageBus) Close() error {
return nil
}