Minion
Minion
Apache Pinot의 minion 구성 요소를 살펴보는 페이지예요. minion은 브로커와 서버의 쿼리 프로세스와 별개로 테이블 데이터에 대한 백그라운드 작업을 실행해 효율적인 데이터 이동과 세그먼트 생성을 가능하게 해줘요.
출처: Minion
본문
Pinot minion은 브로커와 서버가 수행하는 쿼리 프로세스와 별개로 테이블 데이터에 대한 백그라운드 작업을 실행하는 선택적 클러스터 컴포넌트예요. Minion은 독립 하드웨어 리소스에서 실행되며 controller가 지시하는 minion 태스크를 실행할 책임이 있어요. minion 태스크의 예로는 Avro나 JSON 같은 표준 형식의 배치 데이터를 오프라인 테이블에 로드할 세그먼트 파일로 변환하는 것, GDPR 같은 데이터 개인정보 보호법이 요구하는 대로 레코드를 제거하기 위해 기존 세그먼트 파일을 다시 쓰는 것이 있어요. Minion 태스크는 한 번 실행하거나 주기적으로 실행되도록 스케줄할 수 있어요.
Minion은 대역 외(out-of-band) 데이터 처리의 계산 부담을 서버로부터 격리해요. Pinot 클러스터는 minion이 없어도 기능하지만, 일반적으로 배치 데이터 수집 같은 일상적인 작업을 지원하기 위해 존재해요.
Minion 시작 (Starting a minion)
Zookeeper를 설정했는지 확인하세요. Docker를 사용한다면 Pinot Docker 이미지를 받아두세요. minion을 시작하려면:
Usage: StartMinion
-help : Print this message. (required=false)
-minionHost <String> : Host name for minion. (required=false)
-minionPort <int> : Port number to start the minion at. (required=false)
-zkAddress <http> : HTTP address of Zookeeper. (required=false)
-clusterName <String> : Pinot cluster name. (required=false)
-configFileName <Config File Name> : Minion Starter Config file. (required=false)
Docker 이미지:
docker run \
--network=pinot-demo \
--name pinot-minion \
-d ${PINOT_IMAGE} StartMinion \
-zkAddress pinot-zookeeper:2181
런처 스크립트:
bin/pinot-admin.sh StartMinion \
-zkAddress localhost:2181
인터페이스 (Interfaces)

