CPElement#findTask — 중복 workarea 매칭으로 비결정적 task 선택
RCA: CPElement::findTask | Multiple tasks found for Element
Error Log#
CPElement::findTask | Multiple tasks found for Element bim_external_id: 18/35/0/84/0, category_id: 1027996, phase_id: 10022, workarea_ids: [ 92108 ]
Impact#
- Service:
cupixworks-sitetrack-preprocessor-agent - Team: lemartec
- 발생 횟수: 364
- 최초 발생: 2026-04-06T21:29:26.192Z
- 최근 발생: 2026-04-06T21:29:26.275Z
Root Cause Summary#
CPElement::findTask 메서드가 element에 매칭되는 task를 찾을 때 (categoryId, srvTextureId, workareaId) 조합으로 필터링하는데, 해당 facility(lemartec 팀)의 데이터에 동일한 조합을 가진 task가 복수로 존재합니다. 이는 Tesla API에서 반환하는 task 데이터에 중복된 (category, phase/texture, workarea) 튜플이 있기 때문입니다. 코드는 첫 번째 매칭 task를 사용하여 처리를 계속하므로 즉각적인 기능 장애는 없지만, 잘못된 task가 선택될 가능성이 있어 element record의 정확성에 영향을 줄 수 있습니다. 에러는 3개의 sitetrack 처리 job(16005, 16004, 15891)에서 연속 발생했으며, 주로 category_id: 1027996 / phase_id: 10022 / workarea_ids: [92108] 조합에 집중되어 있습니다.
Technical Analysis#
Code Path#
- Entry point:
sitetrack-preprocessor-runner.ts:9—createTargetModels()호출 createCPElements()(sitetrack-preprocessor-runner.ts:130)에서 facility의 모든 element를 BIM과 category 별로 로드createCPTasks()(sitetrack-preprocessor-runner.ts:159)에서 facility의 모든 task를 로드하고,(categoryId, workareaId)기준으로 필터링loadAllPhases()(sitetrack-preprocessor-runner.ts:206)에서 phase를 로드하고, 각 phase에 task를 연결loadAllElementRecords()(sitetrack-preprocessor-runner.ts:295)에서 각 element에 대해makeElementRecords()호출makeElementRecords()(cpelement.ts:83)에서 각 phase에 대해findTask()호출- Failure point:
findTask()(cpelement.ts:115-132) —candidateTasks.length > 1조건에서 에러 로그 발생
findTask() 메서드의 필터링 로직:
// packages/models/src/cpelement.ts:115-132
protected findTask = (cpTasks: CPTask[], cpPhase: CPPhase): CPTask | undefined => {
const candidateTasks = cpTasks
.filter(cpTask => cpTask.categoryId === this.categoryId)
.filter(cpTask => cpTask.srvTextureId === cpPhase.srvTextureId)
.filter(cpTask => cpTask.workareaId && this.workareaIds.includes(cpTask.workareaId));
if (candidateTasks.length === 0) {
logger.warn('CPElement::findTask | This element will not be tracked because task not found...');
return undefined;
} else if (candidateTasks.length > 1) {
// logs as error but does not throw an error. use the first task found.
logger.error('CPElement::findTask | Multiple tasks found for Element bim_external_id: %s, category_id: %d, phase_id: %d, workarea_ids: %s'
, this.bimExternalId, this.categoryId, cpPhase.id, this.workareaIds);
}
return candidateTasks[0];
};
기대 동작: 각 element + phase 조합에 대해 (categoryId, srvTextureId, workareaId) 필터로 정확히 1개의 task가 매칭되어야 합니다.
실제 동작: 동일 조합에 2개 이상의 task가 매칭되어, 에러를 로그하고 첫 번째 task를 선택합니다. 이 경우 선택되는 task가 의도된 것인지 보장할 수 없습니다.
Task 로드 과정 (sitetrack-preprocessor-runner.ts:159-191):
// packages/cupix-sitetrack-preprocessor-agent/src/runner/sitetrack-preprocessor-runner.ts:170-180
const srvTasks = await this.cupixApi.task.getAll(cpSitetrack.facilityKey);
const filteredTasks = srvTasks.filter(task =>
uniqueCategoryIds.includes(task.category?.id ?? -1)
&& uniqueWorkareaIds.includes(task.workarea?.id ?? -1)
);
const cpTasks = await createModels(CPTask, cpSitetrack, Promise.resolve(filteredTasks));
for (const cpTask of cpTasks) {
cpSitetrack.addCPTask(cpTask);
}
task.getAll()이 facility 전체의 모든 task를 반환하며, (categoryId, workareaId) 필터만 적용합니다. Phase에 task를 연결하는 과정(loadAllPhases에서 cpPhase.addCPTask)을 거치지만, findTask에서는 phase의 cpTasks 배열에서 다시 categoryId와 srvTextureId, workareaId로 필터링합니다. 서버 데이터에 동일 (category, texture, workarea) 조합의 task가 여러 개 존재하면 이 에러가 발생합니다.
Log Evidence#
Datadog 검색 쿼리:
service:cupixworks-sitetrack-preprocessor-agent status:error "Multiple tasks found" "category_id: 1027996"
Time range: 2026-04-06T20:30:00Z to 2026-04-06T22:00:00Z
에러가 발생한 category/phase/workarea 조합 분포 (06:29:26 KST 기준, sitetrackId: 16005):
34건 category_id: 1027996, phase_id: 10022, workarea_ids: [ 92108 ]
12건 category_id: 1028016, phase_id: 10042, workarea_ids: [ 92108 ]
4건 category_id: 1028081, phase_id: 10107, workarea_ids: [ 92106 ]
처리 job 타임라인 (info 레벨 로그):
06:28:40 KST BaseService::runByMessage | id: 999020
06:28:40 KST PreprocessorService::run | begin
06:28:40 KST PreprocessorService::createCPSitetrack | begin - sitetrackId: 16005
06:28:40 KST PreprocessorService::createCPSitetrack | end
06:28:40 KST JobManager::updateJobProgress | begin - jobId: 999020, processingStatus: load_sitetrack_on_preprocessor
06:28:40 KST JobManager::updateJobProgress | begin - jobId: 999020, processingStatus: load_target_models
06:29:26 KST [364 error logs] CPElement::findTask | Multiple tasks found for Element...
06:29:33 KST JobManager::updateJobProgress | begin - jobId: 999020, processingStatus: download_files
다른 sitetrack ID에서도 동일 에러 발생 (06:40:20 KST, sitetrackId: 16004):
06:39:36 KST PreprocessorService::createCPSitetrack | begin - sitetrackId: 16004
06:40:20 KST CPElement::findTask | Multiple tasks found for Element bim_external_id: 25/0/0/5/11/0/38, category_id: 1028016, phase_id: 10042, workarea_ids: [ 94829 ]
warn 레벨의 findTask 로그도 같은 시간대에 확인됨 (task가 0건인 경우):
06:51:41 KST CPElement::findTask | This element will not be tracked because task not found for Element bim_external_id: ab7328b3-..., category_id: 1024138, phase_id: 3795, workarea_ids: [ 9590 ]
Fix Recommendation#
즉시 조치 (Critical)#
packages/models/src/cpelement.ts:125-128: 에러 로그에 매칭된 task ID 목록을 포함하도록 수정하면 어떤 task들이 중복인지 디버깅이 용이해집니다. 현재 로그에는 element 측 정보만 있고 매칭된 task 정보가 없습니다.- 데이터 정합성 확인: Tesla API에서 lemartec facility의 task 데이터를 조회하여,
category_id: 1027996 / workarea_id: 92108조합에 해당하는 task들이 왜 중복으로 존재하는지 확인 필요합니다. 중복 task가 실수로 생성된 것이라면 데이터 정리가 필요합니다.
단기 개선 (1주 이내)#
findTask()메서드에서 중복 task 발견 시, task의activityKey또는id를 기준으로 결정론적(deterministic) 선택을 하도록 개선합니다. 현재 배열 순서에 의존하는candidateTasks[0]은 API 응답 순서에 따라 비결정적일 수 있습니다.- task 로딩 단계(
createCPTasks)에서 중복(categoryId, srvTextureId, workareaId)조합을 사전 감지하고 경고할 수 있도록 유효성 검증을 추가합니다.
장기 개선 (재발 방지)#
- Tesla API의 task 생성 로직에서 동일 facility 내
(category, phase/texture, workarea)조합의 유일성을 DB 레벨(unique constraint)에서 보장하도록 검토합니다. - Sitetrack preprocessor에서 데이터 정합성 문제를 별도 메트릭으로 추적하여, facility 설정 오류를 조기에 발견할 수 있도록 합니다.
Monitoring#
- 기존 에러 로그 빈도 모니터링:
service:cupixworks-sitetrack-preprocessor-agent status:error "Multiple tasks found"
- 특정 facility/team 기준 중복 task 발생 추세:
service:cupixworks-sitetrack-preprocessor-agent status:error "Multiple tasks found" ("92108" OR "94829")
findTaskwarn + error 합계를 모니터링하여 전체 task 매칭 실패율 추적
Risk Assessment#
- Risk level: low
- 예상 복잡도: standard
- 현재 코드는 첫 번째 task를 선택하여 처리를 계속하므로 서비스 중단은 없습니다. 그러나 잘못된 task가 선택될 경우 element record의 정확성에 영향을 줄 수 있습니다. lemartec 팀의 특정 facility에 국한된 문제로, 해당 facility의 task 데이터 정리가 가장 효과적인 해결 방법입니다.