package processing import ( "fmt" "strconv" "strings" ) // Stable job.error message keys. UI translates via i18n (processing.job.error.*). // Wire format: "key|count=N" so older clients still show a readable string. const ( JobErrAllFailedKey = "processing.job.error.all_failed" JobErrPartialFailedKey = "processing.job.error.partial_failed" ) // IsProcessableJobStatus reports whether ProcessJob may run work for this status. // Terminal statuses (completed/cancelled/failed) are no-ops — use RetryJob to requeue. func IsProcessableJobStatus(status string) bool { switch strings.ToLower(strings.TrimSpace(status)) { case "pending", "running": return true default: return false } } // FormatJobUserError builds a translatable job.error payload with a count param. func FormatJobUserError(key string, count int) string { if count < 0 { count = 0 } return fmt.Sprintf("%s|count=%d", key, count) } // ParseJobUserError extracts key + count from FormatJobUserError (or returns raw, 0, false). func ParseJobUserError(raw string) (key string, count int, ok bool) { raw = strings.TrimSpace(raw) if raw == "" { return "", 0, false } key, rest, found := strings.Cut(raw, "|count=") if !found { return "", 0, false } key = strings.TrimSpace(key) if key == "" { return "", 0, false } n, err := strconv.Atoi(strings.TrimSpace(rest)) if err != nil { return "", 0, false } return key, n, true }