Add tdbg command for 'schedule migrate' (#9502)

## What changed?
- Added the 'tdbg schedule migrate' command

## Why?
- Allows us an operator to manually trigger a migration (roll forward or
backward) to a schedule via tdbg CLI

## How did you test it?
- Tested manually with V1->CHASM direction. Verified (via `temporal` and
`tdbg`) CHASM scheduler was created, V1 scheduler workflow closed
successfully.
This commit is contained in:
Lina Jodoin
2026-03-16 19:40:23 +00:00
committed by GitHub
parent 9423581a49
commit 42f08e06db
3 changed files with 78 additions and 0 deletions
+44
View File
@@ -8,6 +8,7 @@ import (
"time"
"github.com/fatih/color"
"github.com/google/uuid"
"github.com/urfave/cli/v2"
commonpb "go.temporal.io/api/common/v1"
historypb "go.temporal.io/api/history/v1"
@@ -866,3 +867,46 @@ func AdminReplicateWorkflow(
fmt.Fprintln(c.App.Writer, "Replication tasks generated successfully.")
return nil
}
// AdminMigrateSchedule migrates a schedule between V1 (workflow-backed) and V2 (CHASM).
func AdminMigrateSchedule(c *cli.Context, clientFactory ClientFactory) error {
ns, err := getRequiredOption(c, FlagNamespace)
if err != nil {
return err
}
scheduleID, err := getRequiredOption(c, FlagScheduleID)
if err != nil {
return err
}
targetStr, err := getRequiredOption(c, FlagTarget)
if err != nil {
return err
}
var target adminservice.MigrateScheduleRequest_SchedulerTarget
switch strings.ToLower(targetStr) {
case "chasm":
target = adminservice.MigrateScheduleRequest_SCHEDULER_TARGET_CHASM
case "workflow":
target = adminservice.MigrateScheduleRequest_SCHEDULER_TARGET_WORKFLOW
default:
return fmt.Errorf("invalid target %q, valid values are: chasm, workflow", targetStr)
}
adminClient := clientFactory.AdminClient(c)
ctx, cancel := newContext(c)
defer cancel()
_, err = adminClient.MigrateSchedule(ctx, &adminservice.MigrateScheduleRequest{
Namespace: ns,
ScheduleId: scheduleID,
Target: target,
Identity: getCurrentUserFromEnv(),
RequestId: uuid.NewString(),
})
if err != nil {
return fmt.Errorf("unable to migrate schedule: %w", err)
}
_, _ = fmt.Fprintf(c.App.Writer, "Successfully initiated migration of schedule %q in namespace %q to %s.\n", scheduleID, ns, targetStr)
return nil
}
+3
View File
@@ -76,4 +76,7 @@ var (
FlagVisibilityQuery = "query"
FlagJobID = "job-id"
FlagDecode = "decode"
FlagScheduleID = "schedule-id"
FlagScheduleIDAlias = []string{"sid"}
FlagTarget = "target"
)
+31
View File
@@ -64,6 +64,12 @@ func getCommands(
},
},
},
{
Name: "schedule",
Aliases: []string{"sch"},
Usage: "Run admin operation on a schedule",
Subcommands: newAdminScheduleCommands(clientFactory),
},
{
Name: "decode",
Usage: "Decode payload",
@@ -275,6 +281,31 @@ func newAdminExecutionCommands(clientFactory ClientFactory, prompterFactory Prom
}
}
func newAdminScheduleCommands(clientFactory ClientFactory) []*cli.Command {
return []*cli.Command{
{
Name: "migrate",
Usage: "Migrate a schedule between V1 (workflow-backed) and V2 (CHASM)",
Flags: []cli.Flag{
&cli.StringFlag{
Name: FlagScheduleID,
Aliases: FlagScheduleIDAlias,
Usage: "Schedule ID",
Required: true,
},
&cli.StringFlag{
Name: FlagTarget,
Usage: "Target scheduler implementation: chasm, workflow",
Required: true,
},
},
Action: func(c *cli.Context) error {
return AdminMigrateSchedule(c, clientFactory)
},
},
}
}
func newAdminShardManagementCommands(clientFactory ClientFactory, taskCategoryRegistry tasks.TaskCategoryRegistry) []*cli.Command {
// There are two different categories for the task type, and they have slightly
// different semantics. The first is the task category for the list-tasks command,