0.12.0-12 Job Fix

This commit is contained in:
2026-03-23 08:55:36 +00:00
parent a66c3bfdb6
commit 56f8133589
9 changed files with 93 additions and 43 deletions
+3 -1
View File
@@ -24,7 +24,9 @@
"Bash(lsblk -o NAME,TYPE,MODEL)", "Bash(lsblk -o NAME,TYPE,MODEL)",
"Bash(node --check /home/michael/ripster/backend/src/routes/pipelineRoutes.js)", "Bash(node --check /home/michael/ripster/backend/src/routes/pipelineRoutes.js)",
"Bash(grep -n \"inferMediaProfile\" /home/michael/ripster/backend/src/services/*.js)", "Bash(grep -n \"inferMediaProfile\" /home/michael/ripster/backend/src/services/*.js)",
"Bash(grep -rn \"PROCESS_LOG\\\\|LOG_UPDATE\\\\|processLog\" /home/michael/ripster/backend/src --include=*.js)" "Bash(grep -rn \"PROCESS_LOG\\\\|LOG_UPDATE\\\\|processLog\" /home/michael/ripster/backend/src --include=*.js)",
"Bash(grep -n \"buildHandBrakeConfig\" /home/michael/ripster/backend/src/services/*.js)",
"Bash(grep -n \"class.*Plugin\\\\|get id\\(\\)\\\\|get name\\(\\)\" /home/michael/ripster/backend/src/plugins/*.js)"
] ]
} }
} }
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "ripster-backend", "name": "ripster-backend",
"version": "0.12.0-11", "version": "0.12.0-12",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ripster-backend", "name": "ripster-backend",
"version": "0.12.0-11", "version": "0.12.0-12",
"dependencies": { "dependencies": {
"archiver": "^7.0.1", "archiver": "^7.0.1",
"cors": "^2.8.5", "cors": "^2.8.5",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ripster-backend", "name": "ripster-backend",
"version": "0.12.0-11", "version": "0.12.0-12",
"private": true, "private": true,
"type": "commonjs", "type": "commonjs",
"scripts": { "scripts": {
+59 -22
View File
@@ -8187,17 +8187,18 @@ class PipelineService extends EventEmitter {
} }
const hasEncodableTitle = Boolean(review.encodeInputPath && review.encodeInputTitleId); const hasEncodableTitle = Boolean(review.encodeInputPath && review.encodeInputTitleId);
const readyStatusText = review.titleSelectionRequired
? 'Titel-/Spurprüfung fertig - Titel per Checkbox wählen'
: (hasEncodableTitle
? 'Titel-/Spurprüfung fertig - Auswahl bestätigen, dann Encode manuell starten'
: 'Titel-/Spurprüfung fertig - kein Titel erfüllt MIN_LENGTH_MINUTES');
if (this.isPrimaryJob(jobId)) { if (this.isPrimaryJob(jobId)) {
const mergedPluginExecutionForReady = getMergedReviewPluginExecution(); const mergedPluginExecutionForReady = getMergedReviewPluginExecution();
await this.setState('READY_TO_ENCODE', { await this.setState('READY_TO_ENCODE', {
activeJobId: jobId, activeJobId: jobId,
progress: 0, progress: 0,
eta: null, eta: null,
statusText: review.titleSelectionRequired statusText: readyStatusText,
? 'Titel-/Spurprüfung fertig - Titel per Checkbox wählen'
: (hasEncodableTitle
? 'Titel-/Spurprüfung fertig - Auswahl bestätigen, dann Encode manuell starten'
: 'Titel-/Spurprüfung fertig - kein Titel erfüllt MIN_LENGTH_MINUTES'),
context: { context: {
...(this.snapshot.context || {}), ...(this.snapshot.context || {}),
jobId, jobId,
@@ -8218,6 +8219,26 @@ class PipelineService extends EventEmitter {
...(mergedPluginExecutionForReady ? { pluginExecution: mergedPluginExecutionForReady } : {}) ...(mergedPluginExecutionForReady ? { pluginExecution: mergedPluginExecutionForReady } : {})
} }
}); });
} else {
await this.updateProgress('READY_TO_ENCODE', 0, null, readyStatusText, jobId, {
contextPatch: {
jobId,
rawPath,
inputPath: review.encodeInputPath || null,
hasEncodableTitle,
reviewConfirmed: false,
mode,
mediaProfile,
sourceJobId: options.sourceJobId || null,
mediaInfoReview: review,
selectedMetadata,
playlistAnalysis: playlistAnalysis || null,
playlistDecisionRequired,
playlistCandidates,
selectedPlaylist: resolvedPlaylistId || null,
selectedTitleId: selectedTitleForReview
}
});
} }
void this.notifyPushover('metadata_ready', { void this.notifyPushover('metadata_ready', {
@@ -10164,13 +10185,8 @@ class PipelineService extends EventEmitter {
'SYSTEM', 'SYSTEM',
`HandBrake DVD Titelauswahl erforderlich: ${titleCandidates.length} Kandidaten. Nutzer muss Titel wählen.` `HandBrake DVD Titelauswahl erforderlich: ${titleCandidates.length} Kandidaten. Nutzer muss Titel wählen.`
); );
if (this.isPrimaryJob(jobId)) { const dvdWaitingStatusText = `DVD Titelauswahl: ${titleCandidates.length} Kandidaten gefunden`;
await this.setState('WAITING_FOR_USER_DECISION', { const dvdWaitingContextPatch = {
activeJobId: jobId,
progress: 0,
eta: null,
statusText: `DVD Titelauswahl: ${titleCandidates.length} Kandidaten gefunden`,
context: {
jobId, jobId,
rawPath, rawPath,
handBrakeTitleDecisionRequired: true, handBrakeTitleDecisionRequired: true,
@@ -10181,10 +10197,23 @@ class PipelineService extends EventEmitter {
mediaProfile, mediaProfile,
sourceJobId: options.sourceJobId || null, sourceJobId: options.sourceJobId || null,
mediaInfoReview: enrichedReview, mediaInfoReview: enrichedReview,
selectedMetadata, selectedMetadata
};
if (this.isPrimaryJob(jobId)) {
await this.setState('WAITING_FOR_USER_DECISION', {
activeJobId: jobId,
progress: 0,
eta: null,
statusText: dvdWaitingStatusText,
context: {
...dvdWaitingContextPatch,
...(reviewPluginExecution ? { pluginExecution: this.mergePluginExecutionState(mkInfo?.pluginExecution, reviewPluginExecution) } : {}) ...(reviewPluginExecution ? { pluginExecution: this.mergePluginExecutionState(mkInfo?.pluginExecution, reviewPluginExecution) } : {})
} }
}); });
} else {
await this.updateProgress('WAITING_FOR_USER_DECISION', 0, null, dvdWaitingStatusText, jobId, {
contextPatch: dvdWaitingContextPatch
});
} }
void this.notifyPushover('metadata_ready', { void this.notifyPushover('metadata_ready', {
title: 'Ripster - DVD Titelauswahl', title: 'Ripster - DVD Titelauswahl',
@@ -10247,17 +10276,12 @@ class PipelineService extends EventEmitter {
); );
} }
if (this.isPrimaryJob(jobId)) { const mediainfoReadyStatusText = titleSelectionRequired
await this.setState('READY_TO_ENCODE', {
activeJobId: jobId,
progress: 0,
eta: null,
statusText: titleSelectionRequired
? 'Mediainfo geprüft - Titelauswahl per Checkbox erforderlich' ? 'Mediainfo geprüft - Titelauswahl per Checkbox erforderlich'
: (hasEncodableTitle : (hasEncodableTitle
? 'Mediainfo geprüft - Encode manuell starten' ? 'Mediainfo geprüft - Encode manuell starten'
: 'Mediainfo geprüft - kein Titel erfüllt MIN_LENGTH_MINUTES'), : 'Mediainfo geprüft - kein Titel erfüllt MIN_LENGTH_MINUTES');
context: { const mediainfoReadyContextPatch = {
jobId, jobId,
rawPath, rawPath,
inputPath: enrichedReview.encodeInputPath || null, inputPath: enrichedReview.encodeInputPath || null,
@@ -10267,10 +10291,23 @@ class PipelineService extends EventEmitter {
mediaProfile, mediaProfile,
sourceJobId: options.sourceJobId || null, sourceJobId: options.sourceJobId || null,
mediaInfoReview: enrichedReview, mediaInfoReview: enrichedReview,
selectedMetadata, selectedMetadata
};
if (this.isPrimaryJob(jobId)) {
await this.setState('READY_TO_ENCODE', {
activeJobId: jobId,
progress: 0,
eta: null,
statusText: mediainfoReadyStatusText,
context: {
...mediainfoReadyContextPatch,
...(reviewPluginExecution ? { pluginExecution: this.mergePluginExecutionState(mkInfo?.pluginExecution, reviewPluginExecution) } : {}) ...(reviewPluginExecution ? { pluginExecution: this.mergePluginExecutionState(mkInfo?.pluginExecution, reviewPluginExecution) } : {})
} }
}); });
} else {
await this.updateProgress('READY_TO_ENCODE', 0, null, mediainfoReadyStatusText, jobId, {
contextPatch: mediainfoReadyContextPatch
});
} }
void this.notifyPushover('metadata_ready', { void this.notifyPushover('metadata_ready', {
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "ripster-frontend", "name": "ripster-frontend",
"version": "0.12.0-11", "version": "0.12.0-12",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ripster-frontend", "name": "ripster-frontend",
"version": "0.12.0-11", "version": "0.12.0-12",
"dependencies": { "dependencies": {
"primeicons": "^7.0.0", "primeicons": "^7.0.0",
"primereact": "^10.9.2", "primereact": "^10.9.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ripster-frontend", "name": "ripster-frontend",
"version": "0.12.0-11", "version": "0.12.0-12",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+12 -1
View File
@@ -981,6 +981,17 @@ export default function DashboardPage({
() => buildCdDriveLifecycleKey(pipeline?.cdDrives), () => buildCdDriveLifecycleKey(pipeline?.cdDrives),
[pipeline?.cdDrives] [pipeline?.cdDrives]
); );
// Detects when a background job reaches a terminal interactive state via PIPELINE_PROGRESS
// (e.g. READY_TO_ENCODE or WAITING_FOR_USER_DECISION), triggering a dashboard jobs reload.
const jobProgressInteractiveKey = useMemo(() => Object.entries(pipeline?.jobProgress || {})
.filter(([, v]) => {
const s = String(v?.state || '').toUpperCase();
return s === 'READY_TO_ENCODE' || s === 'WAITING_FOR_USER_DECISION';
})
.map(([id]) => id)
.sort()
.join(','),
[pipeline?.jobProgress]);
const monitoringSample = monitoringState.sample; const monitoringSample = monitoringState.sample;
const cpuMetrics = monitoringSample?.cpu || null; const cpuMetrics = monitoringSample?.cpu || null;
const memoryMetrics = monitoringSample?.memory || null; const memoryMetrics = monitoringSample?.memory || null;
@@ -1215,7 +1226,7 @@ export default function DashboardPage({
useEffect(() => { useEffect(() => {
void loadDashboardJobs(); void loadDashboardJobs();
}, [pipeline?.state, pipeline?.activeJobId, pipeline?.context?.jobId, cdDriveLifecycleKey, jobsRefreshToken]); }, [pipeline?.state, pipeline?.activeJobId, pipeline?.context?.jobId, cdDriveLifecycleKey, jobsRefreshToken, jobProgressInteractiveKey]);
useEffect(() => { useEffect(() => {
api.getDetectedDrives() api.getDetectedDrives()
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "ripster", "name": "ripster",
"version": "0.12.0-11", "version": "0.12.0-12",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ripster", "name": "ripster",
"version": "0.12.0-11", "version": "0.12.0-12",
"devDependencies": { "devDependencies": {
"concurrently": "^9.1.2" "concurrently": "^9.1.2"
} }
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "ripster", "name": "ripster",
"private": true, "private": true,
"version": "0.12.0-11", "version": "0.12.0-12",
"scripts": { "scripts": {
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"", "dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
"dev:backend": "npm run dev --prefix backend", "dev:backend": "npm run dev --prefix backend",