nest.jsには、タイムアウト設定が行えます。
https://zenn.dev/kazumasa/books/3f8519dfd26d6a/viewer/44d66b
ただし、この実装を行った場合、
確かにタイムアウト判定はされるものの、
そのリクエストの処理自体は途中で終了とはならず、最後まで処理をしてしまいます。
そのため、
Promise ベースのコードの場合、キャンセル用のフラグを手動でチェックする仕組みを作る必要があります。インターセプター内でキャンセル用のトークンを生成し、それをサービスに渡します。
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
RequestTimeoutException,
} from ‘@nestjs/common’;
import { Observable, throwError, catchError, firstValueFrom, timeout } from ‘rxjs’;
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
private activeTasks = new Map<string, AbortController>();
constructor(private readonly timeoutMs: number = 5000) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const requestId = context.switchToHttp().getRequest().id;
const abortController = new AbortController();
// サービスにキャンセル用のトークン(AbortController)を渡す
context.switchToHttp().getRequest().abortController = abortController;
this.activeTasks.set(requestId, abortController);
return next.handle().pipe(
timeout(this.timeoutMs),
catchError((err) => {
if (err.name === ‘TimeoutError’) {
abortController.abort(); // タイムアウト時に処理を中断
return throwError(() => new RequestTimeoutException());
}
return throwError(() => err);
}),
// 完了後にキャンセル情報を削除
catchError(() => {
this.activeTasks.delete(requestId);
return throwError(() => new Error(‘Request Failed’));
}),
);
}
}