Pinot task generator
Pinot task generator 인터페이스는 minion이 실행할 태스크를 controller가 생성하기 위한 API를 정의해요.
⚠️ 설정 파일의 중복 키 (Duplicate Keys in Configuration File)
Apache Pinot 1.3.0부터 minion 설정 파일의 중복 키는 시작 중에
ConfigurationException을 던져요. 이전에는 중복 키가 조용히 리스트로 병합됐어요. 이 오류가 발생하면 각 구성 속성이 설정 파일에 한 번만 나타나는지 확인하세요. 예외에는 정확한 파일 경로, 중복 키 이름, 중복을 찾은 줄 번호가 포함돼요.예시 오류:
ConfigurationException: Duplicate key found in /path/to/minion.conf at line 10 and line 15: pinot.minion.task.allow\.download.from.server
public interface PinotTaskGenerator {
/**
* Initializes the task generator.
*/
void init(ClusterInfoAccessor clusterInfoAccessor);
/**
* Returns the task type of the generator.
*/
String getTaskType();
/**
* Generates a list of tasks to schedule based on the given table configs.
*/
List<PinotTaskConfig> generateTasks(List<TableConfig> tableConfigs);
/**
* Returns the timeout in milliseconds for each task, 3600000 (1 hour) by default.
*/
default long getTaskTimeoutMs() {
return JobConfig.DEFAULT_TIMEOUT_PER_TASK;
}
/**
* Returns the maximum number of concurrent tasks allowed per instance, 1 by default.
*/
default int getNumConcurrentTasksPerInstance() {
return JobConfig.DEFAULT_NUM_CONCURRENT_TASKS_PER_INSTANCE;
}
/**
* Performs necessary cleanups (e.g. remove metrics) when the controller leadership changes.
*/
default void nonLeaderCleanUp() {
}
}
PinotTaskExecutorFactory
Minion이 태스크를 실행하기 위한 API를 정의하는 PinotTaskExecutor의 팩토리예요.
public interface PinotTaskExecutorFactory {
/**
* Initializes the task executor factory.
*/
void init(MinionTaskZkMetadataManager zkMetadataManager);
/**
* Returns the task type of the executor.
*/
String getTaskType();
/**
* Creates a new task executor.
*/
PinotTaskExecutor create();
}
public interface PinotTaskExecutor {
/**
* Executes the task based on the given task config and returns the execution result.
*/
Object executeTask(PinotTaskConfig pinotTaskConfig)
throws Exception;
/**
* Tries to cancel the task.
*/
void cancel();
}
MinionEventObserverFactory
minion에서 태스크 이벤트 콜백을 위한 API를 정의하는 MinionEventObserver의 팩토리예요.
public interface MinionEventObserverFactory {
/**
* Initializes the task executor factory.
*/
void init(MinionTaskZkMetadataManager zkMetadataManager);
/**
* Returns the task type of the event observer.
*/
String getTaskType();
/**
* Creates a new task event observer.
*/
MinionEventObserver create();
}
public interface MinionEventObserver {
/**
* Invoked when a minion task starts.
*
* @param pinotTaskConfig Pinot task config
*/
void notifyTaskStart(PinotTaskConfig pinotTaskConfig);
/**
* Invoked when a minion task succeeds.
*
* @param pinotTaskConfig Pinot task config
* @param executionResult Execution result
*/
void notifyTaskSuccess(PinotTaskConfig pinotTaskConfig, @Nullable Object executionResult);
/**
* Invoked when a minion task gets cancelled.
*
* @param pinotTaskConfig Pinot task config
*/
void notifyTaskCancelled(PinotTaskConfig pinotTaskConfig);
/**
* Invoked when a minion task encounters exception.
*
* @param pinotTaskConfig Pinot task config
* @param exception Exception encountered during execution
*/
void notifyTaskError(PinotTaskConfig pinotTaskConfig, Exception exception);
}
내장 태스크 (Built-in tasks)
Pinot는 다음 내장 Minion 태스크를 제공해요:
| 태스크 | 목적 | 테이블 유형 |
|---|---|---|
| SegmentGenerationAndPushTask | 배치 수집: 원시 데이터 파일을 읽어 Pinot 세그먼트로 변환 | OFFLINE |
| RealtimeToOfflineSegmentsTask | 완료된 실시간 세그먼트를 최적화된 오프라인 세그먼트로 변환 | REALTIME to OFFLINE |
| MergeRollupTask | 작은 세그먼트를 더 큰 것으로 병합하고 선택적으로 더 거친 세분화로 데이터 롤업 | OFFLINE, REALTIME (upsert/dedup 없음) |
| PurgeTask | 데이터 보존과 규정 준수(예: GDPR)를 위해 레코드 제거 또는 수정 | OFFLINE, REALTIME |
| RefreshSegmentTask | 테이블 설정 또는 스키마 변경 후 세그먼트 재처리 (새 인덱스, 칼럼, 데이터 타입) | OFFLINE, REALTIME |
| UpsertCompactionTask | 무효화된 레코드를 제거해 개별 upsert 세그먼트 컴팩션 | REALTIME (upsert만) |
| UpsertCompactMergeTask | 여러 작은 upsert 세그먼트를 더 큰 것으로 병합해 세그먼트 수 감소 | REALTIME (upsert만) |
💡
PurgeTask,RefreshSegmentTask,UpsertCompactionTask는 모두 단일 세그먼트를 다시 빌드하고 교체 세그먼트를 업로드해요. 업로드가 실패하면 Pinot는 성공으로 보고하는 대신 태스크 시도를 실패로 표시해 Minion 태스크 프레임워크가 재시도할 수 있게 해요.
SegmentGenerationAndPushTask
SegmentGenerationAndPushTask는 입력 폴더(예: S3 버킷)에서 파일을 가져와 세그먼트로 변환할 수 있어요. 파일 하나를 세그먼트 하나로 변환하고 중복 수집을 피하기 위해 세그먼트 메타데이터에 파일 이름을 유지해요.
전체 구성 세부 사항은 SegmentGenerationAndPushTask 런북을 참조하세요.
다음은 이 태스크를 활성화하기 위해 TableConfig에 넣는 예시 태스크 설정이에요. 태스크는 남은 파일을 계속 수집하도록 10분마다 스케줄되며, 최대 10개의 병렬 태스크와 태스크당 1개 파일로 실행돼요.
참고: 다음 주의 사항 때문에 tableMaxNumTasks를 그냥 생략하고 싶을 수 있어요. 태스크는 파일당 세그먼트 하나를 생성하고 파일의 시간 칼럼을 기반으로 세그먼트 이름을 도출해요. 두 파일이 같은 시간 범위를 가지고 서로 다른 일정의 태스크로 수집되면 세그먼트 이름 충돌이 있을 수 있어요. 지금은 이 문제를 극복하기 위해 tableMaxNumTasks를 생략할 수 있고, 기본값이 Integer.MAX_VALUE라 단일 배치로 모든 입력 파일을 수집하도록 가능한 한 많은 태스크를 스케줄해요. 한 배치 내에서는 시퀀스 번호 접미사를 사용해 세그먼트 이름 충돌을 방지해요. 시퀀스 번호 접미사가 한 배치 내로 한정되므로 다른 배치의 태스크는 위에서 말한 세그먼트 이름 충돌 문제를 겪을 수 있어요.
💡 규모 있는 수집을 수행할 때
SegmentGenerationAndPushTask작업이 스케줄될 때마다 Pinot가inputDirURI에 포함된 모든 파일을 나열한다는 점을 기억하세요. GCS 같은 클라우드 버킷에서 파일을 가져올 때 이는 병목이 될 수 있어요. 이를 방지하려면inputDirURI가 가능한 한 적은 수의 파일을 가리키도록 하세요.
"ingestionConfig": {
"batchIngestionConfig": {
"segmentIngestionType": "APPEND",
"segmentIngestionFrequency": "DAILY",
"batchConfigMaps": [
{
"input.fs.className": "org.apache.pinot.plugin.filesystem.S3PinotFS",
"input.fs.prop.region": "us-west-2",
"input.fs.prop.secretKey": "....",
"input.fs.prop.accessKey": "....",
"inputDirURI": "s3://my.s3.bucket/batch/airlineStats/rawdata/",
"includeFileNamePattern": "glob:**/*.avro",
"excludeFileNamePattern": "glob:**/*.tmp",
"inputFormat": "avro"
}
]
}
},
"task": {
"taskTypeConfigsMap": {
"SegmentGenerationAndPushTask": {
"schedule": "0 */10 * * * ?",
"tableMaxNumTasks": "10"
}
}
}
RealtimeToOfflineSegmentsTask
자세한 내용은 Pinot managed Offline flows를 참조하세요.
MergeRollupTask
자세한 내용은 Minion merge rollup task를 참조하세요.
PurgeTask
자세한 내용은 PurgeTask 런북을 참조하세요.
RefreshSegmentTask
자세한 내용은 RefreshSegmentTask 런북을 참조하세요.
UpsertCompactionTask
자세한 내용은 UpsertCompactionTask 런북을 참조하세요.
UpsertCompactMergeTask
자세한 내용은 UpsertCompactMergeTask 런북을 참조하세요.
태스크 활성화 (Enable tasks)
태스크는 테이블 단위로 활성화돼요. 테이블에서 특정 태스크 유형(예: myTask)을 활성화하려면 테이블 설정에 태스크 유형을 포함하도록 업데이트하세요:
{
...
"task": {
"taskTypeConfigsMap": {
"myTask": {
"myProperty1": "value1",
"myProperty2": "value2"
}
}
}
}
각 활성화된 태스크 유형 아래에서 태스크 유형에 대한 커스텀 속성을 구성할 수 있어요.
같은 task 블록에서 concurrentSchedulingEnabled를 설정해 테이블에 대한 Pinot의 태스크 생성 스케줄링 방식을 재정의할 수도 있어요:
{
...
"task": {
"concurrentSchedulingEnabled": true,
"taskTypeConfigsMap": {
"myTask": {
"myProperty1": "value1"
}
}
}
}
concurrentSchedulingEnabled를 다음과 같이 사용하세요:
null또는 생략:controller.task.concurrentSchedulingEnabled에서 클러스터 기본값을 상속true: 이 테이블을 동시 태스크 스케줄링에 옵트인false: 클러스터 기본값이 동시여도 이 테이블에 레거시 직렬화된 스케줄링 경로를 강제
또한 클러스터 구성의 일부로 설정해야 하는 두 개의 태스크 설정이 있어요. 하나는 태스크의 전체 타임아웃(기본 1시간), 다른 하나는 단일 minion 워커에서 실행할 태스크 수(기본 1)를 제어해요.
Using "POST /cluster/configs" API on CLUSTER tab in Swagger, with this payload
{
"RealtimeToOfflineSegmentsTask.timeoutMs": "600000",
"RealtimeToOfflineSegmentsTask.numConcurrentTasksPerInstance": "4"
}
태스크 스케줄링 (Schedule tasks)
자동 스케줄 (Auto-schedule)
태스크 스케줄링을 활성화하는 방법은 두 가지가 있어요:
모든 minion 태스크에 대한 Controller 수준 스케줄
활성화된 모든 테이블의 모든 태스크 유형에 대해 태스크를 주기적으로 스케줄할 수 있어요. controller.task.frequencyPeriod 키로 controller 설정에서 스케줄 빈도를 구성해 자동 태스크 스케줄링을 활성화하세요. 이 값은 2h, 30m, 1d 같은 기간 문자열을 받아요.
PinotTaskManager가 서로 다른 테이블에 대한 태스크를 병렬로 생성하게 하려면 분산 잠금을 먼저 활성화한 다음 동시 스케줄링을 활성화하세요:
controller.task.enableDistributedLocking=true
controller.task.concurrentSchedulingEnabled=true
클러스터 기본값을 직렬화된 상태로 유지하려면 controller.task.concurrentSchedulingEnabled=false로 두고 task.concurrentSchedulingEnabled=true로 개별 테이블을 옵트인하세요. Pinot는 스케줄링 요청이 대상으로 하는 모든 테이블이 동시 스케줄링으로 해석되는 경우에만 동시 경로를 사용해요.
테이블 및 태스크 수준 스케줄
태스크는 cron 표현식을 기반으로도 스케줄할 수 있어요. cron 표현식은 각 태스크 유형의 schedule 설정에 별도로 설정돼요. cron 스케줄링을 활성화하려면 controller 설정의 controller.task.scheduler.enabled를 true로 설정해야 해요.
아래와 같이 RealtimeToOfflineSegmentsTask는 매분의 첫 번째 초에 스케줄됩니다(여기 정의된 문법에 따름).
"task": {
"taskTypeConfigsMap": {
"RealtimeToOfflineSegmentsTask": {
"bucketTimePeriod": "1h",
"bufferTimePeriod": "1h",
"schedule": "0 * * * * ?"
}
}
},
수동 스케줄 (Manual schedule)
다음 controller REST API를 사용해 태스크를 수동으로 스케줄할 수 있어요:
| REST API | 설명 |
|---|---|
| POST /tasks/schedule | 모든 활성화된 테이블의 모든 태스크 유형에 대한 태스크 스케줄 |
| POST /tasks/schedule?taskType=myTask | 모든 활성화된 테이블에서 주어진 태스크 유형에 대한 태스크 스케줄 |
| POST /tasks/schedule?tableName=myTable_OFFLINE | 주어진 테이블의 모든 태스크 유형에 대한 태스크 스케줄 |
| POST /tasks/schedule?taskType=myTask&tableName=myTable_OFFLINE | 주어진 테이블에서 주어진 태스크 유형에 대한 태스크 스케줄 |
특정 인스턴스에 태스크 스케줄
태스크 수준에서 다음 설정을 사용해 특정 인스턴스에 태스크를 스케줄할 수 있어요:
"task": {
"taskTypeConfigsMap": {
"RealtimeToOfflineSegmentsTask": {
"bucketTimePeriod": "1h",
"bufferTimePeriod": "1h",
"schedule": "0 * * * * ?",
"minionInstanceTag": "tag1_MINION"
}
}
},
기본적으로 하위 호환성을 위해 값은 minion_untagged예요. 이를 통해 사용자는 특정 노드에 태스크를 스케줄하고 테이블/태스크 유형 간에 태스크를 격리할 수 있어요.
| REST API | 설명 |
|---|---|
| POST /tasks/schedule?taskType=myTask&tableName=myTable_OFFLINE&minionInstanceTag=tag1_MINION | 주어진 테이블의 주어진 태스크 유형에 대한 태스크를 tag1_MINION으로 태그된 minion 노드에 스케줄 |
태스크 수준 고급 설정 (Task level advanced configs)
allowDownloadFromServer
태스크가 세그먼트에서 실행될 때 minion 노드는 deepstore에서 세그먼트를 가져와요. deepstore에 접근할 수 없으면 minion 노드는 서버 노드에서 세그먼트를 다운로드할 수 있어요. 이는 태스크 설정의 allowDownloadFromServer 설정으로 제어되며, 기본값은 false예요.
이 설정을 minion 인스턴스 수준 pinot.minion.task.allow.download.from.server(기본 false)로도 설정할 수 있어요. 이 인스턴스 수준 설정은 테이블/태스크 수가 많고 모두에 대해 활성화하고 싶을 때 이 동작을 강제하는 데 도움이 돼요. 참고: 태스크 수준 설정이 인스턴스 수준 설정 값을 재정의해요.
커스텀 태스크 플러그인 (Plug-in custom tasks)
커스텀 태스크를 플러그인하려면 해당 태스크 유형에 대해 PinotTaskGenerator, PinotTaskExecutorFactory, MinionEventObserverFactory(선택)를 구현하고(모두 getTaskType()에 대해 같은 문자열을 반환해야 함) 다음 어노테이션으로 표시하세요:
| 구현 | 어노테이션 |
|---|---|
| PinotTaskGenerator | @TaskGenerator |
| PinotTaskExecutorFactory | @TaskExecutorFactory |
| MinionEventObserverFactory | @EventObserverFactory |
클래스를 어노테이션한 후 org.apache.pinot.*.plugin.minion.tasks.* 이름의 패키지 아래에 넣으면 controller와 minion이 자동으로 등록해요.
예제
TestTask가 플러그인된 SimpleMinionClusterIntegrationTest를 참조하세요.
태스크 매니저 UI (Task Manager UI)
Pinot Data Explorer에서 왼쪽 탐색의 Minion Tasks를 선택하면 Minion Task Manager 페이지가 열려요. 이 페이지는 minion 큐 문제 해결과 태스크 드릴다운에 초점을 맞춰요. Controller 차원의 스케줄러 세부 사항은 Cluster Manager 페이지에 있으며, Cron Scheduler Information과 Periodic Tasks가 별도로 표시돼요.
Minion Task Manager 랜딩 페이지는 네 개의 요약 타일을 보여줘요:
- Task Types
- Minion Instances
- Running Tasks
- Waiting Tasks
요약 타일 아래에는 태스크 큐 테이블이 있어요. 이 테이블은 어떤 태스크 유형이 Helix에서 활성인지 보여주고 각 큐로 드릴다운할 수 있게 해줘요.
이것은 어떤 유형의 Minion Task가 사용되었는지, 즉 어떤 태스크 유형이 Helix에 태스크 큐를 만들었는지 보여줘요.

