Never double-import a file into the engine: detail Transcribe bails when the pump already owns the file (in-flight check was absent there — mid-upload the mapping sidecar doesn't exist yet, so the upload path created a second server recording; happened live with Gambino Tahoe 11-50). Pump's transcribeFile reuses an existing mapping via /reprocess instead of uploading fresh (a pipeline killed mid-run no longer re-imports as a new recording on next pump). Purged the 11:08 orphan recording from the engine DB.

This commit is contained in:
avi 2026-09-17 13:38:01 -05:00
commit 26f7b273ce

View file

@ -673,6 +673,19 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
return false
}
return try {
// If an earlier pass ever uploaded this file, reuse that
// recording and re-run the pipeline in place. Uploading again
// would create a duplicate server recording (this is exactly
// how a file whose pipeline died mid-run got re-imported as a
// second row on the next pump).
val existing = loadMapping(f)?.recordingId
val refKey: String
if (existing != null) {
refKey = existing
runCatching {
provider.reprocess(existing, "transcribe")
} // 409 "already running" is fine: we adopt it by polling.
} else {
val draft = RecordingDraft(
id = UUID.randomUUID().toString(),
title = f.nameWithoutExtension,
@ -685,12 +698,14 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
)
val ref = provider.upload(draft) {}
saveMapping(f, RemoteMapping(ref.key))
refKey = ref.key
}
var jobs: List<JobInfo> = emptyList()
var polls = 0
while (polls < 600) { // up to ~30 min per file at 2s polls
polls++
delay(2000)
jobs = runCatching { parseJobs(provider.fetchJobs(ref.key)) }.getOrNull().orEmpty()
jobs = runCatching { parseJobs(provider.fetchJobs(refKey)) }.getOrNull().orEmpty()
setLive(f.name, jobProgress(jobs))
rescanStatuses()
val t = jobs.firstOrNull { it.jobType == "transcribe" }?.status
@ -702,9 +717,9 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
it.jobType == "transcribe" && it.status == "failed"
}
if (transcribeFailed) return false
val transcript = runCatching { parseTranscript(provider.fetchTranscript(ref.key)) }
val transcript = runCatching { parseTranscript(provider.fetchTranscript(refKey)) }
.getOrNull() ?: return false
val summary = runCatching { parseSummary(provider.fetchSummary(ref.key)) }.getOrNull()
val summary = runCatching { parseSummary(provider.fetchSummary(refKey)) }.getOrNull()
saveReport(DetailUi(file = f, transcript = transcript, summary = summary))
true
} catch (e: Exception) {
@ -1377,6 +1392,17 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
fun transcribe() {
val d = _detail.value ?: return
pollJob?.cancel()
// The pump (or a detail-run from elsewhere) already owns this
// file: never start a second pipeline for it. The upload path
// below creates a NEW server recording, and the mapping sidecar
// only exists once an upload completes — so mid-flight this is
// the only reliable dedup. Show the live row state instead.
if (d.file.name in inFlight || isRunning(d.file.name)) {
d.busy = _liveProgress.value[d.file.name]?.label ?: "Already queued…"
d.error = null
_detail.value = d.copy()
return
}
// A file with a known server recording re-runs the pipeline IN
// PLACE (the endpoint takes the model override too) — re-uploading
// would duplicate the recording server-side. Only never-uploaded