nsfwapp/backend/tasks_release_file.go
2026-04-09 12:48:17 +02:00

216 lines
4.6 KiB
Go

// backend\tasks_release_file.go
package main
import (
"encoding/json"
"net/http"
"path/filepath"
"strings"
"time"
)
type releaseFileTasksRequest struct {
File string `json:"file"`
}
type releaseFileTasksResponse struct {
OK bool `json:"ok"`
File string `json:"file"`
ReleasedAny bool `json:"releasedAny"`
AssetsTaskCancelled bool `json:"assetsTaskCancelled"`
RegenerateCancelled bool `json:"regenerateCancelled"`
PostworkCancelled bool `json:"postworkCancelled"`
EnrichCancelled bool `json:"enrichCancelled"`
}
func assetIDFromAnyFileName(file string) string {
base := strings.TrimSpace(filepath.Base(strings.TrimSpace(file)))
if base == "" {
return ""
}
stem := strings.TrimSuffix(base, filepath.Ext(base))
return strings.TrimSpace(stripHotPrefix(stem))
}
func sameBaseFile(a, b string) bool {
aa := strings.TrimSpace(filepath.Base(strings.TrimSpace(a)))
bb := strings.TrimSpace(filepath.Base(strings.TrimSpace(b)))
if aa == "" || bb == "" {
return false
}
return strings.EqualFold(aa, bb)
}
func cancelAssetsTaskForFile(file string) bool {
assetsTaskMu.Lock()
cancel := assetsTaskCancel
running := assetsTaskState.Running
currentFile := assetsTaskState.CurrentFile
assetsTaskMu.Unlock()
if !running || cancel == nil {
return false
}
if !sameBaseFile(currentFile, file) {
return false
}
cancel()
return true
}
func cancelRegenerateAssetsTaskForFile(file string) bool {
regenerateAssetsMu.Lock()
var matched []*regenerateAssetsJob
for _, job := range regenerateAssetsJobs {
if job == nil {
continue
}
if !sameBaseFile(job.File, file) {
continue
}
matched = append(matched, job)
}
regenerateAssetsMu.Unlock()
cancelled := false
for _, job := range matched {
if job != nil && job.Cancel != nil {
job.Cancel()
cancelled = true
}
}
return cancelled
}
func cancelQueuesForFile(file string) (postworkCancelled bool, enrichCancelled bool) {
file = strings.TrimSpace(file)
// 1) Direkt aus Dateiname ableiten:
// Für laufende Sprites ist das meistens der relevante Queue-Key.
if assetID := assetIDFromAnyFileName(file); assetID != "" {
enrichKey := "enrich:" + assetID
if enrichQ.Cancel(enrichKey) {
enrichCancelled = true
}
if enrichQ.RemoveQueued(enrichKey) {
enrichCancelled = true
}
clearEnrichStatusSnapshot(enrichKey)
}
// 2) Zusätzlich wie bisher über jobs suchen
type queueKeys struct {
postworkKey string
enrichKey string
}
matches := make([]queueKeys, 0, 8)
jobsMu.RLock()
for _, job := range jobs {
if job == nil {
continue
}
if !sameBaseFile(job.Output, file) {
continue
}
postworkKey := strings.TrimSpace(job.PostWorkKey)
enrichKey := ""
if id := strings.TrimSpace(assetIDForJob(job)); id != "" {
enrichKey = "enrich:" + id
}
matches = append(matches, queueKeys{
postworkKey: postworkKey,
enrichKey: enrichKey,
})
}
jobsMu.RUnlock()
for _, item := range matches {
if item.postworkKey != "" {
if postWorkQ.Cancel(item.postworkKey) {
postworkCancelled = true
}
if postWorkQ.RemoveQueued(item.postworkKey) {
postworkCancelled = true
}
}
if item.enrichKey != "" {
if enrichQ.Cancel(item.enrichKey) {
enrichCancelled = true
}
if enrichQ.RemoveQueued(item.enrichKey) {
enrichCancelled = true
}
clearEnrichStatusSnapshot(item.enrichKey)
}
}
return postworkCancelled, enrichCancelled
}
func releaseFileTasks(file string) releaseFileTasksResponse {
file = strings.TrimSpace(file)
resp := releaseFileTasksResponse{
OK: true,
File: file,
}
if file == "" {
return resp
}
resp.AssetsTaskCancelled = cancelAssetsTaskForFile(file)
resp.RegenerateCancelled = cancelRegenerateAssetsTaskForFile(file)
resp.PostworkCancelled, resp.EnrichCancelled = cancelQueuesForFile(file)
resp.ReleasedAny =
resp.AssetsTaskCancelled ||
resp.RegenerateCancelled ||
resp.PostworkCancelled ||
resp.EnrichCancelled
// ffmpeg / Analyse / Sprite-Generierung einen Moment zum Beenden geben
if resp.ReleasedAny {
time.Sleep(900 * time.Millisecond)
}
return resp
}
func handleReleaseFileTasks(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Nur POST erlaubt", http.StatusMethodNotAllowed)
return
}
var req releaseFileTasksRequest
if r.Body != nil {
_ = json.NewDecoder(r.Body).Decode(&req)
}
file := strings.TrimSpace(req.File)
if file == "" {
file = strings.TrimSpace(r.URL.Query().Get("file"))
}
if file == "" {
http.Error(w, "file fehlt", http.StatusBadRequest)
return
}
writeJSON(w, http.StatusOK, releaseFileTasks(file))
}