태스크 유형을 클릭하면 해당 태스크 유형을 사용하는 테이블과 함께 큐 중지, 정리 같은 큐 관리 작업이 표시돼요.

이 목록에서 아무 테이블을 클릭하면 해당 테이블에 대해 태스크가 어떻게 구성됐는지, 그리고 ZK에 태스크 메타데이터가 있다면 그것을 볼 수 있어요. 예를 들어 MergeRollupTask는 ZK에 워터마크를 추적해요. 태스크가 cron 스케줄이라면 현재와 다음 스케줄도 아래와 같이 이 페이지에 표시돼요.


이 페이지 맨 아래에는 이 테이블에 대해 이 특정 태스크 유형으로 생성된 태스크 목록이 있어요. 여기처럼 MergeRollup 태스크 하나가 생성되어 완료됐어요. 태스크 목록에는 Status Filter 컨트롤도 있어 단일 태스크 상태에 집중할 수 있고, 각 태스크의 서브태스크를 요약하는 Sub Tasks (Total/Completed/Running/Waiting/Error/Other) 칼럼도 있어요. Other 버킷은 UNKNOWN, DROPPED, TIMED_OUT, ABORTED 서브태스크를 결합해요.
태스크를 클릭하면 시작/종료 시간, 런타임 구성, 그리고 큐에서 태스크와 그 서브태스크를 제거하는 Delete Task 작업이 있는 Operations 아코디언을 포함한 태스크 상세가 열려요. 태스크 상세 페이지는 그 태스크에 대해 생성된 서브태스크도 나열해요 (컨텍스트로, 하나의 minion 태스크는 데이터를 병렬로 처리하기 위해 여러 서브태스크를 가질 수 있어요). 서브태스크 테이블에는 자체 Status Filter 컨트롤이 있는데, 태스크 팬아웃이 여러 minion 워커에 걸쳐 많은 서브태스크를 만들 때 유용해요. 이 예에서는 서브태스크가 하나 있었고, 언제 시작하고 멈추며 어떤 minion 워커에서 실행되는지 보여줘요.

