fix(scan): Fix-mode scanner + dialog suppression + cancel/timer + importer revive
Build backend images / build content-svc (push) Failing after 1m25s
Build backend images / build file-svc (push) Failing after 1m10s
Build backend images / build gateway (push) Failing after 56s
Build backend images / build identity-svc (push) Failing after 53s
Build backend images / build notification-svc (push) Failing after 57s
Build backend images / build render-svc (push) Failing after 48s
Build backend images / build studio-svc (push) Failing after 1m5s

- scan.jsx: app.beginSuppressDialogs() + clean quit (no AE hang on font/footage
  dialogs); FIX-mode branch parses frl_c(x)t/m(y) layer names → scenes by c(x);
  flexible/mockup keep comp-based walk; FR_SCAN_MODE selects.
- render-svc: scan job carries project mode; cancel endpoint + node watchdog that
  kills AE on cancel; parseObjectURL handles minio:// (bucket in host); scan with
  no template fails cleanly; status guards so late results can't un-cancel.
- content importer: revive soft-deleted scenes instead of duplicate-inserting
  (fixes scenes_project_id_key unique violation); orphan diff ignores deleted.
- admin: scan dialog gets project-type picker + elapsed timer + Cancel button.
- node-agent: AE-2026 wiring (host port 5010, host-reachable presign endpoint),
  FR_SCAN_MODE plumbing. docs/aep-template-convention.md: per-type naming + bundles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-04 19:06:08 +03:30
parent ee670552a8
commit 6661f53734
17 changed files with 498 additions and 45 deletions
@@ -250,6 +250,7 @@ func (c *Client) ClaimJob(ctx context.Context, nodeID, region string) (*ClaimedJ
type ScanClaim struct {
ScanJobID string `json:"scan_job_id"`
ProjectID string `json:"project_id"`
Mode string `json:"mode"` // fix | flexible | mockup | musicvisualizer
AEPDownloadURL string `json:"aep_download_url"`
IsBundle bool `json:"is_bundle"`
BundleMD5 string `json:"bundle_md5"`
@@ -306,6 +307,23 @@ func (c *Client) ReportScanFail(ctx context.Context, scanJobID, reason string) e
return nil
}
// ScanStatus returns the scan job's current status (for the cancel watchdog).
func (c *Client) ScanStatus(ctx context.Context, scanJobID string) (string, error) {
resp, err := c.do(ctx, http.MethodGet, fmt.Sprintf("/v1/internal/scan/%s/status", scanJobID), nil)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
return "", fmt.Errorf("scan status: HTTP %d", resp.StatusCode)
}
var out struct {
Status string `json:"status"`
}
_ = json.NewDecoder(resp.Body).Decode(&out)
return out.Status, nil
}
// UpdatePreview sends a base64-encoded preview frame to the orchestrator.
// Errors are non-fatal — the UI simply won't update the preview image.
func (c *Client) UpdatePreview(ctx context.Context, jobID, imageB64 string) error {