replace Redis with an embedded SQLite string->string KV store (group commit, in-tx events, SQL search)
Build and Push Docker Image / build (push) Successful in 2m44s
Build and Push Docker Image / build (push) Successful in 2m44s
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// EventsStream is the Redis Stream name for file events
|
||||
// EventsStream is the stream name for file events
|
||||
EventsStream = "file:events"
|
||||
|
||||
// EventsStreamMaxLen is the approximate cap on stream length. Bounded
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
EventsStreamMaxLen = 100_000
|
||||
)
|
||||
|
||||
// Dispatcher sends file events to Redis Stream
|
||||
// Dispatcher sends file events to the file:events stream
|
||||
type Dispatcher struct {
|
||||
mu sync.RWMutex
|
||||
storageClient *storage.Client
|
||||
@@ -31,20 +31,20 @@ func NewDispatcher() *Dispatcher {
|
||||
return &Dispatcher{}
|
||||
}
|
||||
|
||||
// SetStorageClient sets the storage client for Redis Stream publishing
|
||||
// SetStorageClient sets the storage client for file:events publishing
|
||||
func (d *Dispatcher) SetStorageClient(client *storage.Client) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.storageClient = client
|
||||
log.Println("[Dispatcher] Storage client set for Redis Stream publishing")
|
||||
log.Println("[Dispatcher] Storage client set for file:events publishing")
|
||||
}
|
||||
|
||||
// Dispatch sends an event to Redis Stream
|
||||
// Dispatch sends an event to the file:events stream
|
||||
func (d *Dispatcher) Dispatch(event FileEvent) {
|
||||
go d.dispatchToStream(event)
|
||||
}
|
||||
|
||||
// dispatchToStream publishes event to Redis Stream for service consumption
|
||||
// dispatchToStream publishes event to the file:events stream for service consumption
|
||||
func (d *Dispatcher) dispatchToStream(event FileEvent) {
|
||||
d.mu.RLock()
|
||||
client := d.storageClient
|
||||
@@ -114,7 +114,7 @@ func (d *Dispatcher) EmitReset(watcherID string) error {
|
||||
// Emit reset event as the first message in the fresh stream
|
||||
event := FileEvent{
|
||||
Type: EventTypeReset,
|
||||
Path: "", // No specific path for reset
|
||||
Path: "", // No specific path for reset
|
||||
WatcherID: watcherID,
|
||||
Timestamp: NowMS(),
|
||||
}
|
||||
@@ -125,7 +125,7 @@ func (d *Dispatcher) EmitReset(watcherID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRecentEvents reads recent events from the Redis stream, newest first.
|
||||
// GetRecentEvents reads recent events from the stream, newest first.
|
||||
// If sinceMS > 0, only events strictly newer than that timestamp are returned.
|
||||
// limit caps the number of returned events (defaults to 100 when <= 0).
|
||||
func (d *Dispatcher) GetRecentEvents(sinceMS int64, limit int) ([]FileEvent, error) {
|
||||
@@ -160,7 +160,7 @@ func (d *Dispatcher) GetRecentEvents(sinceMS int64, limit int) ([]FileEvent, err
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// parseStreamEntry converts a Redis stream entry back into a FileEvent.
|
||||
// parseStreamEntry converts a stream entry back into a FileEvent.
|
||||
// All fields are stored as strings by XADD, so numerics need parsing.
|
||||
func parseStreamEntry(entry storage.StreamEntry) FileEvent {
|
||||
event := FileEvent{}
|
||||
@@ -192,7 +192,7 @@ func parseStreamEntry(entry storage.StreamEntry) FileEvent {
|
||||
}
|
||||
|
||||
// Fall back to the stream ID's millisecond prefix if the timestamp
|
||||
// field is missing or unparseable — every Redis stream ID starts with ms.
|
||||
// field is missing or unparseable — every stream ID starts with ms.
|
||||
if event.Timestamp == 0 && entry.ID != "" {
|
||||
if dash := strings.IndexByte(entry.ID, '-'); dash > 0 {
|
||||
if n, err := strconv.ParseInt(entry.ID[:dash], 10, 64); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user