- Fix YAML tags in auth config struct (json -> yaml) - Update CLI configs to use pre-hashed API keys - Remove double hashing in WebSocket client - Fix port mapping (9102 -> 9103) in CLI commands - Update permission keys to use jobs:read, jobs:create, etc. - Clean up all debug logging from CLI and server - All user roles now authenticate correctly: * Admin: Can queue jobs and see all jobs * Researcher: Can queue jobs and see own jobs * Analyst: Can see status (read-only access) Multi-user authentication is now fully functional.
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
// Package network provides SSH client and retry utilities.
|
|
package network
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
// RetryConfig defines retry behavior parameters.
|
|
type RetryConfig struct {
|
|
MaxAttempts int
|
|
InitialDelay time.Duration
|
|
MaxDelay time.Duration
|
|
Multiplier float64
|
|
}
|
|
|
|
// DefaultRetryConfig returns a default retry configuration.
|
|
func DefaultRetryConfig() RetryConfig {
|
|
return RetryConfig{
|
|
MaxAttempts: 3,
|
|
InitialDelay: 1 * time.Second,
|
|
MaxDelay: 30 * time.Second,
|
|
Multiplier: 2.0,
|
|
}
|
|
}
|
|
|
|
// Retry executes a function with exponential backoff retry logic.
|
|
func Retry(ctx context.Context, cfg RetryConfig, fn func() error) error {
|
|
var lastErr error
|
|
delay := cfg.InitialDelay
|
|
|
|
for attempt := 0; attempt < cfg.MaxAttempts; attempt++ {
|
|
err := fn()
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
lastErr = err
|
|
|
|
if attempt < cfg.MaxAttempts-1 {
|
|
select {
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
case <-time.After(delay):
|
|
delay = time.Duration(math.Min(
|
|
float64(delay)*cfg.Multiplier,
|
|
float64(cfg.MaxDelay),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
|
|
return lastErr
|
|
}
|
|
|
|
// RetryWithBackoff provides a convenient wrapper for common retry scenarios
|
|
func RetryWithBackoff(ctx context.Context, maxAttempts int, operation func() error) error {
|
|
cfg := RetryConfig{
|
|
MaxAttempts: maxAttempts,
|
|
InitialDelay: 200 * time.Millisecond,
|
|
MaxDelay: 2 * time.Second,
|
|
Multiplier: 2.0,
|
|
}
|
|
return Retry(ctx, cfg, operation)
|
|
}
|
|
|
|
// RetryForNetworkOperations is optimized for network-related operations
|
|
func RetryForNetworkOperations(ctx context.Context, operation func() error) error {
|
|
cfg := RetryConfig{
|
|
MaxAttempts: 5,
|
|
InitialDelay: 200 * time.Millisecond,
|
|
MaxDelay: 5 * time.Second,
|
|
Multiplier: 1.5,
|
|
}
|
|
return Retry(ctx, cfg, operation)
|
|
}
|