Skip to content

Commit fde2000

Browse files
committed
fix
1 parent 158de96 commit fde2000

File tree

1 file changed

+86
-16
lines changed

1 file changed

+86
-16
lines changed

supernode/transport/gateway/recovery_admin.go

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,31 @@ func (ra *recoveryAdmin) handleStatus(w http.ResponseWriter, r *http.Request, ac
364364
ctx := logtrace.CtxWithCorrelationID(r.Context(), actionID)
365365
ctx = logtrace.CtxWithOrigin(ctx, "recovery_status")
366366

367+
// "downloadable" semantics: action can be decoded now via normal download flow (network+local).
368+
downloadable, downloadErr, downloadEvents, downloadLastEvent, downloadedFilePath, downloadedDir, err := ra.checkDownloadable(ctx, actionID)
369+
if err != nil {
370+
writeJSON(w, http.StatusInternalServerError, map[string]any{"ok": false, "action_id": actionID, "error": err.Error()})
371+
return
372+
}
373+
367374
bundle, err := ra.resolveArtefactBundle(ctx, actionID)
368375
if err != nil {
369-
writeJSON(w, http.StatusOK, map[string]any{"ok": false, "action_id": actionID, "error": err.Error()})
376+
resp := map[string]any{
377+
"ok": false,
378+
"action_id": actionID,
379+
"downloadable": downloadable,
380+
"checked_supernode": ra.selfSupernode,
381+
"download_events": downloadEvents,
382+
"download_last_event": downloadLastEvent,
383+
"downloaded_file_path": downloadedFilePath,
384+
"downloaded_dir": downloadedDir,
385+
"duration_ms": time.Since(start).Milliseconds(),
386+
"error": err.Error(),
387+
}
388+
if downloadErr != "" {
389+
resp["download_error"] = downloadErr
390+
}
391+
writeJSON(w, http.StatusOK, resp)
370392
return
371393
}
372394

@@ -387,9 +409,9 @@ func (ra *recoveryAdmin) handleStatus(w http.ResponseWriter, r *http.Request, ac
387409
layoutMax := len(bundle.LayoutIDs)
388410
symbolMax := len(bundle.SymbolKeys)
389411
reachable := 0
390-
downloadable := false
391-
downloadableFrom := ""
392-
downloadableFromAll := make([]string, 0, 4)
412+
fullCopyAvailable := false
413+
fullCopyFrom := ""
414+
fullCopyFromAll := make([]string, 0, 4)
393415
dist := make([]map[string]any, 0, len(results))
394416
for _, pr := range results {
395417
if pr.OK {
@@ -400,11 +422,11 @@ func (ra *recoveryAdmin) handleStatus(w http.ResponseWriter, r *http.Request, ac
400422
pr.LayoutFilesPresent == layoutMax &&
401423
pr.SymbolsPresent == symbolMax
402424
if complete {
403-
if !downloadable {
404-
downloadableFrom = pr.Target.SupernodeAddress
425+
if !fullCopyAvailable {
426+
fullCopyFrom = pr.Target.SupernodeAddress
405427
}
406-
downloadable = true
407-
downloadableFromAll = append(downloadableFromAll, pr.Target.SupernodeAddress)
428+
fullCopyAvailable = true
429+
fullCopyFromAll = append(fullCopyFromAll, pr.Target.SupernodeAddress)
408430
}
409431
dist = append(dist, map[string]any{
410432
"supernode_address": pr.Target.SupernodeAddress,
@@ -420,12 +442,35 @@ func (ra *recoveryAdmin) handleStatus(w http.ResponseWriter, r *http.Request, ac
420442
}
421443

422444
writeJSON(w, http.StatusOK, map[string]any{
423-
"ok": true,
424-
"action_id": actionID,
425-
"duration_ms": time.Since(start).Milliseconds(),
426-
"downloadable": downloadable,
427-
"downloadable_from_supernode": downloadableFrom,
428-
"downloadable_from_supernodes": downloadableFromAll,
445+
"ok": true,
446+
"action_id": actionID,
447+
"duration_ms": time.Since(start).Milliseconds(),
448+
"downloadable": downloadable,
449+
"downloadable_from_supernode": func() string {
450+
if downloadable {
451+
return ra.selfSupernode
452+
}
453+
return ""
454+
}(),
455+
"downloadable_from_supernodes": func() []string {
456+
if downloadable {
457+
return []string{ra.selfSupernode}
458+
}
459+
return []string{}
460+
}(),
461+
"download_events": downloadEvents,
462+
"download_last_event": downloadLastEvent,
463+
"download_error": downloadErr,
464+
"downloaded_file_path": downloadedFilePath,
465+
"downloaded_dir": downloadedDir,
466+
"full_copy_available": fullCopyAvailable,
467+
"full_copy_from_supernode": func() string {
468+
if fullCopyAvailable {
469+
return fullCopyFrom
470+
}
471+
return ""
472+
}(),
473+
"full_copy_from_supernodes": fullCopyFromAll,
429474
"totals": map[string]any{
430475
"index_files_total": indexMax,
431476
"layout_files_total": layoutMax,
@@ -440,6 +485,31 @@ func (ra *recoveryAdmin) handleStatus(w http.ResponseWriter, r *http.Request, ac
440485
})
441486
}
442487

488+
func (ra *recoveryAdmin) checkDownloadable(ctx context.Context, actionID string) (ok bool, downloadErr string, events int, lastEvent string, downloadedFilePath string, downloadedDir string, err error) {
489+
task := ra.cascadeFactory.NewCascadeRegistrationTask()
490+
crt, castOK := task.(*cascadeService.CascadeRegistrationTask)
491+
if !castOK {
492+
return false, "", 0, "", "", "", fmt.Errorf("unexpected task type")
493+
}
494+
495+
dlErr := crt.Download(ctx, &cascadeService.DownloadRequest{
496+
ActionID: actionID,
497+
BypassPrivateSignature: true,
498+
}, func(resp *cascadeService.DownloadResponse) error {
499+
events++
500+
lastEvent = fmt.Sprintf("%d:%s", resp.EventType, resp.Message)
501+
if resp.EventType == cascadeService.SupernodeEventTypeDecodeCompleted {
502+
downloadedDir = resp.DownloadedDir
503+
downloadedFilePath = resp.FilePath
504+
}
505+
return nil
506+
})
507+
if dlErr != nil {
508+
return false, dlErr.Error(), events, lastEvent, downloadedFilePath, downloadedDir, nil
509+
}
510+
return true, "", events, lastEvent, downloadedFilePath, downloadedDir, nil
511+
}
512+
443513
func (ra *recoveryAdmin) handleInternalProbe(w http.ResponseWriter, r *http.Request) {
444514
if r.Method != http.MethodPost {
445515
writeJSON(w, http.StatusMethodNotAllowed, map[string]any{"ok": false, "error": "method not allowed"})
@@ -562,13 +632,13 @@ func (ra *recoveryAdmin) resolveArtefactBundle(ctx context.Context, actionID str
562632
return artefactBundle{}, fmt.Errorf("parse layout_id %s: %v", lid, perr)
563633
}
564634
for _, blk := range layout.Blocks {
565-
prefix := fmt.Sprintf("block_%d", blk.BlockID)
566635
for _, sid := range blk.Symbols {
567636
sid = strings.TrimSpace(sid)
568637
if sid == "" {
569638
continue
570639
}
571-
symbolSet[prefix+"/"+sid] = struct{}{}
640+
// DHT symbol keys are raw symbol IDs (base58), not path-like block prefixes.
641+
symbolSet[sid] = struct{}{}
572642
}
573643
}
574644
}

0 commit comments

Comments
 (0)