mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
fix(server): connection aborted logging (#5595)
This commit is contained in:
parent
3a794d7a2b
commit
b7b4483a33
@ -21,6 +21,8 @@ export type Options = {
|
||||
each?: boolean;
|
||||
};
|
||||
|
||||
export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED';
|
||||
|
||||
export function ValidateUUID({ optional, each }: Options = { optional: false, each: false }) {
|
||||
return applyDecorators(
|
||||
IsUUID('4', { each }),
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
IAccessRepository,
|
||||
IJobRepository,
|
||||
ILibraryRepository,
|
||||
isConnectionAborted,
|
||||
JobName,
|
||||
mapAsset,
|
||||
mimeTypes,
|
||||
@ -20,6 +21,7 @@ import { constants } from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { QueryFailedError } from 'typeorm';
|
||||
import { promisify } from 'util';
|
||||
import { IAssetRepository } from './asset-repository';
|
||||
import { AssetCore } from './asset.core';
|
||||
import { AssetBulkUploadCheckDto } from './dto/asset-check.dto';
|
||||
@ -42,6 +44,10 @@ import { CuratedObjectsResponseDto } from './response-dto/curated-objects-respon
|
||||
type SendFile = Parameters<Response['sendFile']>;
|
||||
type SendFileOptions = SendFile[1];
|
||||
|
||||
// TODO: move file sending logic to an interceptor
|
||||
const sendFile = (res: Response, path: string, options: SendFileOptions) =>
|
||||
promisify<string, SendFileOptions>(res.sendFile).bind(res)(path, options);
|
||||
|
||||
@Injectable()
|
||||
export class AssetService {
|
||||
readonly logger = new Logger(AssetService.name);
|
||||
@ -336,19 +342,16 @@ export class AssetService {
|
||||
|
||||
res.set('Cache-Control', 'private, max-age=86400, no-transform');
|
||||
res.header('Content-Type', mimeTypes.lookup(filepath));
|
||||
return new Promise((resolve, reject) => {
|
||||
res.sendFile(filepath, options, (error: Error) => {
|
||||
if (!error) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (error.message !== 'Request aborted') {
|
||||
this.logger.error(`Unable to send file: ${error.name}`, error.stack);
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
try {
|
||||
await sendFile(res, filepath, options);
|
||||
} catch (error: Error | any) {
|
||||
if (!isConnectionAborted(error)) {
|
||||
this.logger.error(`Unable to send file: ${error.name}`, error.stack);
|
||||
}
|
||||
// throwing closes the connection and prevents `Error: write EPIPE`
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async getLibraryId(authUser: AuthUserDto, libraryId?: string) {
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
NestInterceptor,
|
||||
} from '@nestjs/common';
|
||||
import { Observable, catchError, throwError } from 'rxjs';
|
||||
import { isConnectionAborted } from '../../domain';
|
||||
import { routeToErrorMessage } from '../app.utils';
|
||||
|
||||
@Injectable()
|
||||
@ -20,7 +21,9 @@ export class ErrorInterceptor implements NestInterceptor {
|
||||
throwError(() => {
|
||||
if (error instanceof HttpException === false) {
|
||||
const errorMessage = routeToErrorMessage(context.getHandler().name);
|
||||
this.logger.error(errorMessage, error, error?.errors);
|
||||
if (!isConnectionAborted(error)) {
|
||||
this.logger.error(errorMessage, error, error?.errors);
|
||||
}
|
||||
return new InternalServerErrorException(errorMessage);
|
||||
} else {
|
||||
return error;
|
||||
|
Loading…
Reference in New Issue
Block a user