diff --git a/backend/src/routes/pipelineRoutes.js b/backend/src/routes/pipelineRoutes.js index 29a962f..002d69c 100644 --- a/backend/src/routes/pipelineRoutes.js +++ b/backend/src/routes/pipelineRoutes.js @@ -143,7 +143,9 @@ router.post( logger.info('post:audiobook:upload', { reqId: req.reqId, originalName: req.file.originalname, - sizeBytes: Number(req.file.size || 0) + sizeBytes: Number(req.file.size || 0), + mimeType: String(req.file.mimetype || '').trim() || null, + tempPath: String(req.file.path || '').trim() || null }); const result = await pipelineService.uploadAudiobookFile(req.file, { format: req.body?.format, diff --git a/backend/src/services/pipelineService.js b/backend/src/services/pipelineService.js index e919e19..37c93f0 100644 --- a/backend/src/services/pipelineService.js +++ b/backend/src/services/pipelineService.js @@ -10804,6 +10804,14 @@ class PipelineService extends EventEmitter { try { await historyService.resetProcessLog(job.id); await historyService.appendLog(job.id, 'SYSTEM', `AAX-Upload empfangen: ${originalName}`); + logger.info('audiobook:upload:received', { + jobId: job.id, + originalName, + tempFilePath, + rawBaseDir, + outputFormat, + startImmediately + }); const probeConfig = audiobookService.buildProbeCommand(ffprobeCommand, tempFilePath); const captured = await this.runCapturedCommand(probeConfig.cmd, probeConfig.args); @@ -10822,12 +10830,25 @@ class PipelineService extends EventEmitter { rawTemplate, originalName ); + logger.info('audiobook:upload:staging', { + jobId: job.id, + tempFilePath, + rawDir: storagePaths.rawDir, + rawFilePath: storagePaths.rawFilePath, + rawTemplate, + outputTemplate + }); ensureDir(storagePaths.rawDir); - fs.renameSync(tempFilePath, storagePaths.rawFilePath); + moveFileWithFallback(tempFilePath, storagePaths.rawFilePath); stagedRawDir = storagePaths.rawDir; stagedRawFilePath = storagePaths.rawFilePath; chownRecursive(storagePaths.rawDir, settings?.raw_dir_owner); + logger.info('audiobook:upload:staged', { + jobId: job.id, + stagedRawDir, + stagedRawFilePath + }); const makemkvInfo = this.withAnalyzeContextMediaProfile({ status: 'SUCCESS', @@ -10899,6 +10920,14 @@ class PipelineService extends EventEmitter { ...(startResult && typeof startResult === 'object' ? startResult : {}) }; } catch (error) { + logger.error('audiobook:upload:failed', { + jobId: job.id, + originalName, + tempFilePath, + stagedRawDir, + stagedRawFilePath, + error: errorToMeta(error) + }); const updatePayload = { status: 'ERROR', last_state: 'ERROR', diff --git a/install-dev.sh b/install-dev.sh index ea16492..b7f84ce 100644 --- a/install-dev.sh +++ b/install-dev.sh @@ -119,6 +119,64 @@ info "Frontend-Host: $FRONTEND_HOST" command_exists() { command -v "$1" &>/dev/null; } +nginx_replace_or_insert_directive() { + local file="$1" + local directive_regex="$2" + local desired_line="$3" + local anchor_regex="$4" + local directive_sed_regex="${directive_regex//\//\\/}" + local anchor_sed_regex="${anchor_regex//\//\\/}" + local desired_sed_line="${desired_line//\//\\/}" + + if grep -Eq "$directive_regex" "$file"; then + sed -i -E "0,/$directive_sed_regex/s//${desired_sed_line}/" "$file" + return 0 + fi + + sed -i "/$anchor_sed_regex/a\\$desired_line" "$file" +} + +patch_existing_ripster_nginx_site() { + local file="$1" + local backup_file="${file}.bak-$(date +%Y%m%d%H%M%S)" + + [[ -f "$file" ]] || return 1 + + cp -a "$file" "$backup_file" + info "Bestehende nginx-Konfiguration erkannt - ergänze Upload-/Proxy-Settings" + info "Backup erstellt: $backup_file" + + nginx_replace_or_insert_directive \ + "$file" \ + '^[[:space:]]*client_max_body_size[[:space:]]+[^;]+;' \ + ' client_max_body_size 8G;' \ + 'server_name .*;' + + nginx_replace_or_insert_directive \ + "$file" \ + '^[[:space:]]*proxy_connect_timeout[[:space:]]+[^;]+;' \ + ' proxy_connect_timeout 60s;' \ + 'location /api/ {' + + nginx_replace_or_insert_directive \ + "$file" \ + '^[[:space:]]*proxy_send_timeout[[:space:]]+[^;]+;' \ + ' proxy_send_timeout 3600s;' \ + 'location /api/ {' + + nginx_replace_or_insert_directive \ + "$file" \ + '^[[:space:]]*proxy_read_timeout[[:space:]]+[^;]+;' \ + ' proxy_read_timeout 3600s;' \ + 'location /api/ {' + + nginx_replace_or_insert_directive \ + "$file" \ + '^[[:space:]]*proxy_request_buffering[[:space:]]+[^;]+;' \ + ' proxy_request_buffering off;' \ + 'location /api/ {' +} + install_node() { header "Node.js installieren" local required_major=20 @@ -844,7 +902,10 @@ ok "ripster-backend.service erstellt" if [[ "$SKIP_NGINX" == false ]]; then header "nginx konfigurieren" - cat > /etc/nginx/sites-available/ripster < /etc/nginx/sites-available/ripster < /etc/nginx/sites-available/ripster < /etc/nginx/sites-available/ripster <