Implementation:TobikoData Sqlmesh Tracker Plan Apply
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, Data_Model, Plan_Management, State_Tracking |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
A TypeScript class that tracks the real-time progress and state of SQLMesh plan apply operations.
Description
ModelPlanApplyTracker extends the base plan tracker to specifically monitor plan application execution, including creation, restate, backfill, and promote stages. It maintains both current and last completed execution states, integrates with ModelPlanOverviewTracker to access plan change details, and provides computed properties for accessing tasks, queues, stage metadata, and evaluation timings.
The tracker handles incremental updates from WebSocket channels, preserving stage information until completion, and provides snapshot capabilities for displaying historical execution states. It manages the task queue showing currently processing models and exposes filtered lists of added/removed/direct/indirect/metadata changes from the associated plan overview.
Usage
Use this tracker in the Plan page to monitor plan apply operations. It's updated via WebSocket messages from the backend plan-apply channel and provides the data needed to render progress bars, task lists, and stage completion indicators.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/models/tracker-plan-apply.ts
Signature
export class ModelPlanApplyTracker
extends ModelPlanTracker<PlanApplyTracker>
implements InitialModelPlanApplyTracker
{
constructor(model?: ModelPlanApplyTracker)
// Current state accessors
get current(): Optional<PlanApplyTracker>
get environment(): Optional<string>
get meta(): Optional<TrackableMeta>
get plan_options(): Optional<PlanOptions>
get start(): Optional<PlanOverviewStageTrackerStart>
get end(): Optional<PlanOverviewStageTrackerEnd>
// Plan overview integration
get overview(): Optional<ModelPlanOverviewTracker>
get backfills(): ModelSQLMeshChangeDisplay[]
get added(): ModelSQLMeshChangeDisplay[]
get removed(): ModelSQLMeshChangeDisplay[]
get direct(): ModelSQLMeshChangeDisplay[]
get indirect(): ModelSQLMeshChangeDisplay[]
get metadata(): ModelSQLMeshChangeDisplay[]
// Task tracking
get tasks(): Record<string, ModelSQLMeshChangeDisplay>
get queue(): ModelSQLMeshChangeDisplay[]
// Stage accessors
get stageValidation(): Optional<PlanStageValidation>
get stageChanges(): Optional<PlanStageChanges>
get stageBackfills(): Optional<PlanStageBackfills>
get stageCreation(): Optional<PlanStageCreation>
get stageRestate(): Optional<PlanStageRestate>
get stageBackfill(): Optional<PlanStageBackfill>
get stagePromote(): Optional<PlanStagePromote>
// Evaluation metadata
get shouldShowEvaluation(): boolean
get evaluationStart(): Optional<PlanOverviewStageTrackerStart>
get evaluationEnd(): Optional<PlanOverviewStageTrackerEnd>
// State management
update(tracker: PlanApplyTracker, planOverview?: ModelPlanOverviewTracker): void
reset(): void
clear(): void
clone(): ModelPlanApplyTracker
}
export interface PlanApplyTracker extends PlanTracker {
creation?: PlanStageCreation
restate?: PlanStageRestate
backfill?: PlanStageBackfill
promote?: PlanStagePromote
}
Import
import { ModelPlanApplyTracker } from '@models/tracker-plan-apply'
I/O Contract
Constructor Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| model | ModelPlanApplyTracker | No | Existing tracker instance to clone |
Key Properties
| Name | Type | Description |
|---|---|---|
| current | PlanApplyTracker | Current or last execution state |
| environment | string | Target environment name |
| meta | TrackableMeta | Execution metadata (done, status, start, end times) |
| tasks | Record<string, ModelSQLMeshChangeDisplay> | All tasks by model name (URL encoded keys) |
| queue | ModelSQLMeshChangeDisplay[] | Currently executing tasks |
| overview | ModelPlanOverviewTracker | Associated plan overview data |
| stageCreation | PlanStageCreation | Snapshot creation stage |
| stageRestate | PlanStageRestate | Restate stage |
| stageBackfill | PlanStageBackfill | Backfill stage with task details |
| stagePromote | PlanStagePromote | Environment promotion stage |
| shouldShowEvaluation | boolean | Whether evaluation stages should be displayed |
Methods
| Name | Parameters | Description |
|---|---|---|
| update | tracker, planOverview | Update tracker with new data from WebSocket |
| reset | - | Clear current execution, keep last |
| clear | - | Clear all execution data |
| clone | - | Create deep copy of tracker |
Usage Examples
// Initialize tracker in plan store
const planApply = new ModelPlanApplyTracker()
// Update from WebSocket channel
channel?.('plan-apply', (data: PlanApplyTracker) => {
planApply.update(data, planOverview)
setPlanApply(planApply)
})
// Display task overview
<TasksOverview tasks={planApply.tasks}>
{({ completed, total, completedBatches, totalBatches }) => (
<TasksSummary
headline="Applying Changes"
environment={planApply.environment}
completed={completed}
total={total}
completedBatches={completedBatches}
totalBatches={totalBatches}
updateType="Backfill"
updatedAt={planApply.end}
/>
)}
</TasksOverview>
// Show currently processing tasks
{planApply.queue.map(task => (
<TaskItem
key={task.name}
name={task.displayViewName}
progress={toRatio(task.completed, task.total)}
/>
))}
// Display stage information
{planApply.shouldShowEvaluation && (
<div>
<h3>Evaluation Stages</h3>
{planApply.stageCreation && (
<Stage name="Creation" meta={planApply.stageCreation.meta} />
)}
{planApply.stageBackfill && (
<Stage
name="Backfill"
meta={planApply.stageBackfill.meta}
progress={
Object.values(planApply.tasks).filter(t => t.completed === t.total).length /
Object.values(planApply.tasks).length
}
/>
)}
{planApply.stagePromote && (
<Stage name="Promote" meta={planApply.stagePromote.meta} />
)}
</div>
)}
// Check if plan is complete
if (planApply.isFinished) {
console.log('Plan apply completed')
console.log('Duration:', planApply.evaluationEnd - planApply.evaluationStart)
}
// Clone for historical comparison
const snapshot = planApply.clone()
// Reset after viewing results
planApply.reset() // Clears current, keeps last execution
// Full cleanup
planApply.clear() // Clears everything
State Lifecycle
1. Initial State: Tracker created with no data 2. First Update: WebSocket sends initial plan apply data, `_current` is set 3. Incremental Updates: Stages are updated as they complete, `_current` accumulates changes 4. Completion: When `meta.done === true`, `_current` moves to `_last`, `_current` becomes undefined 5. Subsequent Applies: New execution creates new `_current`, preserving `_last` for comparison