Files
tasks/chasm/lib/scheduler/proto/v1/service.proto
Alex StanfieldandGitHub 223478bf8f V1 to CHASM scheduler migration RPC (#9261)
## What changed

Adds an admin RPC (`MigrateSchedule`) that migrates workflow-backed (V1)
schedulers to CHASM (V2) schedulers.

The flow:
1. Admin API signals the V1 scheduler workflow with `migrate-to-chasm`
2. V1 workflow runs a local activity that snapshots state and calls
`CreateFromMigrationState` on the CHASM scheduler service
3. On success, the V1 workflow closes. On failure, a `PendingMigration`
flag persists so the next run loop iteration retries automatically

Key details:
- `CreateSchedulerFromMigration` initializes the full CHASM scheduler
tree (generator, invoker, backfillers, visibility) from V1 state
- Running/completed workflows are converted to buffered starts; ongoing
backfills are preserved
- Migration is idempotent -- if the CHASM schedule already exists, it's
treated as success
- Metrics: `schedule_migration_started`, `schedule_migration_completed`,
`schedule_migration_failed` (with direction tag)
- Local activity uses 10m schedule-to-close timeout; retries happen at
the workflow level via the persistent flag

## Why

Needed for migrating existing V1 schedulers to CHASM without downtime or
data loss.

## Follow-up items

- V2 to V1 migration (rollback path)
- Sentinel key handling when `EnableCHASMSchedulerCreation` was
previously enabled
- Attach completion callbacks to running workflows after migration
2026-03-12 10:18:02 -05:00

45 lines
2.3 KiB
Protocol Buffer

syntax = "proto3";
package temporal.server.chasm.lib.scheduler.proto.v1;
option go_package = "go.temporal.io/server/chasm/lib/scheduler/gen/schedulerpb;schedulerpb";
import "chasm/lib/scheduler/proto/v1/request_response.proto";
import "temporal/server/api/routing/v1/extension.proto";
import "temporal/server/api/common/v1/api_category.proto";
service SchedulerService {
rpc CreateSchedule(CreateScheduleRequest) returns (CreateScheduleResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc UpdateSchedule(UpdateScheduleRequest) returns (UpdateScheduleResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc PatchSchedule(PatchScheduleRequest) returns (PatchScheduleResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc DeleteSchedule(DeleteScheduleRequest) returns (DeleteScheduleResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc DescribeSchedule(DescribeScheduleRequest) returns (DescribeScheduleResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc ListScheduleMatchingTimes(ListScheduleMatchingTimesRequest) returns (ListScheduleMatchingTimesResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "frontend_request.schedule_id";
option (temporal.server.api.common.v1.api_category).category = API_CATEGORY_STANDARD;
}
rpc CreateFromMigrationState(CreateFromMigrationStateRequest) returns (CreateFromMigrationStateResponse) {
option (temporal.server.api.routing.v1.routing).business_id = "state.scheduler_state.schedule_id";
}
}