Skip to content

AbrGeocoderStream: geocoder.geocode 失敗時に UnhandledPromiseRejection が発生する #232

@honjo-hiroaki-gtt

Description

@honjo-hiroaki-gtt

概要

src/usecases/geocode/abr-geocoder-stream.ts_write メソッド内において、geocoder.geocode() が返す Promise に対するエラーハンドリング(.catch)がコメントアウトされています。
このコメントアウトされたコードを見る限り、本来は「ジオコーディング処理中に予期せぬエラーが発生した場合でもストリームを停止させず、エラー情報を持つ結果(MatchLevel.ERRORなど)として下流に流す」という意図があったと思われます。
しかし現状では、geocode 処理が reject された場合にエラーが捕捉されず、UnhandledPromiseRejection が発生してプロセス全体に影響を及ぼす状態となっています。

発生箇所

https://github.com/digital-go-jp/abr-geocoder/blob/main/src/usecases/geocode/abr-geocoder-stream.ts#L120-L126

// ... existing code ...
   120|    // エラーが発生した
   121|    // .catch((error: Error | string) => {
   122|    //   const query = Query.create(input);
   123|    //   this.emit(this.kShiftEvent, query.copy({
   124|    //     match_level: MatchLevel.ERROR,
   125|    //   }));
   126|    // })
// ... existing code ...

再現手順

以下のテストコードを作成し実行すると再現します。AbrGeocoder のモックが reject を返した際、ストリーム側でエラーが捕捉されないことを確認できます。

import { describe, expect, test, jest } from '@jest/globals';
import { Readable } from 'node:stream';
import { AbrGeocoder } from '../abr-geocoder';
import { AbrGeocoderStream } from '../abr-geocoder-stream';
import { MatchLevel } from '@domain/types/geocode/match-level';

describe('AbrGeocoderStream', () => {
  test('should handle rejection from geocoder', (done) => {
    const mockGeocoder = {
      geocode: jest.fn().mockRejectedValue(new Error('Test Error')),
      close: jest.fn().mockResolvedValue(undefined),
    } as unknown as AbrGeocoder;

    const stream = new AbrGeocoderStream({
      geocoder: mockGeocoder,
      fuzzy: '?',
    });

    const input = ['東京都千代田区千代田1-1'];
    const readable = Readable.from(input);

    readable.pipe(stream);

    let receivedCount = 0;
    stream.on('data', (data) => {
      receivedCount++;
      // エラーハンドリングの結果として ERROR レベルのデータが流れてくることを期待する場合
      if (data.match_level.num === MatchLevel.ERROR.num) {
        done();
      }
    });

    stream.on('end', () => {
      if (receivedCount === 0) {
        done(new Error('Stream ended without receiving data or error'));
      }
    });

    stream.on('error', (err) => {
      // もしくは stream の error イベントとして捕捉されるべき場合
      done(err);
    });
  });
});

期待する動作

geocoder.geocode が失敗した場合でも、プロセスがクラッシュせず、適切にエラーが処理されること。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions