Implement event-driven daemon improvements for bd-85
- Add mutation events for label/dep/comment operations - Create separate export-only and import-only functions - Add dropped events counter with safety net export - Complete bd-80 mutation channel implementation Event-driven mode now: - Emits mutation events for ALL write operations (not just create/update/close) - Uses createExportFunc() for mutations (export+commit/push only, no pull) - Uses createAutoImportFunc() for file changes (pull+import only, no export) - Tracks dropped events and triggers safety export every 60s if any dropped - Achieves <500ms latency target by avoiding full sync on each trigger Behind BEADS_DAEMON_MODE=events flag (poll is still default)
This commit is contained in:
@@ -47,7 +47,8 @@ type Server struct {
|
||||
// Auto-import single-flight guard
|
||||
importInProgress atomic.Bool
|
||||
// Mutation events for event-driven daemon
|
||||
mutationChan chan MutationEvent
|
||||
mutationChan chan MutationEvent
|
||||
droppedEvents atomic.Int64 // Counter for dropped mutation events
|
||||
}
|
||||
|
||||
// MutationEvent represents a database mutation for event-driven sync
|
||||
@@ -105,7 +106,8 @@ func (s *Server) emitMutation(eventType, issueID string) {
|
||||
}:
|
||||
// Event sent successfully
|
||||
default:
|
||||
// Channel full, event dropped (not critical - sync will happen eventually)
|
||||
// Channel full, increment dropped events counter
|
||||
s.droppedEvents.Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,3 +115,13 @@ func (s *Server) emitMutation(eventType, issueID string) {
|
||||
func (s *Server) MutationChan() <-chan MutationEvent {
|
||||
return s.mutationChan
|
||||
}
|
||||
|
||||
// DroppedEventsCount returns the number of dropped mutation events
|
||||
func (s *Server) DroppedEventsCount() int64 {
|
||||
return s.droppedEvents.Load()
|
||||
}
|
||||
|
||||
// ResetDroppedEventsCount resets the dropped events counter and returns the previous value
|
||||
func (s *Server) ResetDroppedEventsCount() int64 {
|
||||
return s.droppedEvents.Swap(0)
|
||||
}
|
||||
|
||||
@@ -34,12 +34,15 @@ func (s *Server) handleDepAdd(req *Request) Response {
|
||||
}
|
||||
}
|
||||
|
||||
// Emit mutation event for event-driven daemon
|
||||
s.emitMutation("update", depArgs.FromID)
|
||||
|
||||
return Response{Success: true}
|
||||
}
|
||||
|
||||
// Generic handler for simple store operations with standard error handling
|
||||
func (s *Server) handleSimpleStoreOp(req *Request, argsPtr interface{}, argDesc string,
|
||||
opFunc func(context.Context, storage.Storage, string) error) Response {
|
||||
opFunc func(context.Context, storage.Storage, string) error, issueID string) Response {
|
||||
if err := json.Unmarshal(req.Args, argsPtr); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
@@ -57,6 +60,9 @@ func (s *Server) handleSimpleStoreOp(req *Request, argsPtr interface{}, argDesc
|
||||
}
|
||||
}
|
||||
|
||||
// Emit mutation event for event-driven daemon
|
||||
s.emitMutation("update", issueID)
|
||||
|
||||
return Response{Success: true}
|
||||
}
|
||||
|
||||
@@ -64,21 +70,21 @@ func (s *Server) handleDepRemove(req *Request) Response {
|
||||
var depArgs DepRemoveArgs
|
||||
return s.handleSimpleStoreOp(req, &depArgs, "dep remove", func(ctx context.Context, store storage.Storage, actor string) error {
|
||||
return store.RemoveDependency(ctx, depArgs.FromID, depArgs.ToID, actor)
|
||||
})
|
||||
}, depArgs.FromID)
|
||||
}
|
||||
|
||||
func (s *Server) handleLabelAdd(req *Request) Response {
|
||||
var labelArgs LabelAddArgs
|
||||
return s.handleSimpleStoreOp(req, &labelArgs, "label add", func(ctx context.Context, store storage.Storage, actor string) error {
|
||||
return store.AddLabel(ctx, labelArgs.ID, labelArgs.Label, actor)
|
||||
})
|
||||
}, labelArgs.ID)
|
||||
}
|
||||
|
||||
func (s *Server) handleLabelRemove(req *Request) Response {
|
||||
var labelArgs LabelRemoveArgs
|
||||
return s.handleSimpleStoreOp(req, &labelArgs, "label remove", func(ctx context.Context, store storage.Storage, actor string) error {
|
||||
return store.RemoveLabel(ctx, labelArgs.ID, labelArgs.Label, actor)
|
||||
})
|
||||
}, labelArgs.ID)
|
||||
}
|
||||
|
||||
func (s *Server) handleCommentList(req *Request) Response {
|
||||
@@ -128,6 +134,9 @@ func (s *Server) handleCommentAdd(req *Request) Response {
|
||||
}
|
||||
}
|
||||
|
||||
// Emit mutation event for event-driven daemon
|
||||
s.emitMutation("comment", commentArgs.ID)
|
||||
|
||||
data, _ := json.Marshal(comment)
|
||||
return Response{
|
||||
Success: true,
|
||||
|
||||
Reference in New Issue
Block a user