0.13.0-1 Series Flow
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.13.0",
|
||||
"version": "0.13.0-1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-backend",
|
||||
"version": "0.13.0",
|
||||
"version": "0.13.0-1",
|
||||
"dependencies": {
|
||||
"archiver": "^7.0.1",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.13.0",
|
||||
"version": "0.13.0-1",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
|
||||
@@ -905,11 +905,27 @@ function enrichJobRow(job, settings = null, options = {}) {
|
||||
const backupSuccess = ripSuccessful;
|
||||
const finishedWithOutput = normalizedJobStatus === 'FINISHED'
|
||||
&& (includeFsChecks ? Boolean(outputStatus?.exists) : true);
|
||||
const seriesBatchSummary = handbrakeInfo?.seriesBatch && typeof handbrakeInfo.seriesBatch === 'object'
|
||||
? handbrakeInfo.seriesBatch
|
||||
: null;
|
||||
const seriesBatchMode = String(handbrakeInfo?.mode || '').trim().toLowerCase() === 'series_batch';
|
||||
const seriesBatchTotal = Number(seriesBatchSummary?.totalCount || 0);
|
||||
const seriesBatchFinished = Number(seriesBatchSummary?.finishedCount || 0);
|
||||
const seriesBatchErrors = Number(seriesBatchSummary?.errorCount || 0);
|
||||
const seriesBatchCancelled = Number(seriesBatchSummary?.cancelledCount || 0);
|
||||
const seriesBatchEncodeSuccess = seriesBatchMode
|
||||
&& seriesBatchTotal > 0
|
||||
&& seriesBatchFinished >= seriesBatchTotal
|
||||
&& seriesBatchErrors <= 0
|
||||
&& seriesBatchCancelled <= 0;
|
||||
const encodeSuccess = directoryLikeOutput
|
||||
? finishedWithOutput
|
||||
: (mediaType === 'converter'
|
||||
? finishedWithOutput
|
||||
: String(handbrakeInfo?.status || '').trim().toUpperCase() === 'SUCCESS');
|
||||
: (
|
||||
seriesBatchEncodeSuccess
|
||||
|| (mediaType === 'converter'
|
||||
? finishedWithOutput
|
||||
: String(handbrakeInfo?.status || '').trim().toUpperCase() === 'SUCCESS')
|
||||
);
|
||||
|
||||
return {
|
||||
...job,
|
||||
@@ -3629,6 +3645,7 @@ class HistoryService {
|
||||
});
|
||||
const seriesCandidateIds = seriesCandidates.map((job) => normalizeJobIdValue(job?.id)).filter(Boolean);
|
||||
let childRows = [];
|
||||
let nestedChildRows = [];
|
||||
let outputFolders = [];
|
||||
if (containerIds.length > 0) {
|
||||
const placeholders = containerIds.map(() => '?').join(', ');
|
||||
@@ -3639,15 +3656,46 @@ class HistoryService {
|
||||
const childIds = childRows.map((row) => normalizeJobIdValue(row?.id)).filter(Boolean);
|
||||
if (childIds.length > 0) {
|
||||
const childPlaceholders = childIds.map(() => '?').join(', ');
|
||||
nestedChildRows = await db.all(
|
||||
`SELECT id, parent_job_id, output_path, raw_path, handbrake_info_json, status, encode_plan_json, makemkv_info_json, rip_successful FROM jobs WHERE parent_job_id IN (${childPlaceholders})`,
|
||||
childIds
|
||||
);
|
||||
}
|
||||
const summaryJobIds = Array.from(new Set([
|
||||
...childRows.map((row) => normalizeJobIdValue(row?.id)).filter(Boolean),
|
||||
...nestedChildRows.map((row) => normalizeJobIdValue(row?.id)).filter(Boolean)
|
||||
]));
|
||||
if (summaryJobIds.length > 0) {
|
||||
const childPlaceholders = summaryJobIds.map(() => '?').join(', ');
|
||||
outputFolders = await db.all(
|
||||
`SELECT job_id, output_path FROM job_output_folders WHERE job_id IN (${childPlaceholders})`,
|
||||
childIds
|
||||
summaryJobIds
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const allContainerChildRows = [...childRows, ...nestedChildRows];
|
||||
const directChildRowById = new Map();
|
||||
for (const row of childRows) {
|
||||
const childId = normalizeJobIdValue(row?.id);
|
||||
if (childId) {
|
||||
directChildRowById.set(childId, row);
|
||||
}
|
||||
}
|
||||
const nestedRowsByParentId = new Map();
|
||||
for (const row of nestedChildRows) {
|
||||
const parentId = normalizeJobIdValue(row?.parent_job_id);
|
||||
if (!parentId) {
|
||||
continue;
|
||||
}
|
||||
if (!nestedRowsByParentId.has(parentId)) {
|
||||
nestedRowsByParentId.set(parentId, []);
|
||||
}
|
||||
nestedRowsByParentId.get(parentId).push(row);
|
||||
}
|
||||
|
||||
const childOutputMap = new Map();
|
||||
for (const child of childRows) {
|
||||
for (const child of allContainerChildRows) {
|
||||
const childId = normalizeJobIdValue(child?.id);
|
||||
if (!childId) {
|
||||
continue;
|
||||
@@ -3701,9 +3749,12 @@ class HistoryService {
|
||||
let expectedFromPlans = 0;
|
||||
const seenOutputs = new Set();
|
||||
let existingCount = 0;
|
||||
let existingCountFromSeriesBatch = 0;
|
||||
const totalChildren = childIds.length;
|
||||
for (const childId of childIds) {
|
||||
const childRow = childRows.find((row) => normalizeJobIdValue(row?.id) === childId) || null;
|
||||
const childRow = directChildRowById.get(childId) || null;
|
||||
const descendantRows = nestedRowsByParentId.get(childId) || [];
|
||||
const relatedRows = [childRow, ...descendantRows].filter(Boolean);
|
||||
if (childRow) {
|
||||
const rawPath = String(childRow?.raw_path || '').trim();
|
||||
if (rawPath) {
|
||||
@@ -3722,32 +3773,87 @@ class HistoryService {
|
||||
if (ripSuccessful) {
|
||||
backupSuccessCount += 1;
|
||||
}
|
||||
let selectedCount = 0;
|
||||
const childPlan = parseJsonSafe(childRow?.encode_plan_json, null);
|
||||
if (childPlan && typeof childPlan === 'object') {
|
||||
const titles = Array.isArray(childPlan?.titles) ? childPlan.titles : [];
|
||||
const selectedCount = titles.filter((title) => title?.selectedForEncode || title?.encodeInput).length;
|
||||
if (selectedCount > 0) {
|
||||
expectedFromPlans += selectedCount;
|
||||
}
|
||||
selectedCount = titles.filter((title) => title?.selectedForEncode || title?.encodeInput).length;
|
||||
}
|
||||
const handbrakeInfo = parseJsonSafe(childRow?.handbrake_info_json, null);
|
||||
const hbStatus = String(handbrakeInfo?.status || '').trim().toUpperCase();
|
||||
if (hbStatus === 'SUCCESS') {
|
||||
encodeSuccessAny = true;
|
||||
encodeSuccessCount += 1;
|
||||
const seriesBatchSummary = handbrakeInfo?.seriesBatch && typeof handbrakeInfo.seriesBatch === 'object'
|
||||
? handbrakeInfo.seriesBatch
|
||||
: null;
|
||||
const seriesBatchTotal = Number(seriesBatchSummary?.totalCount || 0);
|
||||
const seriesBatchFinished = Number(seriesBatchSummary?.finishedCount || 0);
|
||||
const seriesBatchErrors = Number(seriesBatchSummary?.errorCount || 0);
|
||||
const seriesBatchCancelled = Number(seriesBatchSummary?.cancelledCount || 0);
|
||||
const expectedFromNested = descendantRows.length > 0 ? descendantRows.length : 0;
|
||||
const expectedFromChild = seriesBatchTotal > 0
|
||||
? seriesBatchTotal
|
||||
: (selectedCount > 0 ? selectedCount : expectedFromNested);
|
||||
if (expectedFromChild > 0) {
|
||||
expectedFromPlans += expectedFromChild;
|
||||
}
|
||||
if (seriesBatchFinished > 0) {
|
||||
existingCountFromSeriesBatch += seriesBatchFinished;
|
||||
}
|
||||
|
||||
let childEncodeSuccess = hbStatus === 'SUCCESS';
|
||||
if (
|
||||
!childEncodeSuccess
|
||||
&& seriesBatchTotal > 0
|
||||
&& seriesBatchFinished >= seriesBatchTotal
|
||||
&& seriesBatchErrors <= 0
|
||||
&& seriesBatchCancelled <= 0
|
||||
) {
|
||||
childEncodeSuccess = true;
|
||||
}
|
||||
if (!childEncodeSuccess && descendantRows.length > 0) {
|
||||
let finishedDescendants = 0;
|
||||
let errorDescendants = 0;
|
||||
let cancelledDescendants = 0;
|
||||
for (const row of descendantRows) {
|
||||
const rowState = String(row?.status || row?.last_state || '').trim().toUpperCase();
|
||||
if (rowState === 'FINISHED') {
|
||||
finishedDescendants += 1;
|
||||
} else if (rowState === 'ERROR') {
|
||||
errorDescendants += 1;
|
||||
} else if (rowState === 'CANCELLED') {
|
||||
cancelledDescendants += 1;
|
||||
}
|
||||
}
|
||||
childEncodeSuccess = finishedDescendants >= descendantRows.length
|
||||
&& errorDescendants === 0
|
||||
&& cancelledDescendants === 0;
|
||||
}
|
||||
if (childEncodeSuccess) {
|
||||
encodeSuccessAny = true;
|
||||
encodeSuccessCount += 1;
|
||||
}
|
||||
} else if (descendantRows.length > 0) {
|
||||
expectedFromPlans += descendantRows.length;
|
||||
}
|
||||
const outputs = Array.from(childOutputMap.get(childId) || []);
|
||||
for (const outputPath of outputs) {
|
||||
if (!outputPath || seenOutputs.has(outputPath)) {
|
||||
for (const relatedRow of relatedRows) {
|
||||
const relatedRowId = normalizeJobIdValue(relatedRow?.id);
|
||||
if (!relatedRowId) {
|
||||
continue;
|
||||
}
|
||||
seenOutputs.add(outputPath);
|
||||
if (!includeFsChecks || fs.existsSync(outputPath)) {
|
||||
existingCount += 1;
|
||||
const outputs = Array.from(childOutputMap.get(relatedRowId) || []);
|
||||
for (const outputPath of outputs) {
|
||||
if (!outputPath || seenOutputs.has(outputPath)) {
|
||||
continue;
|
||||
}
|
||||
seenOutputs.add(outputPath);
|
||||
if (!includeFsChecks || fs.existsSync(outputPath)) {
|
||||
existingCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (existingCountFromSeriesBatch > existingCount) {
|
||||
existingCount = existingCountFromSeriesBatch;
|
||||
}
|
||||
if (!encodeSuccessAny && existingCount > 0) {
|
||||
encodeSuccessAny = true;
|
||||
if (encodeSuccessCount === 0 && totalChildren > 0) {
|
||||
@@ -5102,6 +5208,18 @@ class HistoryService {
|
||||
?? analyzeContext?.seriesLookupHint?.discNumber
|
||||
?? null
|
||||
);
|
||||
const resolvedJobMediaType = inferMediaType(
|
||||
job,
|
||||
makemkvInfo,
|
||||
job?.mediainfo_info_json,
|
||||
job?.encode_plan_json,
|
||||
job?.handbrake_info_json
|
||||
);
|
||||
if (resolvedJobMediaType === 'dvd' && discNumber === null) {
|
||||
const error = new Error('Serien-DVD erkannt: Disk-Nummer ist Pflicht (Start bei 1).');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
let metadataKind = manualMetadataKind
|
||||
|| String(
|
||||
existingSelectedMetadata?.metadataKind
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user