refactor(process): replace fmt.Errorf and errors.New with coreerr.E()
Replace all 27 instances of fmt.Errorf/errors.New in production code with coreerr.E() from forge.lthn.ai/core/go-log for structured error context (op, message, cause). Promote go-log from indirect to direct dependency in go.mod. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
10adcbe289
commit
d73dfa3d73
8 changed files with 40 additions and 30 deletions
13
daemon.go
13
daemon.go
|
|
@ -3,10 +3,11 @@ package process
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// DaemonOptions configures daemon mode execution.
|
||||
|
|
@ -72,7 +73,7 @@ func (d *Daemon) Start() error {
|
|||
defer d.mu.Unlock()
|
||||
|
||||
if d.running {
|
||||
return errors.New("daemon already running")
|
||||
return coreerr.E("Daemon.Start", "daemon already running", nil)
|
||||
}
|
||||
|
||||
if d.pid != nil {
|
||||
|
|
@ -100,7 +101,7 @@ func (d *Daemon) Start() error {
|
|||
entry.Health = d.health.Addr()
|
||||
}
|
||||
if err := d.opts.Registry.Register(entry); err != nil {
|
||||
return fmt.Errorf("registry: %w", err)
|
||||
return coreerr.E("Daemon.Start", "registry", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ func (d *Daemon) Run(ctx context.Context) error {
|
|||
d.mu.Lock()
|
||||
if !d.running {
|
||||
d.mu.Unlock()
|
||||
return errors.New("daemon not started - call Start() first")
|
||||
return coreerr.E("Daemon.Run", "daemon not started - call Start() first", nil)
|
||||
}
|
||||
d.mu.Unlock()
|
||||
|
||||
|
|
@ -138,13 +139,13 @@ func (d *Daemon) Stop() error {
|
|||
if d.health != nil {
|
||||
d.health.SetReady(false)
|
||||
if err := d.health.Stop(shutdownCtx); err != nil {
|
||||
errs = append(errs, fmt.Errorf("health server: %w", err))
|
||||
errs = append(errs, coreerr.E("Daemon.Stop", "health server", err))
|
||||
}
|
||||
}
|
||||
|
||||
if d.pid != nil {
|
||||
if err := d.pid.Release(); err != nil && !os.IsNotExist(err) {
|
||||
errs = append(errs, fmt.Errorf("pid file: %w", err))
|
||||
errs = append(errs, coreerr.E("Daemon.Stop", "pid file", err))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// Options configuration for command execution
|
||||
|
|
@ -147,7 +149,7 @@ func RunQuiet(ctx context.Context, name string, args ...string) error {
|
|||
cmd := Command(ctx, name, args...).WithStderr(&stderr)
|
||||
if err := cmd.Run(); err != nil {
|
||||
// Include stderr in error message
|
||||
return fmt.Errorf("%w: %s", err, strings.TrimSpace(stderr.String()))
|
||||
return coreerr.E("RunQuiet", strings.TrimSpace(stderr.String()), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -155,9 +157,9 @@ func RunQuiet(ctx context.Context, name string, args ...string) error {
|
|||
func wrapError(err error, name string, args []string) error {
|
||||
cmdStr := name + " " + strings.Join(args, " ")
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
return fmt.Errorf("command %q failed with exit code %d: %w", cmdStr, exitErr.ExitCode(), err)
|
||||
return coreerr.E("wrapError", fmt.Sprintf("command %q failed with exit code %d", cmdStr, exitErr.ExitCode()), err)
|
||||
}
|
||||
return fmt.Errorf("failed to execute %q: %w", cmdStr, err)
|
||||
return coreerr.E("wrapError", fmt.Sprintf("failed to execute %q", cmdStr), err)
|
||||
}
|
||||
|
||||
func (c *Cmd) getLogger() Logger {
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -6,13 +6,13 @@ require (
|
|||
forge.lthn.ai/core/api v0.1.2
|
||||
forge.lthn.ai/core/go v0.3.1
|
||||
forge.lthn.ai/core/go-io v0.1.2
|
||||
forge.lthn.ai/core/go-log v0.0.2
|
||||
forge.lthn.ai/core/go-ws v0.2.0
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
)
|
||||
|
||||
require (
|
||||
forge.lthn.ai/core/go-log v0.0.2 // indirect
|
||||
github.com/99designs/gqlgen v0.17.88 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/agnivade/levenshtein v1.2.1 // indirect
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// HealthCheck is a function that returns nil if healthy.
|
||||
|
|
@ -82,7 +84,7 @@ func (h *HealthServer) Start() error {
|
|||
|
||||
listener, err := net.Listen("tcp", h.addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen on %s: %w", h.addr, err)
|
||||
return coreerr.E("HealthServer.Start", fmt.Sprintf("failed to listen on %s", h.addr), err)
|
||||
}
|
||||
|
||||
h.listener = listener
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"syscall"
|
||||
|
||||
coreio "forge.lthn.ai/core/go-io"
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// PIDFile manages a process ID file for single-instance enforcement.
|
||||
|
|
@ -34,7 +35,7 @@ func (p *PIDFile) Acquire() error {
|
|||
if err == nil && pid > 0 {
|
||||
if proc, err := os.FindProcess(pid); err == nil {
|
||||
if err := proc.Signal(syscall.Signal(0)); err == nil {
|
||||
return fmt.Errorf("another instance is running (PID %d)", pid)
|
||||
return coreerr.E("PIDFile.Acquire", fmt.Sprintf("another instance is running (PID %d)", pid), nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,13 +44,13 @@ func (p *PIDFile) Acquire() error {
|
|||
|
||||
if dir := filepath.Dir(p.path); dir != "." {
|
||||
if err := coreio.Local.EnsureDir(dir); err != nil {
|
||||
return fmt.Errorf("failed to create PID directory: %w", err)
|
||||
return coreerr.E("PIDFile.Acquire", "failed to create PID directory", err)
|
||||
}
|
||||
}
|
||||
|
||||
pid := os.Getpid()
|
||||
if err := coreio.Local.Write(p.path, strconv.Itoa(pid)); err != nil {
|
||||
return fmt.Errorf("failed to write PID file: %w", err)
|
||||
return coreerr.E("PIDFile.Acquire", "failed to write PID file", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"os/exec"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// Process represents a managed external process.
|
||||
|
|
@ -87,13 +89,13 @@ func (p *Process) Wait() error {
|
|||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
if p.Status == StatusFailed {
|
||||
return fmt.Errorf("process failed to start: %s", p.ID)
|
||||
return coreerr.E("Process.Wait", fmt.Sprintf("process failed to start: %s", p.ID), nil)
|
||||
}
|
||||
if p.Status == StatusKilled {
|
||||
return fmt.Errorf("process was killed: %s", p.ID)
|
||||
return coreerr.E("Process.Wait", fmt.Sprintf("process was killed: %s", p.ID), nil)
|
||||
}
|
||||
if p.ExitCode != 0 {
|
||||
return fmt.Errorf("process exited with code %d", p.ExitCode)
|
||||
return coreerr.E("Process.Wait", fmt.Sprintf("process exited with code %d", p.ExitCode), nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ package process
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// Runner orchestrates multiple processes with dependencies.
|
||||
|
|
@ -104,7 +105,7 @@ func (r *Runner) RunAll(ctx context.Context, specs []RunSpec) (*RunAllResult, er
|
|||
Name: name,
|
||||
Spec: remaining[name],
|
||||
Skipped: true,
|
||||
Error: errors.New("circular dependency or missing dependency"),
|
||||
Error: coreerr.E("Runner.RunAll", "circular dependency or missing dependency", nil),
|
||||
})
|
||||
}
|
||||
break
|
||||
|
|
@ -136,7 +137,7 @@ func (r *Runner) RunAll(ctx context.Context, specs []RunSpec) (*RunAllResult, er
|
|||
Name: spec.Name,
|
||||
Spec: spec,
|
||||
Skipped: true,
|
||||
Error: errors.New("skipped due to dependency failure"),
|
||||
Error: coreerr.E("Runner.RunAll", "skipped due to dependency failure", nil),
|
||||
}
|
||||
} else {
|
||||
result = r.runSpec(ctx, spec)
|
||||
|
|
|
|||
21
service.go
21
service.go
|
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"forge.lthn.ai/core/go/pkg/core"
|
||||
coreerr "forge.lthn.ai/core/go-log"
|
||||
)
|
||||
|
||||
// Default buffer size for process output (1MB).
|
||||
|
|
@ -20,9 +21,9 @@ const DefaultBufferSize = 1024 * 1024
|
|||
|
||||
// Errors
|
||||
var (
|
||||
ErrProcessNotFound = errors.New("process not found")
|
||||
ErrProcessNotRunning = errors.New("process is not running")
|
||||
ErrStdinNotAvailable = errors.New("stdin not available")
|
||||
ErrProcessNotFound = coreerr.E("", "process not found", nil)
|
||||
ErrProcessNotRunning = coreerr.E("", "process is not running", nil)
|
||||
ErrStdinNotAvailable = coreerr.E("", "stdin not available", nil)
|
||||
)
|
||||
|
||||
// Service manages process execution with Core IPC integration.
|
||||
|
|
@ -121,19 +122,19 @@ func (s *Service) StartWithOptions(ctx context.Context, opts RunOptions) (*Proce
|
|||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("failed to create stdout pipe: %w", err)
|
||||
return nil, coreerr.E("Service.StartWithOptions", "failed to create stdout pipe", err)
|
||||
}
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("failed to create stderr pipe: %w", err)
|
||||
return nil, coreerr.E("Service.StartWithOptions", "failed to create stderr pipe", err)
|
||||
}
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("failed to create stdin pipe: %w", err)
|
||||
return nil, coreerr.E("Service.StartWithOptions", "failed to create stdin pipe", err)
|
||||
}
|
||||
|
||||
// Create output buffer (enabled by default)
|
||||
|
|
@ -161,7 +162,7 @@ func (s *Service) StartWithOptions(ctx context.Context, opts RunOptions) (*Proce
|
|||
// Start the process
|
||||
if err := cmd.Start(); err != nil {
|
||||
cancel()
|
||||
return nil, fmt.Errorf("failed to start process: %w", err)
|
||||
return nil, coreerr.E("Service.StartWithOptions", "failed to start process", err)
|
||||
}
|
||||
|
||||
// Store process
|
||||
|
|
@ -327,7 +328,7 @@ func (s *Service) Remove(id string) error {
|
|||
}
|
||||
|
||||
if proc.IsRunning() {
|
||||
return errors.New("cannot remove running process")
|
||||
return coreerr.E("Service.Remove", "cannot remove running process", nil)
|
||||
}
|
||||
|
||||
delete(s.processes, id)
|
||||
|
|
@ -367,7 +368,7 @@ func (s *Service) Run(ctx context.Context, command string, args ...string) (stri
|
|||
|
||||
output := proc.Output()
|
||||
if proc.ExitCode != 0 {
|
||||
return output, fmt.Errorf("process exited with code %d", proc.ExitCode)
|
||||
return output, coreerr.E("Service.Run", fmt.Sprintf("process exited with code %d", proc.ExitCode), nil)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
|
@ -383,7 +384,7 @@ func (s *Service) RunWithOptions(ctx context.Context, opts RunOptions) (string,
|
|||
|
||||
output := proc.Output()
|
||||
if proc.ExitCode != 0 {
|
||||
return output, fmt.Errorf("process exited with code %d", proc.ExitCode)
|
||||
return output, coreerr.E("Service.RunWithOptions", fmt.Sprintf("process exited with code %d", proc.ExitCode), nil)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue