feat(ops): add job center for cross-source job operations

Provide a unified ops console for inspecting, retrying and cancelling
jobs across generation, template/kol assist, knowledge parse, desktop
publish/task, compliance review and monitoring collect sources. Wires
RabbitMQ for retry republish and consolidates the desktop_publish_jobs
columns into the base migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 12:56:39 +08:00
parent ab62d666b4
commit 7b4d7ccf68
13 changed files with 3043 additions and 12 deletions
+54
View File
@@ -25,6 +25,7 @@ type Config struct {
MonitoringDatabase sharedconfig.DatabaseConfig `mapstructure:"monitoring_database"`
Redis sharedconfig.RedisConfig `mapstructure:"redis"`
Cache sharedconfig.CacheConfig `mapstructure:"cache"`
RabbitMQ sharedconfig.RabbitMQConfig `mapstructure:"rabbitmq"`
Log sharedconfig.LogConfig `mapstructure:"log"`
JWT JWTConfig `mapstructure:"jwt"`
DefaultAdmin DefaultAdminConfig `mapstructure:"default_admin"`
@@ -232,6 +233,9 @@ func Diff(previous, current *Config) []FieldChange {
if previous.Cache != current.Cache {
add("cache", false)
}
if previous.RabbitMQ != current.RabbitMQ {
add("rabbitmq", false)
}
if previous.Log != current.Log {
add("log", false)
}
@@ -340,6 +344,7 @@ func normalizeConfig(cfg *Config) {
cfg.Cache.Driver = "redis"
}
sharedconfig.NormalizeCacheConfig(&cfg.Cache)
normalizeOpsRabbitMQConfig(&cfg.RabbitMQ)
if strings.TrimSpace(cfg.Log.Level) == "" {
cfg.Log.Level = "info"
}
@@ -374,6 +379,7 @@ func defaultSettings() map[string]any {
"cache": map[string]any{
"driver": "redis",
},
"rabbitmq": map[string]any{},
"log": map[string]any{
"level": "info",
"format": "json",
@@ -423,9 +429,57 @@ func applyEnvOverrides(cfg *Config) error {
if v := os.Getenv("OPS_SERVER_TRUSTED_PROXIES"); v != "" {
cfg.Server.TrustedProxies = strings.Split(v, ",")
}
if v := os.Getenv("OPS_RABBITMQ_URL"); v != "" {
cfg.RabbitMQ.URL = v
}
return nil
}
func normalizeOpsRabbitMQConfig(cfg *sharedconfig.RabbitMQConfig) {
if cfg == nil {
return
}
if strings.TrimSpace(cfg.GenerationExchange) == "" {
cfg.GenerationExchange = "generation.task"
}
if strings.TrimSpace(cfg.GenerationRoutingKey) == "" {
cfg.GenerationRoutingKey = "generation.task.run"
}
if strings.TrimSpace(cfg.DesktopTaskEventExchange) == "" {
cfg.DesktopTaskEventExchange = "desktop.task.event"
}
if strings.TrimSpace(cfg.DesktopDispatchExchange) == "" {
cfg.DesktopDispatchExchange = "desktop.task.dispatch"
}
if strings.TrimSpace(cfg.DesktopDispatchPublishPrefix) == "" {
cfg.DesktopDispatchPublishPrefix = "publish"
}
if strings.TrimSpace(cfg.DesktopDispatchMonitorPrefix) == "" {
cfg.DesktopDispatchMonitorPrefix = "monitor"
}
if strings.TrimSpace(cfg.TemplateAssistExchange) == "" {
cfg.TemplateAssistExchange = "template.assist"
}
if strings.TrimSpace(cfg.TemplateAssistRoutingKey) == "" {
cfg.TemplateAssistRoutingKey = "template.assist.run"
}
if strings.TrimSpace(cfg.KolAssistExchange) == "" {
cfg.KolAssistExchange = "kol.assist"
}
if strings.TrimSpace(cfg.KolAssistRoutingKey) == "" {
cfg.KolAssistRoutingKey = "kol.assist.run"
}
if strings.TrimSpace(cfg.ComplianceReviewExchange) == "" {
cfg.ComplianceReviewExchange = "compliance.review"
}
if strings.TrimSpace(cfg.ComplianceReviewRoutingKey) == "" {
cfg.ComplianceReviewRoutingKey = "compliance.review.run"
}
if cfg.PublishChannelPoolSize <= 0 {
cfg.PublishChannelPoolSize = 16
}
}
type fileSnapshot struct {
size int64
modTime time.Time