0.12.0-10 Fix Multi Job

This commit is contained in:
2026-03-23 07:30:44 +00:00
parent a87ba330b1
commit 6911892b89
7 changed files with 66 additions and 35 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "ripster-backend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster-backend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"dependencies": {
"archiver": "^7.0.1",
"cors": "^2.8.5",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "ripster-backend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"private": true,
"type": "commonjs",
"scripts": {
+34 -3
View File
@@ -7133,7 +7133,15 @@ class PipelineService extends EventEmitter {
const runningJobs = await historyService.getRunningJobs();
const foreignRunningJobs = runningJobs.filter((item) => Number(item?.id) !== Number(job.id));
const keepCurrentPipelineSession = foreignRunningJobs.length > 0;
// Only block metadata selection if a foreign job requires active user interaction
// in the pipeline UI. Autonomous jobs (ENCODING, RIPPING, READY_TO_ENCODE) run
// independently via activeProcesses and must not prevent new disc metadata selection.
const PIPELINE_INTERACTIVE_STATES = new Set([
'ANALYZING', 'METADATA_SELECTION', 'WAITING_FOR_USER_DECISION', 'MEDIAINFO_CHECK'
]);
const keepCurrentPipelineSession = foreignRunningJobs.some(
(item) => PIPELINE_INTERACTIVE_STATES.has(String(item?.status || '').toUpperCase())
);
if (!keepCurrentPipelineSession) {
await this.setState('METADATA_SELECTION', {
activeJobId: job.id,
@@ -7161,7 +7169,7 @@ class PipelineService extends EventEmitter {
await historyService.appendLog(
job.id,
'SYSTEM',
`Metadaten-Auswahl im Hintergrund vorbereitet. Aktive Session bleibt bei laufendem Job #${foreignRunningJobs.map((item) => item.id).join(',')}.`
`Metadaten-Auswahl im Hintergrund vorbereitet. Aktive Session bleibt bei interaktivem Job #${foreignRunningJobs.map((item) => item.id).join(',')}.`
);
}
@@ -8478,7 +8486,15 @@ class PipelineService extends EventEmitter {
const runningJobs = await historyService.getRunningJobs();
const foreignRunningJobs = runningJobs.filter((item) => Number(item?.id) !== Number(jobId));
const keepCurrentPipelineSession = foreignRunningJobs.length > 0;
// Only block the state transition if a foreign job requires active user interaction.
// Autonomous jobs (ENCODING, RIPPING, READY_TO_ENCODE) must not prevent this job
// from advancing through its own pipeline steps.
const PIPELINE_INTERACTIVE_STATES = new Set([
'ANALYZING', 'METADATA_SELECTION', 'WAITING_FOR_USER_DECISION', 'MEDIAINFO_CHECK'
]);
const keepCurrentPipelineSession = foreignRunningJobs.some(
(item) => PIPELINE_INTERACTIVE_STATES.has(String(item?.status || '').toUpperCase())
);
if (existingRawPath) {
await historyService.appendLog(
@@ -11201,6 +11217,11 @@ class PipelineService extends EventEmitter {
? `${finishedStatusTextBase} (${postEncodeScriptsSummary.failed} Skript(e) fehlgeschlagen)`
: finishedStatusTextBase;
// Only switch the pipeline UI to FINISHED if this job is still the active one.
// If the pipeline has moved to another job (e.g. metadata selection for a new disc
// that was inserted while this one was encoding), complete silently so the other
// job's UI state is not disrupted. The DB status is already FINISHED (above).
if (Number(this.snapshot.activeJobId) === Number(jobId)) {
await this.setState('FINISHED', {
activeJobId: jobId,
progress: 100,
@@ -11212,6 +11233,10 @@ class PipelineService extends EventEmitter {
outputPath: finalizedOutputPath
}
});
} else {
logger.info('encoding:finished:background', { jobId, mode, activeJobId: this.snapshot.activeJobId });
void this.pumpQueue();
}
if (mode === 'reencode') {
void this.notifyPushover('reencode_finished', {
@@ -14046,6 +14071,8 @@ class PipelineService extends EventEmitter {
error_message: null
});
// Only switch the pipeline UI to FINISHED if this job is still the active one.
if (Number(this.snapshot.activeJobId) === Number(jobId)) {
await this.setState('FINISHED', {
activeJobId: jobId,
progress: 100,
@@ -14058,6 +14085,10 @@ class PipelineService extends EventEmitter {
outputPath: finalizedOutputPath
}
});
} else {
logger.info('audiobook:finished:background', { jobId, activeJobId: this.snapshot.activeJobId });
void this.pumpQueue();
}
void this.notifyPushover('job_finished', {
title: 'Ripster - Audiobook abgeschlossen',
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "ripster-frontend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster-frontend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"dependencies": {
"primeicons": "^7.0.0",
"primereact": "^10.9.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "ripster-frontend",
"version": "0.12.0-9",
"version": "0.12.0-10",
"private": true,
"type": "module",
"scripts": {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "ripster",
"version": "0.12.0-9",
"version": "0.12.0-10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ripster",
"version": "0.12.0-9",
"version": "0.12.0-10",
"devDependencies": {
"concurrently": "^9.1.2"
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "ripster",
"private": true,
"version": "0.12.0-9",
"version": "0.12.0-10",
"scripts": {
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
"dev:backend": "npm run dev --prefix backend",