이 서브태스크를 클릭하면 입력 태스크 설정, 진행 상황, 태스크가 실패했다면 오류 정보 같은 더 많은 세부 사항이 표시돼요. 서브태스크가 이미 minion 워커에 할당됐다면 페이지에 Minion Log Files 패널이 포함되어 파일 목록을 새로 고치고 UI에서 직접 해당 minion의 로그를 다운로드할 수 있어요.

태스크 관련 메트릭 (Task-related metrics)
controller.minion.task.metrics.emitter.frequencyPeriod로 제어되는 controller 작업이 기본적으로 5분마다 실행되며 Pinot에서 스케줄된 Minion 태스크에 대한 메트릭을 방출해요. 각 태스크 유형에 대해 다음 메트릭이 방출돼요:
- NumMinionTasksInProgress: 실행 중인 태스크 수
- NumMinionSubtasksRunning: 실행 중인 서브태스크 수
- NumMinionSubtasksWaiting: 대기 중인 서브태스크 수 (아직 minion에 할당되지 않음)
- NumMinionSubtasksError: 오류 서브태스크 수 (오류/예외로 완료)
- PercentMinionSubtasksInQueue: 대기 또는 실행 상태의 서브태스크 비율
- PercentMinionSubtasksInError: 오류 상태의 서브태스크 비율
- MaxSubtaskWaitTimeMs:
WAITING상태의 서브태스크 중 현재 최장 대기 시간을 나타내는 테이블별·태스크 유형별 controller 게이지. 대기 서브태스크가 없으면 Pinot가0을 방출하므로 큐가 비워지면 알림이 스스로 해소될 수 있어요. - MaxSubtaskRunningTimeMs:
RUNNING상태의 서브태스크 중 현재 최장 실행 시간을 나타내는 테이블별·태스크 유형별 controller 게이지. 실행 서브태스크가 없으면 Pinot가0을 방출해요.
Controller는 또한 태스크가 cron으로 스케줄되는 방식에 대한 메트릭을 방출해요:
- cronSchedulerJobScheduled: cron 표현식에 따라 주기적으로 트리거되도록 등록된 현재 cron 스케줄 수. Gauge.
- cronSchedulerJobTrigger: 트리거된 cron 스케줄 수. Meter.
- cronSchedulerJobSkipped: 늦게 스킵된 cron 스케줄 수. Meter.
- cronSchedulerJobExecutionTimeMs: 태스크 생성 완료에 사용된 시간. Timer.
각 태스크에 대해 minion은 다음 메트릭을 방출해요:
- TASK_QUEUEING: 태스크 큐잉 시간 (task_dequeue_time - task_inqueue_time). helix controller와 pinot minion 사이의 시간 드리프트가 작다고 가정하며, 그렇지 않으면 값이 음수가 될 수 있어요.
- TASK_EXECUTION: 태스크 실행 시간, 즉 태스크 실행에 소요된 시간
- NUMBER_OF_TASKS: 해당 minion에서 진행 중인 태스크 수. Minion이 태스크를 시작할 때마다 Gauge를 1 증가, 완료(성공 또는 실패)할 때마다 1 감소.
- NUMBER_TASKS_EXECUTED: 실행된 태스크 수. Meter.
- NUMBER_TASKS_COMPLETED: 완료된 태스크 수. Meter.
- NUMBER_TASKS_CANCELLED: 취소된 태스크 수. Meter.
- NUMBER_TASKS_FAILED: 실패한 태스크 수. Meter. 치명적 실패와 달리, 태스크가 이 실행에서 복구할 수 없는 오류를 만났지만 재시도하면 성공할 수 있어요.
- NUMBER_TASKS_FATAL_FAILED: 치명적으로 실패한 태스크 수. Meter. 실패와 달리, 태스크가 재시도해도 복구되지 않을 오류를 만났어요.