wing-ops/backend/src/vessels/vesselService.ts
jeonghyo.k 1f2e493226 feat(vessel): 선박 검색을 전체 캐시 대상으로 확대
뷰포트에 관계없이 백엔드 캐시의 전체 선박을 검색 가능하도록 개선.

- backend: GET /api/vessels/all 엔드포인트 추가 (getAllVessels)
- vesselSignalClient: onAllVessels? 콜백 추가; PollingClient는 3분마다 pollAll(), WS Client는 필터링 전 전송
- useVesselSignals: { vessels, allVessels } 반환, 초기 스냅샷도 allVessels에 반영
- MapView: allVessels prop 추가, VesselSearchBar에 우선 전달
- OilSpillView/HNSView/RescueView/IncidentsView: allVessels 구조분해 후 MapView/VesselSearchBar에 전달

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 15:10:58 +09:00

60 lines
1.6 KiB
TypeScript

import type { VesselPosition, BoundingBox } from './vesselTypes.js';
const VESSEL_TTL_MS = 10 * 60 * 1000; // 10분
const cachedVessels = new Map<string, VesselPosition>();
let lastUpdated: Date | null = null;
// lastUpdate가 TTL을 초과한 선박을 캐시에서 제거.
// lastUpdate 파싱이 불가능한 경우 보수적으로 유지한다.
function evictStale(): void {
const now = Date.now();
for (const [mmsi, vessel] of cachedVessels) {
const ts = Date.parse(vessel.lastUpdate);
if (Number.isNaN(ts)) continue;
if (now - ts > VESSEL_TTL_MS) {
cachedVessels.delete(mmsi);
}
}
}
export function updateVesselCache(vessels: VesselPosition[]): void {
for (const vessel of vessels) {
if (!vessel.mmsi) continue;
cachedVessels.set(vessel.mmsi, vessel);
}
evictStale();
lastUpdated = new Date();
}
export function getVesselsInBounds(bounds: BoundingBox): VesselPosition[] {
const result: VesselPosition[] = [];
for (const v of cachedVessels.values()) {
if (
v.lon >= bounds.minLon &&
v.lon <= bounds.maxLon &&
v.lat >= bounds.minLat &&
v.lat <= bounds.maxLat
) {
result.push(v);
}
}
return result;
}
export function getAllVessels(): VesselPosition[] {
return Array.from(cachedVessels.values());
}
export function getCacheStatus(): {
count: number;
bangjeCount: number;
lastUpdated: Date | null;
} {
let bangjeCount = 0;
for (const v of cachedVessels.values()) {
if (v.shipNm && v.shipNm.toUpperCase().includes('BANGJE')) bangjeCount++;
}
return { count: cachedVessels.size, bangjeCount, lastUpdated };
}