feat: make MediaCleaner configurable via tools.media_cleanup
Add MediaCleanupConfig with enabled, max_age_minutes, and interval_minutes fields. MediaCleaner is only started when enabled (default: true) and logs its effective settings at startup. Defaults: interval=5m, max_age=30m. Operators can tune or disable cleanup for deployments with longer async processing times. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
81df10b0b1
commit
f0484cb6df
5 changed files with 43 additions and 15 deletions
|
|
@ -193,8 +193,14 @@ func gatewayCmd() {
|
||||||
fmt.Println("✓ Device event service started")
|
fmt.Println("✓ Device event service started")
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaCleaner := utils.NewMediaCleaner()
|
if cfg.Tools.MediaCleanup.Enabled {
|
||||||
mediaCleaner.Start()
|
mediaCleaner := utils.NewMediaCleaner(
|
||||||
|
cfg.Tools.MediaCleanup.Interval,
|
||||||
|
cfg.Tools.MediaCleanup.MaxAge,
|
||||||
|
)
|
||||||
|
mediaCleaner.Start()
|
||||||
|
defer mediaCleaner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
if err := channelManager.StartAll(ctx); err != nil {
|
if err := channelManager.StartAll(ctx); err != nil {
|
||||||
fmt.Printf("Error starting channels: %v\n", err)
|
fmt.Printf("Error starting channels: %v\n", err)
|
||||||
|
|
@ -220,7 +226,6 @@ func gatewayCmd() {
|
||||||
deviceService.Stop()
|
deviceService.Stop()
|
||||||
heartbeatService.Stop()
|
heartbeatService.Stop()
|
||||||
cronService.Stop()
|
cronService.Stop()
|
||||||
mediaCleaner.Stop()
|
|
||||||
agentLoop.Stop()
|
agentLoop.Stop()
|
||||||
channelManager.StopAll(ctx)
|
channelManager.StopAll(ctx)
|
||||||
fmt.Println("✓ Gateway stopped")
|
fmt.Println("✓ Gateway stopped")
|
||||||
|
|
|
||||||
|
|
@ -452,11 +452,18 @@ type ExecConfig struct {
|
||||||
CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"`
|
CustomDenyPatterns []string `json:"custom_deny_patterns" env:"PICOCLAW_TOOLS_EXEC_CUSTOM_DENY_PATTERNS"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MediaCleanupConfig struct {
|
||||||
|
Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_MEDIA_CLEANUP_ENABLED"`
|
||||||
|
MaxAge int `json:"max_age_minutes" env:"PICOCLAW_TOOLS_MEDIA_CLEANUP_MAX_AGE_MINUTES"`
|
||||||
|
Interval int `json:"interval_minutes" env:"PICOCLAW_TOOLS_MEDIA_CLEANUP_INTERVAL_MINUTES"`
|
||||||
|
}
|
||||||
|
|
||||||
type ToolsConfig struct {
|
type ToolsConfig struct {
|
||||||
Web WebToolsConfig `json:"web"`
|
Web WebToolsConfig `json:"web"`
|
||||||
Cron CronToolsConfig `json:"cron"`
|
Cron CronToolsConfig `json:"cron"`
|
||||||
Exec ExecConfig `json:"exec"`
|
Exec ExecConfig `json:"exec"`
|
||||||
Skills SkillsToolsConfig `json:"skills"`
|
Skills SkillsToolsConfig `json:"skills"`
|
||||||
|
MediaCleanup MediaCleanupConfig `json:"media_cleanup"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SkillsToolsConfig struct {
|
type SkillsToolsConfig struct {
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,11 @@ func DefaultConfig() *Config {
|
||||||
TTLSeconds: 300,
|
TTLSeconds: 300,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
MediaCleanup: MediaCleanupConfig{
|
||||||
|
Enabled: true,
|
||||||
|
MaxAge: 30,
|
||||||
|
Interval: 5,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Heartbeat: HeartbeatConfig{
|
Heartbeat: HeartbeatConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
|
|
||||||
|
|
@ -154,12 +154,20 @@ type MediaCleaner struct {
|
||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMediaCleaner creates a new MediaCleaner with default settings
|
// NewMediaCleaner creates a new MediaCleaner with the given settings.
|
||||||
// (scan every 5 minutes, remove files older than 30 minutes).
|
// If intervalMinutes or maxAgeMinutes are <= 0, defaults are used (5 and 30 respectively).
|
||||||
func NewMediaCleaner() *MediaCleaner {
|
func NewMediaCleaner(intervalMinutes, maxAgeMinutes int) *MediaCleaner {
|
||||||
|
interval := time.Duration(intervalMinutes) * time.Minute
|
||||||
|
if interval <= 0 {
|
||||||
|
interval = 5 * time.Minute
|
||||||
|
}
|
||||||
|
maxAge := time.Duration(maxAgeMinutes) * time.Minute
|
||||||
|
if maxAge <= 0 {
|
||||||
|
maxAge = 30 * time.Minute
|
||||||
|
}
|
||||||
return &MediaCleaner{
|
return &MediaCleaner{
|
||||||
interval: 5 * time.Minute,
|
interval: interval,
|
||||||
maxAge: 30 * time.Minute,
|
maxAge: maxAge,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +176,10 @@ func NewMediaCleaner() *MediaCleaner {
|
||||||
func (mc *MediaCleaner) Start() {
|
func (mc *MediaCleaner) Start() {
|
||||||
mc.once.Do(func() {
|
mc.once.Do(func() {
|
||||||
go mc.loop()
|
go mc.loop()
|
||||||
logger.InfoC("media", "Media cleaner started")
|
logger.InfoCF("media", "Media cleaner started", map[string]any{
|
||||||
|
"interval": mc.interval.String(),
|
||||||
|
"max_age": mc.maxAge.String(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func TestMediaCleanerRemovesOldFiles(t *testing.T) {
|
||||||
defer os.Remove(newFile)
|
defer os.Remove(newFile)
|
||||||
|
|
||||||
// Run cleanup directly
|
// Run cleanup directly
|
||||||
mc := NewMediaCleaner()
|
mc := NewMediaCleaner(5, 30)
|
||||||
mc.cleanup()
|
mc.cleanup()
|
||||||
|
|
||||||
// Old file should be gone
|
// Old file should be gone
|
||||||
|
|
@ -50,7 +50,7 @@ func TestMediaCleanerRemovesOldFiles(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMediaCleanerStartStop(t *testing.T) {
|
func TestMediaCleanerStartStop(t *testing.T) {
|
||||||
mc := NewMediaCleaner()
|
mc := NewMediaCleaner(5, 30)
|
||||||
|
|
||||||
// Start should not panic
|
// Start should not panic
|
||||||
mc.Start()
|
mc.Start()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue