Minion Task Plugin
Write a custom Minion task plugin with a task generator and task executor.
Minion tasks execute background maintenance and data processing jobs in Pinot. Each task type has two components: a Task Generator (runs on the Controller) that creates task configurations, and a Task Executor (runs on the Minion) that performs the work.
Architecture
Controller Minion
┌────────────────────┐ ┌────────────────────┐
│ PinotTaskGenerator│ ─ Helix ─> │ PinotTaskExecutor │
│ - generateTasks() │ schedules │ - executeTask() │
│ - getTaskType() │ │ - cancel() │
└────────────────────┘ └────────────────────┘The Controller runs the Task Generator on a schedule or via ad-hoc API call
The Generator creates
PinotTaskConfigobjects describing the workThe Controller schedules tasks via Helix
Minion instances pick up tasks based on tag/routing
The Minion executes the task using the Task Executor
Results are returned to the Controller
Step 1: Implement the Task Executor
The executor runs on the Minion and performs the actual work.
Task Executor Factory
Task Executor
Safely replace a segment with metadata push
If a custom task extends BaseSingleSegmentConversionExecutor, rebuilds a segment under the same segment name, and uses push.mode=METADATA, opt in to controller-side copying:
Also provide output.segment.dir.uri in each task configuration. The Minion uses this location to stage the converted segment, and the Controller must be able to access both the staging location and the table's deep store.
This opt-in path preserves the existing segment download URL. The Minion stages the replacement with a task-specific name, sends the original segment CRC and refresh-only guard to the Controller, and asks the Controller to copy the staged data into the segment's existing deep-store location. After the request completes or fails, the Minion deletes the staged file. A retry of the same task can overwrite its own leftover staging file.
If conversion produces the same CRC as the original segment, Pinot does not stage or copy segment data. It only refreshes the segment metadata against the existing download URL.
Override this method only for same-name replacement tasks. It defaults to false, so existing tasks—including PurgeTask, RefreshSegmentTask, and UpsertCompactionTask—keep their current metadata-push behavior unless their executor explicitly opts in.
Step 2: Implement the Task Generator
The generator runs on the Controller and decides when and how to create tasks.
Optional Generator Overrides
getTaskTimeoutMs(String minionTag)
3,600,000 (1 hour)
Task timeout in milliseconds
getNumConcurrentTasksPerInstance(String minionTag)
1
Max concurrent tasks per Minion
getMaxAttemptsPerTask(String minionTag)
1 (no retry)
Max retry attempts
getMinionInstanceTag(TableConfig tableConfig)
UNTAGGED_MINION_INSTANCE
Tag for routing tasks to specific Minion instances
validateTaskConfigs(TableConfig, Schema, Map)
no-op
Validate task-specific configs at table creation time
Step 3: Enable the Task in Table Config
Add the task configuration to the table config:
The schedule property uses a CRON expression to define when the task generator runs. Without it, the task can only be triggered via the Controller API.
Step 4: Trigger Tasks via API
To manually trigger task generation:
Built-in Task Types
Pinot includes several built-in Minion tasks:
RealtimeToOfflineSegmentsTask
Converts realtime segments to offline segments
UpsertCompactionTask
Compacts segments in upsert-enabled tables
UpsertCompactMergeTask
Merges and compacts upsert segments
PurgeTask
Purges records matching a purge function
MergeRollupTask
Merges and rolls up small segments
SegmentGenerationAndPushTask
Generates and pushes segments from external data
RefreshSegmentTask
Refreshes segments from deep store
For more details on built-in tasks, see Minion Merge Rollup Task and Upsert Compaction Task.
Last updated
Was this helpful?

