Recover from a job killed by a deploy, and show when a cut reorders

cuts_state is set before the thread starts and cleared when it finishes, so
a deploy in between left the page waiting forever on work that was no longer
running, with the retry button hidden. Fifteen minutes is longer than the
work can legitimately take.

A cut may reorder as well as drop, which changes what it is - worth saying
rather than leaving the reader to spot it in the id list.
This commit is contained in:
gator 2026-09-17 12:51:27 +00:00
parent 8a3e257637
commit efa861f227

View file

@ -332,7 +332,7 @@
+ 'Each other model reads ONLY this script - no book - and says what it understood.">' + 'Each other model reads ONLY this script - no book - and says what it understood.">'
+ (REVIEWS.length ? "Test it again" : "Does it make sense? Ask " + others + " readers") + (REVIEWS.length ? "Test it again" : "Does it make sense? Ask " + others + " readers")
+ '</button>'); + '</button>');
if ((PKG.shots || []).length >= 6 && String(PKG.cuts_state || "") !== "thinking") if ((PKG.shots || []).length >= 6 && !busyCuts())
out.push('<button type="button" class="btn" data-cuts="' + esc(meta.id) out.push('<button type="button" class="btn" data-cuts="' + esc(meta.id)
+ '" title="Several shorter versions of what is already filmed. ' + '" title="Several shorter versions of what is already filmed. '
+ 'Costs nothing to propose or to watch.">' + 'Costs nothing to propose or to watch.">'
@ -367,6 +367,14 @@
return out.join(""); return out.join("");
} }
// A cut may move shots as well as drop them, which makes it a different
// film rather than a shorter one. Worth saying out loud.
function reordered(ids) {
var a = (ids || []).map(String);
var b = a.slice().sort();
return a.join("") !== b.join("");
}
function mmss(n) { function mmss(n) {
return Math.floor(n / 60) + ":" + String(Math.round(n % 60)).padStart(2, "0"); return Math.floor(n / 60) + ":" + String(Math.round(n % 60)).padStart(2, "0");
} }
@ -392,6 +400,16 @@
+ (worst && over > 5 ? "<ul>" + worst + "</ul>" : "") + "</div>"; + (worst && over > 5 ? "<ul>" + worst + "</ul>" : "") + "</div>";
} }
// A job lives in the worker's memory and dies with it. Every deploy kills
// one, and the flag it set stays set, so anything older than this is treated
// as gone rather than leaving the page waiting on it for ever.
function busyCuts() {
if (String(PKG.cuts_state || "") !== "thinking") return false;
var t = Date.parse(PKG.cuts_started || "");
if (!t) return false;
return (Date.now() - t) < 15 * 60 * 1000;
}
// A cut is an ordering, not a render. Playing one is free, so all of them // A cut is an ordering, not a render. Playing one is free, so all of them
// can be looked at before anything is joined into a file. // can be looked at before anything is joined into a file.
function cutsHtml(meta) { function cutsHtml(meta) {
@ -406,7 +424,9 @@
+ 'the question is not “what is the right length” but “which ' + 'the question is not “what is the right length” but “which '
+ 'version do people watch to the end”.</p>'; + 'version do people watch to the end”.</p>';
if (st === "thinking") out += '<p class="busy">Working out what to drop…</p>'; if (busyCuts()) out += '<p class="busy">Working out what to drop…</p>';
else if (st === "thinking") out += '<p class="cont">The last attempt stopped '
+ 'before it finished — the server restarted under it. Ask again.</p>';
else if (/^failed/.test(st)) out += '<p class="cont">' + esc(st) + '</p>'; else if (/^failed/.test(st)) out += '<p class="cont">' + esc(st) + '</p>';
out += cuts.map(function (c) { out += cuts.map(function (c) {
@ -435,7 +455,8 @@
+ (stat ? '<p class="stat">' + stat.views + ' viewer' + (stat ? '<p class="stat">' + stat.views + ' viewer'
+ (stat.views === 1 ? '' : 's') + ' · median ' + stat.median_percent + (stat.views === 1 ? '' : 's') + ' · median ' + stat.median_percent
+ '% watched · ' + stat.completion_rate + '% reached the end</p>' : '') + '% watched · ' + stat.completion_rate + '% reached the end</p>' : '')
+ '<p class="ids">' + esc((c.shot_ids || []).join(" ")) + '</p>' + '<p class="ids">' + esc((c.shot_ids || []).join(" "))
+ (reordered(c.shot_ids) ? ' &middot; reordered' : '') + '</p>'
+ '<div class="tools">' + tools + '</div>' + play + '</div>'; + '<div class="tools">' + tools + '</div>' + play + '</div>';
}).join(""); }).join("");