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:
parent
1f688e79bc
commit
26f7b273ce
1 changed files with 41 additions and 15 deletions
|
|
@ -673,6 +673,19 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return try {
|
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(
|
val draft = RecordingDraft(
|
||||||
id = UUID.randomUUID().toString(),
|
id = UUID.randomUUID().toString(),
|
||||||
title = f.nameWithoutExtension,
|
title = f.nameWithoutExtension,
|
||||||
|
|
@ -685,12 +698,14 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
||||||
)
|
)
|
||||||
val ref = provider.upload(draft) {}
|
val ref = provider.upload(draft) {}
|
||||||
saveMapping(f, RemoteMapping(ref.key))
|
saveMapping(f, RemoteMapping(ref.key))
|
||||||
|
refKey = ref.key
|
||||||
|
}
|
||||||
var jobs: List<JobInfo> = emptyList()
|
var jobs: List<JobInfo> = emptyList()
|
||||||
var polls = 0
|
var polls = 0
|
||||||
while (polls < 600) { // up to ~30 min per file at 2s polls
|
while (polls < 600) { // up to ~30 min per file at 2s polls
|
||||||
polls++
|
polls++
|
||||||
delay(2000)
|
delay(2000)
|
||||||
jobs = runCatching { parseJobs(provider.fetchJobs(ref.key)) }.getOrNull().orEmpty()
|
jobs = runCatching { parseJobs(provider.fetchJobs(refKey)) }.getOrNull().orEmpty()
|
||||||
setLive(f.name, jobProgress(jobs))
|
setLive(f.name, jobProgress(jobs))
|
||||||
rescanStatuses()
|
rescanStatuses()
|
||||||
val t = jobs.firstOrNull { it.jobType == "transcribe" }?.status
|
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"
|
it.jobType == "transcribe" && it.status == "failed"
|
||||||
}
|
}
|
||||||
if (transcribeFailed) return false
|
if (transcribeFailed) return false
|
||||||
val transcript = runCatching { parseTranscript(provider.fetchTranscript(ref.key)) }
|
val transcript = runCatching { parseTranscript(provider.fetchTranscript(refKey)) }
|
||||||
.getOrNull() ?: return false
|
.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))
|
saveReport(DetailUi(file = f, transcript = transcript, summary = summary))
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
@ -1377,6 +1392,17 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
|
||||||
fun transcribe() {
|
fun transcribe() {
|
||||||
val d = _detail.value ?: return
|
val d = _detail.value ?: return
|
||||||
pollJob?.cancel()
|
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
|
// A file with a known server recording re-runs the pipeline IN
|
||||||
// PLACE (the endpoint takes the model override too) — re-uploading
|
// PLACE (the endpoint takes the model override too) — re-uploading
|
||||||
// would duplicate the recording server-side. Only never-uploaded
|
// would duplicate the recording server-side. Only never-uploaded
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue