Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Add UndeployAll() using label selectors to clean up monorepo components on project deletion (replaces name-based Undeploy in DeleteProject and the direct undeploy handler) - Add ResourceGC background worker that periodically finds K8s resources whose project label has no matching DB record, deletes after 1h safety window - Widen deployer client type from *kubernetes.Clientset to kubernetes.Interface for testability - UndeployAll accumulates errors via errors.Join instead of failing fast - Add checkout/checkin sidecar dev flow: temporary git tokens, branch checkout, review on checkin with cleanup workers - Add interactive sessions: pod binding, command execution, SSE streaming, ephemeral preview URLs with session cleanup workers - Add GET /workers/pool endpoint for aggregate capacity and queue depth - Add sessions:read and sessions:execute auth scopes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
package worker
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/orchard9/rdev/internal/logging"
|
|
)
|
|
|
|
// CheckoutCleanupService defines the interface for checkout cleanup operations.
|
|
// This allows the worker to depend on the service interface rather than the concrete type.
|
|
type CheckoutCleanupService interface {
|
|
CleanupExpired(ctx context.Context) (int, error)
|
|
}
|
|
|
|
// CheckoutCleanup runs periodic cleanup of expired checkouts.
|
|
// Expired checkouts have their Gitea tokens revoked and status updated.
|
|
type CheckoutCleanup struct {
|
|
service CheckoutCleanupService
|
|
cleanupInterval time.Duration
|
|
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
// CheckoutCleanupConfig holds configuration for checkout cleanup.
|
|
type CheckoutCleanupConfig struct {
|
|
// CleanupInterval is how often to run cleanup.
|
|
// Default: 5 minutes.
|
|
CleanupInterval time.Duration
|
|
}
|
|
|
|
// DefaultCheckoutCleanupConfig returns sensible defaults.
|
|
func DefaultCheckoutCleanupConfig() *CheckoutCleanupConfig {
|
|
return &CheckoutCleanupConfig{
|
|
CleanupInterval: 5 * time.Minute,
|
|
}
|
|
}
|
|
|
|
// NewCheckoutCleanup creates a new checkout cleanup worker.
|
|
func NewCheckoutCleanup(service CheckoutCleanupService, cfg *CheckoutCleanupConfig) *CheckoutCleanup {
|
|
if cfg == nil {
|
|
cfg = DefaultCheckoutCleanupConfig()
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
return &CheckoutCleanup{
|
|
service: service,
|
|
cleanupInterval: cfg.CleanupInterval,
|
|
ctx: ctx,
|
|
cancel: cancel,
|
|
}
|
|
}
|
|
|
|
// Start begins the cleanup loop.
|
|
func (c *CheckoutCleanup) Start() {
|
|
log := logging.FromContext(c.ctx).WithWorker("checkout-cleanup")
|
|
log.Info("checkout cleanup started",
|
|
"cleanup_interval", c.cleanupInterval,
|
|
)
|
|
|
|
c.wg.Add(1)
|
|
go c.cleanupLoop()
|
|
}
|
|
|
|
// Stop gracefully shuts down the cleanup worker.
|
|
func (c *CheckoutCleanup) Stop() {
|
|
log := logging.FromContext(c.ctx).WithWorker("checkout-cleanup")
|
|
log.Info("checkout cleanup stopping")
|
|
c.cancel()
|
|
c.wg.Wait()
|
|
log.Info("checkout cleanup stopped")
|
|
}
|
|
|
|
// cleanupLoop runs periodic cleanup.
|
|
func (c *CheckoutCleanup) cleanupLoop() {
|
|
defer c.wg.Done()
|
|
|
|
// Run immediately on start
|
|
c.runCleanup()
|
|
|
|
ticker := time.NewTicker(c.cleanupInterval)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-c.ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
c.runCleanup()
|
|
}
|
|
}
|
|
}
|
|
|
|
// runCleanup marks expired checkouts and revokes their tokens.
|
|
func (c *CheckoutCleanup) runCleanup() {
|
|
ctx, cancel := context.WithTimeout(c.ctx, TimeoutMaintenance)
|
|
defer cancel()
|
|
|
|
log := logging.FromContext(ctx).WithWorker("checkout-cleanup")
|
|
|
|
cleaned, err := c.service.CleanupExpired(ctx)
|
|
if err != nil {
|
|
log.Error("failed to cleanup expired checkouts",
|
|
logging.FieldError, err,
|
|
)
|
|
return
|
|
}
|
|
|
|
if cleaned > 0 {
|
|
log.Info("cleaned up expired checkouts",
|
|
"count", cleaned,
|
|
)
|
|
}
|
|
}
|