tdbg_commands.go ×12

Frontier kind: Code frontier

unlabeled · c_c9cf61e2f1f8

42 tests · 3180 LOC · 139 files · introduces 0 tests · 481 LOC · 6 files

Introduces — evidence that enters the hierarchy at this concept

Code
24 ranges481 lines · 6 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
390 ranges3180 lines · 139 files · Browse complete extent
All tests (intent)
42 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

6 files ranked by introduced lines: 481 introduced LOC across 24 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

go.temporal.io/server/tools/tdbg/tdbg_commands.go 340 introduced LOC · 12 ranges

Open complete file

21 prompterFactory PrompterFactory,
22 taskBlobEncoder TaskBlobEncoder,
23 > ) []*cli.Command { tdbg_commands.go
24 > return []*cli.Command{
25 > {
26 > Name: "execution",
27 > Aliases: []string{"e", "w", "workflow"},
28 > Usage: "Run admin operation on an execution (workflow)",
29 > Subcommands: newAdminExecutionCommands(clientFactory, prompterFactory),
30 > },
31 > {
32 > Name: "shard",
33 > Aliases: []string{"s"},
34 > Usage: "Run admin operation on specific shard",
35 > Subcommands: newAdminShardManagementCommands(clientFactory, taskCategoryRegistry),
36 > },
37 > {
38 > Name: "history-host",
39 > Aliases: []string{"hh"},
40 > Usage: "Run admin operation on history host",
41 > Subcommands: newAdminHistoryHostCommands(clientFactory),
42 > },
43 > {
44 > Name: "taskqueue",
45 > Aliases: []string{"tq"},
46 > Usage: "Run admin operation on taskQueue",
47 > Subcommands: newAdminTaskQueueCommands(clientFactory),
48 > },
49 > {
50 > Name: "membership",
51 > Aliases: []string{"m"},
52 > Usage: "Run admin operation on membership",
53 > Subcommands: newAdminMembershipCommands(clientFactory),
54 > },
55 > {
56 > Name: "dlq",
57 > Usage: "Run admin operation on DLQ",
58 > Subcommands: newAdminDLQCommands(dlqServiceProvider, taskCategoryRegistry),
59 > Flags: []cli.Flag{
60 > &cli.StringFlag{
61 > Name: FlagDLQVersion,
62 > Usage: "Version of DLQ to manage, options: v1, v2",
63 > Value: "v2",
64 > },
65 > },
66 > },
67 > {
68 > Name: "schedule",
69 > Aliases: []string{"sch"},
70 > Usage: "Run admin operation on a schedule",
71 > Subcommands: newAdminScheduleCommands(clientFactory),
72 > },
73 > {
74 > Name: "decode",
75 > Usage: "Decode payload",
76 > Subcommands: newDecodeCommands(taskBlobEncoder),
77 > },
78 > }
79 > }
80
81 > func newAdminExecutionCommands(clientFactory ClientFactory, prompterFactory PrompterFactory) []*cli.Command { tdbg_commands.go
82 > return []*cli.Command{
83 > {
84 > Name: "import",
85 > Usage: "import workflow history to database",
86 > Flags: []cli.Flag{
87 > &cli.StringFlag{
88 > Name: FlagWorkflowID,
89 > Aliases: FlagWorkflowIDAlias,
90 > Usage: "Workflow ID",
91 > },
92 > &cli.StringFlag{
93 > Name: FlagRunID,
94 > Aliases: FlagRunIDAlias,
95 > Usage: "Run ID",
96 > },
97 > &cli.StringFlag{
98 > Name: FlagInputFilename,
99 > Usage: "input file",
100 > }},
101 > Action: func(c *cli.Context) error {
102 return AdminImportWorkflow(c, clientFactory)
103 },
298 }
299
300 > func newAdminScheduleCommands(clientFactory ClientFactory) []*cli.Command { tdbg_commands.go
301 > return []*cli.Command{
302 > {
303 > Name: "migrate",
304 > Usage: "Migrate a schedule between V1 (workflow-backed) and V2 (CHASM)",
305 > Flags: []cli.Flag{
306 > &cli.StringFlag{
307 > Name: FlagScheduleID,
308 > Aliases: FlagScheduleIDAlias,
309 > Usage: "Schedule ID (single-schedule mode)",
310 > },
311 > &cli.StringFlag{
312 > Name: FlagTarget,
313 > // Not marked Required here: it is validated (and required) by
314 > // parseMigrateTarget when the migrate action itself runs. Marking it
315 > // Required at the CLI level would also apply to the "status" subcommand
316 > // below, which has no use for --target.
317 > Usage: "Target scheduler implementation: chasm, workflow",
318 > },
319 > &cli.BoolFlag{
320 > Name: FlagFromVisibility,
321 > Usage: "Select schedules from visibility instead of --schedule-id, scoped to --namespace. " +
322 > "The default query is chosen from --target: migrating to chasm selects running V1 schedules, " +
323 > "migrating to workflow selects running V2 schedules. Override with --query",
324 > },
325 > &cli.StringFlag{
326 > Name: FlagVisibilityQuery,
327 > Usage: "Visibility query used with --from-visibility, overriding the target-based default. The defaults are:\n" +
328 > "\tV1 (workflow-backed): TemporalNamespaceDivision = 'TemporalScheduler' AND ExecutionStatus = 'Running'\n" +
329 > "\tV2 (CHASM): TemporalNamespaceDivision = '<scheduler-archetype-id>' AND ExecutionStatus = 'Running'",
330 > },
331 > &cli.BoolFlag{
332 > Name: FlagExecute,
333 > Usage: "Perform the migration. Without this flag, --from-visibility and stdin modes only print what they would do (dry-run)",
334 > },
335 > &cli.IntFlag{
336 > Name: FlagWorkers,
337 > Value: defaultMigrateWorkers,
338 > Usage: "Number of concurrent workers migrating schedules in --from-visibility and stdin modes",
339 > },
340 > &cli.StringFlag{
341 > Name: FlagOutputLog,
342 > Usage: "Path to write a structured (JSON lines) log of each migration result in --from-visibility and stdin modes",
343 > },
344 > },
345 > Action: func(c *cli.Context) error {
346 return AdminMigrateSchedule(c, clientFactory)
347 },
359 }
360
361 > func newAdminShardManagementCommands(clientFactory ClientFactory, taskCategoryRegistry tasks.TaskCategoryRegistry) []*cli.Command { tdbg_commands.go
362 > // There are two different categories for the task type, and they have slightly
363 > // different semantics. The first is the task category for the list-tasks command,
364 > // which is required and does not have a default. The second is the task category
365 > // for the remove-task command, which is optional and defaults to transfer.
366 > taskCategoryFlag := getTaskCategoryFlag(taskCategoryRegistry)
367 > return []*cli.Command{
368 > {
369 > Name: "describe",
370 > Aliases: []string{"d"},
371 > Usage: "Describe shard by ID",
372 > Flags: []cli.Flag{
373 > &cli.IntFlag{
374 > Name: FlagShardID,
375 > Usage: "The ID of the shard to describe",
376 > },
377 > },
378 > Action: func(c *cli.Context) error {
379 return AdminDescribeShard(c, clientFactory)
380 },
472 }
473
474 > func getTaskCategoryFlag(taskCategoryRegistry tasks.TaskCategoryRegistry) *cli.StringFlag { tdbg_commands.go
475 > categories := taskCategoryRegistry.GetCategories()
476 > options := make([]string, 0, len(categories))
477 > for _, category := range categories {
478 > options = append(options, category.Name())
479 > }
480 > flag := &cli.StringFlag{
481 > Name: FlagTaskCategory,
482 > Usage: "Task category: " + strings.Join(options, ", "),
483 > Required: true,
484 > }
485 > return flag
486 }
487
488 > func newAdminMembershipCommands(clientFactory ClientFactory) []*cli.Command { tdbg_commands.go
489 > return []*cli.Command{
490 > {
491 > Name: "list-gossip",
492 > Usage: "List ringpop membership items",
493 > Flags: []cli.Flag{
494 > &cli.StringFlag{
495 > Name: FlagClusterMembershipRole,
496 > Value: "all",
497 > Usage: "Membership role filter: all (default), frontend, history, matching, worker",
498 > },
499 > },
500 > Action: func(c *cli.Context) error {
501 return AdminListGossipMembers(c, clientFactory)
502 },
526 }
527
528 > func newAdminHistoryHostCommands(clientFactory ClientFactory) []*cli.Command { tdbg_commands.go
529 > return []*cli.Command{
530 > {
531 > Name: "describe",
532 > Aliases: []string{"d"},
533 > Usage: "Describe internal information of history host",
534 > Flags: []cli.Flag{
535 > &cli.StringFlag{
536 > Name: FlagWorkflowID,
537 > Aliases: FlagWorkflowIDAlias,
538 > Usage: "Workflow ID",
539 > },
540 > &cli.StringFlag{
541 > Name: FlagHistoryAddress,
542 > Usage: "History Host address(IP:PORT)",
543 > },
544 > &cli.IntFlag{
545 > Name: FlagShardID,
546 > Usage: "ShardId",
547 > },
548 > &cli.BoolFlag{
549 > Name: FlagPrintFullyDetail,
550 > Usage: "Print fully detail",
551 > },
552 > },
553 > Action: func(c *cli.Context) error {
554 return AdminDescribeHistoryHost(c, clientFactory)
555 },
580 }
581
582 > func newAdminTaskQueueCommands(clientFactory ClientFactory) []*cli.Command { tdbg_commands.go
583 > return []*cli.Command{
584 > {
585 > Name: "list-tasks",
586 > Usage: "List tasks of a task queue. Use --fair to list fairness tasks.",
587 > Flags: []cli.Flag{
588 > &cli.BoolFlag{
589 > Name: FlagMore,
590 > Usage: "List more pages, default is to list one page of default page size 10",
591 > },
592 > &cli.IntFlag{
593 > Name: FlagPageSize,
594 > Value: 10,
595 > Usage: "Result page size",
596 > },
597 > &cli.StringFlag{
598 > Name: FlagTaskQueueType,
599 > Value: "activity",
600 > Usage: "Task Queue type: activity, workflow",
601 > },
602 > &cli.StringFlag{
603 > Name: FlagTaskQueue,
604 > Usage: "Task Queue name",
605 > },
606 > &cli.Int64Flag{
607 > Name: FlagMinTaskID,
608 > Usage: "Minimum task ID",
609 > Value: -12346, // include default task id
610 > },
611 > &cli.Int64Flag{
612 > Name: FlagMaxTaskID,
613 > Usage: "Maximum task ID",
614 > },
615 > &cli.IntFlag{
616 > Name: FlagSubqueue,
617 > Usage: "Subqueue to query",
618 > Value: 0,
619 > },
620 > &cli.BoolFlag{
621 > Name: FlagPrintJSON,
622 > Usage: "Print in raw json format",
623 > },
624 > &cli.BoolFlag{
625 > Name: FlagFair,
626 > Usage: "Query fairness tasks",
627 > },
628 > &cli.Int64Flag{
629 > Name: FlagMinPass,
630 > Usage: "Minimum pass (fairness task only)",
631 > Value: 1,
632 > },
633 > },
634 > Action: func(c *cli.Context) error {
635 return AdminListTaskQueueTasks(c, clientFactory)
636 },
754 dlqServiceProvider *DLQServiceProvider,
755 taskCategoryRegistry tasks.TaskCategoryRegistry,
756 > ) []*cli.Command { tdbg_commands.go
757 > return []*cli.Command{
758 > {
759 > Name: "read",
760 > Aliases: []string{"r"},
761 > Usage: "Read DLQ Messages",
762 > Flags: append(
763 > getDLQFlags(taskCategoryRegistry),
764 > &cli.IntFlag{
765 > Name: FlagMaxMessageCount,
766 > Usage: fmt.Sprintf(
767 > "Max message size to fetch, defaults to %d for v2 and nothing for v1",
768 > dlqV2DefaultMaxMessageCount,
769 > ),
770 > },
771 > &cli.StringFlag{
772 > Name: FlagOutputFilename,
773 > Usage: "Output file to write to, if not provided output is written to stdout",
774 > },
775 > &cli.IntFlag{
776 > Name: FlagPageSize,
777 > Usage: "Page size to use when reading messages from the DB, v2 only",
778 > Value: defaultPageSize,
779 > },
780 > ),
781 > Action: func(c *cli.Context) error {
782 ac, err := dlqServiceProvider.GetDLQService(c)
783 if err != nil {
857 func newAdminDLQJobCommands(
858 dlqServiceProvider *DLQServiceProvider,
859 > ) []*cli.Command { tdbg_commands.go
860 > return []*cli.Command{
861 > {
862 > Name: "describe",
863 > Aliases: []string{"d"},
864 > Usage: "Get details of the DLQ job with provided job token",
865 > Description: "This command will get details of the DLQ job with provided job token if using v2",
866 > Flags: []cli.Flag{
867 > &cli.StringFlag{
868 > Name: FlagJobToken,
869 > Usage: "Token of the DLQ job. This token will be printed in the output of merge and purge commands",
870 > Required: true,
871 > },
872 > },
873 > Action: func(c *cli.Context) error {
874 ac := dlqServiceProvider.GetDLQJobService()
875 return ac.DescribeJob(c)
901 }
902
903 > func getDLQFlags(taskCategoryRegistry tasks.TaskCategoryRegistry) []cli.Flag { tdbg_commands.go
904 > categoriesString := getCategoriesList(taskCategoryRegistry)
905 > return []cli.Flag{
906 > &cli.StringFlag{
907 > Name: FlagDLQType,
908 > Usage: fmt.Sprintf(
909 > "Type of DLQ to manage, options: namespace, history for v1; %s for v2",
910 > categoriesString,
911 > ),
912 > },
913 > &cli.StringFlag{
914 > Name: FlagCluster,
915 > Usage: "Source cluster",
916 > },
917 > &cli.IntFlag{
918 > Name: FlagShardID,
919 > Usage: "ShardId, v1 only",
920 > },
921 > &cli.IntFlag{
922 > Name: FlagLastMessageID,
923 > Usage: "The upper boundary of messages to operate on. If not provided, all messages will be operated on. " +
924 > "However, you will be prompted for confirmation unless the --yes flag is also provided.",
925 > },
926 > &cli.StringFlag{
927 > Name: FlagTargetCluster,
928 > Usage: "Target cluster, v2 only. If not provided, current cluster is used.",
929 > },
930 > }
931 > }
932
933 func newDecodeCommands(
934 taskBlobEncoder TaskBlobEncoder,
935 > ) []*cli.Command { tdbg_commands.go
936 > return []*cli.Command{
937 > {
938 > Name: "proto",
939 > Usage: "Decode proto payload",
940 > Flags: []cli.Flag{
941 > &cli.StringFlag{
942 > Name: FlagProtoType,
943 > Usage: "full name of proto type to decode to (i.e. temporal.server.api.persistence.v1.WorkflowExecutionInfo).",
944 > },
945 > &cli.StringFlag{
946 > Name: FlagHexData,
947 > Usage: "data in hex format (i.e. 0x0a243462613036633466...).",
948 > },
949 > &cli.StringFlag{
950 > Name: FlagHexFile,
951 > Usage: "file with data in hex format (i.e. 0x0a243462613036633466...).",
952 > },
953 > &cli.StringFlag{
954 > Name: FlagBinaryFile,
955 > Usage: "file with data in binary format.",
956 > },
957 > },
958 > Action: func(c *cli.Context) error {
959 return AdminDecodeProto(c)
960 },
go.temporal.io/server/tools/tdbg/app.go 99 introduced LOC · 4 ranges

Open complete file

32
33 // NewCliApp instantiates a new instance of the CLI application.
34 > func NewCliApp(opts ...Option) *cli.App { app.go
35 > params := Params{
36 > ClientFactory: NewClientFactory(),
37 > TaskCategoryRegistry: tasks.NewDefaultTaskCategoryRegistry(),
38 > Writer: os.Stdout,
39 > ErrWriter: os.Stderr,
40 > TaskBlobEncoder: NewProtoTaskBlobEncoder(NewPredefinedTaskBlobDeserializer()),
41 > }
42 > for _, opt := range opts {
43 > opt(&params)
44 > }
45 > app := cli.NewApp()
46 > app.Name = "tdbg"
47 > app.Usage = "A command-line tool for Temporal server debugging"
48 > app.Version = headers.ServerVersion
49 > app.Flags = []cli.Flag{
50 > &cli.StringFlag{
51 > Name: FlagAddress,
52 > Value: "",
53 > Usage: "host:port for Temporal frontend service",
54 > EnvVars: []string{"TEMPORAL_CLI_ADDRESS"},
55 > },
56 > &cli.StringFlag{
57 > Name: FlagNamespace,
58 > Aliases: FlagNamespaceAlias,
59 > Value: "default",
60 > Usage: "Temporal workflow namespace",
61 > EnvVars: []string{"TEMPORAL_CLI_NAMESPACE"},
62 > },
63 > &cli.IntFlag{
64 > Name: FlagContextTimeout,
65 > Aliases: FlagContextTimeoutAlias,
66 > Value: defaultContextTimeoutInSeconds,
67 > Usage: "Optional timeout for context of RPC call in seconds",
68 > EnvVars: []string{"TEMPORAL_CONTEXT_TIMEOUT"},
69 > },
70 > &cli.BoolFlag{
71 > Name: FlagYes,
72 > Usage: "Automatically confirm all prompts",
73 > },
74 > &cli.StringFlag{
75 > Name: FlagTLSCertPath,
76 > Value: "",
77 > Usage: "Path to x509 certificate",
78 > EnvVars: []string{"TEMPORAL_CLI_TLS_CERT"},
79 > },
80 > &cli.StringFlag{
81 > Name: FlagTLSKeyPath,
82 > Value: "",
83 > Usage: "Path to private key",
84 > EnvVars: []string{"TEMPORAL_CLI_TLS_KEY"},
85 > },
86 > &cli.StringFlag{
87 > Name: FlagTLSCaPath,
88 > Value: "",
89 > Usage: "Path to server CA certificate",
90 > EnvVars: []string{"TEMPORAL_CLI_TLS_CA"},
91 > },
92 > &cli.BoolFlag{
93 > Name: FlagTLSDisableHostVerification,
94 > Usage: "Disable tls host name verification (tls must be enabled)",
95 > EnvVars: []string{"TEMPORAL_CLI_TLS_DISABLE_HOST_VERIFICATION"},
96 > },
97 > &cli.StringFlag{
98 > Name: FlagTLSServerName,
99 > Value: "",
100 > Usage: "Override for target server name",
101 > EnvVars: []string{"TEMPORAL_CLI_TLS_SERVER_NAME"},
102 > },
103 > &cli.StringFlag{
104 > Name: "color",
105 > Usage: fmt.Sprintf("When to use color: %v, %v, %v.", "auto", "always", "never"),
106 > Value: "auto",
107 > },
108 > }
109 > prompterFactory := NewPrompterFactory()
110 > app.Before = func(ctx *cli.Context) error {
111 > colorFlag := ctx.String("color")
112 > switch colorFlag {
113 case "always":
114 color.NoColor = false
115 case "never":
116 color.NoColor = true
117 > default: app.go
118 // fatih/color will inspect the enviroment and terminal and set a reasonable default.
119 }
120 > return nil app.go
121 }
122 > app.Commands = getCommands( app.go
123 > params.ClientFactory,
124 > NewDLQServiceProvider(
125 > params.ClientFactory,
126 > params.TaskBlobEncoder,
127 > params.TaskCategoryRegistry,
128 > params.Writer,
129 > prompterFactory,
130 > ),
131 > params.TaskCategoryRegistry,
132 > prompterFactory,
133 > params.TaskBlobEncoder,
134 > )
135 > app.ExitErrHandler = handleError
136 > app.Writer = params.Writer
137 > app.ErrWriter = params.ErrWriter
138 >
139 > return app
140 }
141
go.temporal.io/server/tools/tdbg/dlq_v2_service.go 21 introduced LOC · 4 ranges

Open complete file

357 }
358
359 > func getSupportedDLQTaskCategories(taskCategoryRegistry tasks.TaskCategoryRegistry) []tasks.Category { dlq_v2_service.go
360 > categories := make([]tasks.Category, 0, len(taskCategoryRegistry.GetCategories())-1)
361 > for _, c := range taskCategoryRegistry.GetCategories() {
362 > if c != tasks.CategoryMemoryTimer {
363 > categories = append(categories, c)
364 > }
365 }
366 > slices.SortFunc(categories, func(a, b tasks.Category) int { dlq_v2_service.go
367 > return a.ID() - b.ID()
368 > })
369 > return categories
370 }
371
372 > func getCategoriesList(taskCategoryRegistry tasks.TaskCategoryRegistry) string { dlq_v2_service.go
373 > var categoryString strings.Builder
374 > categories := getSupportedDLQTaskCategories(taskCategoryRegistry)
375 > for i, c := range categories {
376 > if i == len(categories)-1 {
377 > categoryString.WriteString(" and ")
378 > } else if i > 0 {
379 > categoryString.WriteString(", ")
380 > }
381 > _, _ = fmt.Fprintf(&categoryString, "%d (%s)", c.ID(), c.Name())
382 }
383 > return categoryString.String() dlq_v2_service.go
384 }
385
go.temporal.io/server/tools/tdbg/factory.go 10 introduced LOC · 2 ranges

Open complete file

60
61 // NewClientFactory creates a new ClientFactory
62 > func NewClientFactory(opts ...ClientFactoryOption) ClientFactory { factory.go
63 > logger := log.NewCLILogger()
64 > params := &clientFactoryParams{
65 > frontendAddressProvider: DefaultFrontendAddressProvider{},
66 > }
67 > for _, opt := range opts {
68 opt(params)
69 }
70
71 > return &clientFactory{ factory.go
72 > logger: logger,
73 > frontendAddressProvider: params.frontendAddressProvider,
74 > }
75 }
76
go.temporal.io/server/tools/tdbg/dlq_service.go 9 introduced LOC · 1 range

Open complete file

42 writer io.Writer,
43 prompterFactory PrompterFactory,
44 > ) *DLQServiceProvider { dlq_service.go
45 > return &DLQServiceProvider{
46 > clientFactory: clientFactory,
47 > taskBlobEncoder: taskBlobEncoder,
48 > taskCategoryRegistry: taskCategoryRegistry,
49 > writer: writer,
50 > prompterFactory: prompterFactory,
51 > }
52 > }
53
54 // GetDLQService returns a DLQService based on FlagDLQVersion.
go.temporal.io/server/tools/tdbg/prompter.go 2 introduced LOC · 1 range

Open complete file

35 )
36
37 > func NewPrompterFactory(opts ...PrompterOption) PrompterFactory { prompter.go
38 > return func(c BoolFlagLookup) *Prompter {
39 return NewPrompter(c, opts...)
40 }