Relay current process output without spool

This commit is contained in:
npc0-hue
2026-08-31 23:35:14 +08:00
parent cde99e19fa
commit c8f5213954
9 changed files with 239 additions and 90 deletions
+17 -18
View File
@@ -205,11 +205,6 @@ func (supervisor *OSManagedProcessSupervisor) Start(ctx context.Context, command
identity.UpdatedAt = identity.StartedAt
identity.CommandFingerprint = fingerprintArgs(command.Args)
previous, hadPrevious := supervisor.items[key]
retiredKey := ""
if hadPrevious && supervisor.hasPendingOutput(previous) {
retiredKey = managedProcessGenerationKey(previous)
supervisor.retired[retiredKey] = previous
}
supervisor.items[key] = identity
if err := supervisor.persistLocked(); err != nil {
_ = forceManagedProcessStop(identity)
@@ -219,9 +214,6 @@ func (supervisor *OSManagedProcessSupervisor) Start(ctx context.Context, command
} else {
delete(supervisor.items, key)
}
if retiredKey != "" {
delete(supervisor.retired, retiredKey)
}
log.Printf("RUN phase=process.managed status=persist_failed job=%s pid=%d error=%s", safeOptional(identity.JobID), identity.PID, RedactText(err.Error()))
return ProcessIdentity{}, err
}
@@ -324,6 +316,8 @@ func (supervisor *OSManagedProcessSupervisor) ResumeOutput(output ManagedProcess
changed := false
for _, item := range supervisor.items {
if item.State == "running" && supervisor.isAlive(item) {
item.StdoutOffset = supervisor.outputFileSize(item.StdoutLogRef, item.StdoutOffset)
item.StderrOffset = supervisor.outputFileSize(item.StderrLogRef, item.StderrOffset)
item.State = "running"
item.ObservationSeq++
item.UpdatedAt = now
@@ -331,17 +325,9 @@ func (supervisor *OSManagedProcessSupervisor) ResumeOutput(output ManagedProcess
changed = true
supervisor.startTailersLocked(item, output)
log.Printf("RUN phase=process.managed status=resume_output pid=%d server=%s scope=%s", item.PID, item.ServerInstanceID, safeOptional(item.Scope))
} else if supervisor.hasPendingOutput(item) {
supervisor.startDrainTailersLocked(item, output)
log.Printf("RUN phase=process.managed status=resume_output_drain pid=%d server=%s scope=%s", item.PID, item.ServerInstanceID, safeOptional(item.Scope))
}
}
for key, item := range supervisor.retired {
if supervisor.hasPendingOutput(item) {
supervisor.startDrainTailersLocked(item, output)
log.Printf("RUN phase=process.managed status=resume_retired_output_drain pid=%d server=%s scope=%s", item.PID, item.ServerInstanceID, safeOptional(item.Scope))
continue
}
for key := range supervisor.retired {
delete(supervisor.retired, key)
changed = true
}
@@ -350,6 +336,17 @@ func (supervisor *OSManagedProcessSupervisor) ResumeOutput(output ManagedProcess
}
}
func (supervisor *OSManagedProcessSupervisor) outputFileSize(ref string, fallback int64) int64 {
if ref == "" {
return fallback
}
info, err := os.Stat(filepath.Join(supervisor.outputRoot, "state", "process-output", filepath.Base(ref)))
if err != nil || info.Size() < fallback {
return fallback
}
return info.Size()
}
func (supervisor *OSManagedProcessSupervisor) Reconcile() {
supervisor.mu.Lock()
defer supervisor.mu.Unlock()
@@ -361,7 +358,9 @@ func (supervisor *OSManagedProcessSupervisor) Reconcile() {
item.UpdatedAt = time.Now().UTC()
item.ObservationSeq++
supervisor.items[key] = item
supervisor.drainTailersLocked(item)
// A Run restart must never replay output produced before this
// process became observable again.
supervisor.stopTailersLocked(item)
changed = true
}
}