Split internal/rpc/server.go into 8 focused modules (bd-215)
Refactored monolithic 2238-line server.go into 8 files with clear responsibilities: - server_core.go: Server type, NewServer (115 lines) - server_lifecycle_conn.go: Start/Stop/connection handling (248 lines) - server_cache_storage.go: Storage caching and eviction (286 lines) - server_routing_validation_diagnostics.go: Request routing/validation (384 lines) - server_issues_epics.go: Issue CRUD operations (506 lines) - server_labels_deps_comments.go: Labels/deps/comments (199 lines) - server_compact.go: Compaction operations (287 lines) - server_export_import_auto.go: Export/import operations (293 lines) Improvements: - Replaced RWMutex.TryLock with atomic.Bool for portable single-flight guard - Added default storage close in Stop() to prevent FD leaks - All methods remain on *Server receiver (no behavior changes) - Each file <510 LOC for better maintainability - All tests pass, daemon verified working Amp-Thread-ID: https://ampcode.com/threads/T-92d481ad-1bda-4ecd-bcf5-874a1889db30 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
199
internal/rpc/server_labels_deps_comments.go
Normal file
199
internal/rpc/server_labels_deps_comments.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/steveyegge/beads/internal/storage"
|
||||
"github.com/steveyegge/beads/internal/types"
|
||||
)
|
||||
|
||||
func (s *Server) handleDepAdd(req *Request) Response {
|
||||
var depArgs DepAddArgs
|
||||
if err := json.Unmarshal(req.Args, &depArgs); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid dep add args: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
store, err := s.getStorageForRequest(req)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("storage error: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
dep := &types.Dependency{
|
||||
IssueID: depArgs.FromID,
|
||||
DependsOnID: depArgs.ToID,
|
||||
Type: types.DependencyType(depArgs.DepType),
|
||||
}
|
||||
|
||||
ctx := s.reqCtx(req)
|
||||
if err := store.AddDependency(ctx, dep, s.reqActor(req)); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("failed to add dependency: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := json.Unmarshal(req.Args, argsPtr); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid %s args: %v", argDesc, err),
|
||||
}
|
||||
}
|
||||
|
||||
store, err := s.getStorageForRequest(req)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("storage error: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
ctx := s.reqCtx(req)
|
||||
if err := opFunc(ctx, store, s.reqActor(req)); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("failed to %s: %v", argDesc, err),
|
||||
}
|
||||
}
|
||||
|
||||
return Response{Success: true}
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleCommentList(req *Request) Response {
|
||||
var commentArgs CommentListArgs
|
||||
if err := json.Unmarshal(req.Args, &commentArgs); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid comment list args: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
store, err := s.getStorageForRequest(req)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("storage error: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
ctx := s.reqCtx(req)
|
||||
comments, err := store.GetIssueComments(ctx, commentArgs.ID)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("failed to list comments: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(comments)
|
||||
return Response{
|
||||
Success: true,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleCommentAdd(req *Request) Response {
|
||||
var commentArgs CommentAddArgs
|
||||
if err := json.Unmarshal(req.Args, &commentArgs); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid comment add args: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
store, err := s.getStorageForRequest(req)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("storage error: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
ctx := s.reqCtx(req)
|
||||
comment, err := store.AddIssueComment(ctx, commentArgs.ID, commentArgs.Author, commentArgs.Text)
|
||||
if err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("failed to add comment: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(comment)
|
||||
return Response{
|
||||
Success: true,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleBatch(req *Request) Response {
|
||||
var batchArgs BatchArgs
|
||||
if err := json.Unmarshal(req.Args, &batchArgs); err != nil {
|
||||
return Response{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("invalid batch args: %v", err),
|
||||
}
|
||||
}
|
||||
|
||||
results := make([]BatchResult, 0, len(batchArgs.Operations))
|
||||
|
||||
for _, op := range batchArgs.Operations {
|
||||
subReq := &Request{
|
||||
Operation: op.Operation,
|
||||
Args: op.Args,
|
||||
Actor: req.Actor,
|
||||
RequestID: req.RequestID,
|
||||
Cwd: req.Cwd, // Pass through context
|
||||
ClientVersion: req.ClientVersion, // Pass through version for compatibility checks
|
||||
}
|
||||
|
||||
resp := s.handleRequest(subReq)
|
||||
|
||||
results = append(results, BatchResult(resp))
|
||||
|
||||
if !resp.Success {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
batchResp := BatchResponse{Results: results}
|
||||
data, _ := json.Marshal(batchResp)
|
||||
|
||||
return Response{
|
||||
Success: true,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user