This is an automated email from the ASF dual-hosted git repository.

dmeden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 07dd143859 traffic_ctl: Refactor command execution in traffic_ctl 
(#12647)
07dd143859 is described below

commit 07dd1438594e4e9fc285236e02dbc954241a197a
Author: Damian Meden <[email protected]>
AuthorDate: Thu Nov 13 13:08:35 2025 +0100

    traffic_ctl: Refactor command execution in traffic_ctl (#12647)
    
    * traffic_ctl: Refactor command execution in traffic_ctl
    
    Replace repeated inline lambdas with a reusable Command_Execute
    lambda. This reduces code duplication.
---
 src/traffic_ctl/traffic_ctl.cc | 123 ++++++++++++++++++++++-------------------
 1 file changed, 65 insertions(+), 58 deletions(-)

diff --git a/src/traffic_ctl/traffic_ctl.cc b/src/traffic_ctl/traffic_ctl.cc
index 673b1906f7..5599bd64c9 100644
--- a/src/traffic_ctl/traffic_ctl.cc
+++ b/src/traffic_ctl/traffic_ctl.cc
@@ -63,7 +63,15 @@ main([[maybe_unused]] int argc, const char **argv)
 {
   ts::ArgParser parser;
 
-  std::shared_ptr<CtrlCommand> command;
+  std::unique_ptr<CtrlCommand> command;
+
+  auto Command_Execute = [&command]() {
+    if (command) {
+      command->execute();
+    } else {
+      throw std::runtime_error("No command provided");
+    }
+  };
 
   auto CtrlUnimplementedCommand = [](std::string_view cmd) {
     std::cout << "Command " << cmd << " unimplemented.\n";
@@ -92,33 +100,31 @@ main([[maybe_unused]] int argc, const char **argv)
   auto &direct_rpc_command = parser.add_command("rpc", "Interact with the rpc 
api").require_commands();
 
   // config commands
-  config_command.add_command("defaults", "Show default information 
configuration values", [&]() { command->execute(); })
+  config_command.add_command("defaults", "Show default information 
configuration values", Command_Execute)
     .add_example_usage("traffic_ctl config defaults [OPTIONS]")
     .add_option("--records", "", "Emit output in YAML format");
   config_command
-    .add_command("describe", "Show detailed information about configuration 
values", "", MORE_THAN_ONE_ARG_N,
-                 [&]() { command->execute(); })
+    .add_command("describe", "Show detailed information about configuration 
values", "", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl config describe RECORD [RECORD ...]");
-  config_command.add_command("diff", "Show non-default configuration values", 
[&]() { command->execute(); })
+  config_command.add_command("diff", "Show non-default configuration values", 
Command_Execute)
     .add_example_usage("traffic_ctl config diff [OPTIONS]")
     .add_option("--records", "", "Emit output in YAML format");
-  config_command.add_command("get", "Get one or more configuration values", 
"", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  config_command.add_command("get", "Get one or more configuration values", 
"", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl config get [OPTIONS] RECORD [RECORD ...]")
     .add_option("--cold", "-c",
                 "Save the value in a configuration file. This does not save 
the value in TS. Local file change only",
                 "TS_RECORD_YAML", MORE_THAN_ZERO_ARG_N)
     .add_option("--records", "", "Emit output in YAML format")
     .add_option("--default", "", "Include default value");
-  config_command
-    .add_command("match", "Get configuration matching a regular expression", 
"", MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  config_command.add_command("match", "Get configuration matching a regular 
expression", "", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl config match [OPTIONS] REGEX [REGEX ...]")
     .add_option("--records", "", "Emit output in YAML format")
     .add_option("--default", "", "Include the default value");
-  config_command.add_command("reload", "Request a configuration reload", [&]() 
{ command->execute(); })
+  config_command.add_command("reload", "Request a configuration reload", 
Command_Execute)
     .add_example_usage("traffic_ctl config reload");
-  config_command.add_command("status", "Check the configuration status", [&]() 
{ command->execute(); })
+  config_command.add_command("status", "Check the configuration status", 
Command_Execute)
     .add_example_usage("traffic_ctl config status");
-  config_command.add_command("set", "Set a configuration value", "", 2, [&]() 
{ command->execute(); })
+  config_command.add_command("set", "Set a configuration value", "", 2, 
Command_Execute)
     .add_option("--cold", "-c",
                 "Save the value in a configuration file. This does not save 
the value in TS. Local file change only",
                 "TS_RECORD_YAML", MORE_THAN_ZERO_ARG_N)
@@ -129,31 +135,30 @@ main([[maybe_unused]] int argc, const char **argv)
       "", 1)
     .add_example_usage("traffic_ctl config set RECORD VALUE");
 
-  config_command.add_command("registry", "Show configuration file registry", 
[&]() { command->execute(); })
+  config_command.add_command("registry", "Show configuration file registry", 
Command_Execute)
     .add_example_usage("traffic_ctl config registry");
   // host commands
-  host_command.add_command("status", "Get one or more host statuses", "", 
MORE_THAN_ZERO_ARG_N, [&]() { command->execute(); })
+  host_command.add_command("status", "Get one or more host statuses", "", 
MORE_THAN_ZERO_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl host status HOST  [HOST  ...]");
-  host_command.add_command("down", "Set down one or more host(s)", "", 
MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  host_command.add_command("down", "Set down one or more host(s)", "", 
MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl host down HOST [OPTIONS]")
     .add_option("--time", "-I", "number of seconds that a host is marked 
down", "", 1, "0")
     .add_option("--reason", "", "reason for marking the host down, one of 
'manual|active|local", "", 1, "manual");
-  host_command.add_command("up", "Set up one or more host(s)", "", 
MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  host_command.add_command("up", "Set up one or more host(s)", "", 
MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl host up METRIC value")
     .add_option("--reason", "", "reason for marking the host up, one of 
'manual|active|local", "", 1, "manual");
 
   // metric commands
-  metric_command.add_command("get", "Get one or more metric values", "", 
MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  metric_command.add_command("get", "Get one or more metric values", "", 
MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl metric get METRIC [METRIC ...]");
   metric_command.add_command("describe", "Show detailed information about one 
or more metric values", "", MORE_THAN_ONE_ARG_N,
-                             [&]() { command->execute(); }); // not implemented
-  metric_command.add_command("match", "Get metrics matching a regular 
expression", "", MORE_THAN_ZERO_ARG_N,
-                             [&]() { command->execute(); });
+                             Command_Execute); // not implemented
+  metric_command.add_command("match", "Get metrics matching a regular 
expression", "", MORE_THAN_ZERO_ARG_N, Command_Execute);
   metric_command
     .add_command(
       "monitor",
       "Display the value of a metric(s) over time. Program stops after <count> 
or with a SIGINT. A brief summary is displayed.", "",
-      MORE_THAN_ZERO_ARG_N, [&]() { command->execute(); })
+      MORE_THAN_ZERO_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl metric monitor METRIC -i 3 -c 10")
     .add_option("--count", "-c",
                 "Terminate execution after requesting <count> metrics. If 0 is 
passed, program should be terminated by a SIGINT",
@@ -161,60 +166,81 @@ main([[maybe_unused]] int argc, const char **argv)
     .add_option("--interval", "-i", "Wait interval seconds between sending 
each metric request. Minimum value is 1s.", "", 1, "5");
 
   // hostdb commands
-  hostdb_command.add_command("status", "Get HostDB info", "", 
MORE_THAN_ZERO_ARG_N, [&]() { command->execute(); })
+  hostdb_command.add_command("status", "Get HostDB info", "", 
MORE_THAN_ZERO_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl hostdb status");
 
   // plugin command
   plugin_command
-    .add_command("msg", "Send message to plugins - a TAG and the message 
DATA(optional)", "", MORE_THAN_ONE_ARG_N,
-                 [&]() { command->execute(); })
+    .add_command("msg", "Send message to plugins - a TAG and the message 
DATA(optional)", "", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("traffic_ctl plugin msg TAG DATA");
 
   // server commands
   server_command.add_command("backtrace", "Show a full stack trace of the 
traffic_server process",
                              [&]() { CtrlUnimplementedCommand("backtrace"); });
-  server_command.add_command("status", "Show the proxy status", [&]() { 
command->execute(); })
-    .add_example_usage("traffic_ctl server status");
-  server_command.add_command("drain", "Drain the requests", [&]() { 
command->execute(); })
+  server_command.add_command("status", "Show the proxy status", 
Command_Execute).add_example_usage("traffic_ctl server status");
+  server_command.add_command("drain", "Drain the requests", Command_Execute)
     .add_example_usage("traffic_ctl server drain [OPTIONS]")
     .add_option("--no-new-connection", "-N", "Wait for new connections down to 
threshold before starting draining")
     .add_option("--undo", "-U", "Recover server from the drain mode");
 
   auto &debug_command =
     server_command.add_command("debug", "Enable/Disable ATS for diagnostic 
messages at runtime").require_commands();
-  debug_command.add_command("enable", "Enables logging for diagnostic messages 
at runtime", [&]() { command->execute(); })
+  debug_command.add_command("enable", "Enables logging for diagnostic messages 
at runtime", Command_Execute)
     .add_option("--tags", "-t", "Debug tags", "TS_DEBUG_TAGS", 1)
     .add_option("--client_ip", "-c", "Client's ip", "", 1, "")
     .add_example_usage("traffic_ctl server debug enable -t my_tags -c 
X.X.X.X");
-  debug_command.add_command("disable", "Disables logging for diagnostic 
messages at runtime", [&]() { command->execute(); })
+  debug_command.add_command("disable", "Disables logging for diagnostic 
messages at runtime", Command_Execute)
     .add_example_usage("traffic_ctl server debug disable");
 
   // storage commands
-  storage_command
-    .add_command("offline", "Take one or more storage volumes offline", "", 
MORE_THAN_ONE_ARG_N, [&]() { command->execute(); })
+  storage_command.add_command("offline", "Take one or more storage volumes 
offline", "", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_example_usage("storage offline DEVICE [DEVICE ...]");
   storage_command.add_command("status", "Show the storage configuration", "", 
MORE_THAN_ONE_ARG_N,
-                              [&]() { command->execute(); }); // not 
implemented
+                              Command_Execute); // not implemented
 
   // direct rpc commands, handy for debug and trouble shooting
   direct_rpc_command
     .add_command("file", "Send direct JSONRPC request to the server from a 
passed file(s)", "", MORE_THAN_ONE_ARG_N,
-                 [&]() { command->execute(); })
+                 Command_Execute)
     .add_example_usage("traffic_ctl rpc file request.yaml");
-  direct_rpc_command.add_command("get-api", "Request full API from server", 
"", 0, [&]() { command->execute(); })
+  direct_rpc_command.add_command("get-api", "Request full API from server", 
"", 0, Command_Execute)
     .add_example_usage("traffic_ctl rpc get-api");
-  direct_rpc_command
-    .add_command("input", "Read from standard input. Ctrl-D to send the 
request", "", 0, [&]() { command->execute(); })
+  direct_rpc_command.add_command("input", "Read from standard input. Ctrl-D to 
send the request", "", 0, Command_Execute)
     .add_option("--raw", "-r",
                 "No json/yaml parse validation will take place, the raw 
content will be directly send to the server.", "", 0, "",
                 "raw")
     .add_example_usage("traffic_ctl rpc input ");
   direct_rpc_command
-    .add_command("invoke", "Call a method by using the method name as input 
parameter", "", MORE_THAN_ONE_ARG_N,
-                 [&]() { command->execute(); })
+    .add_command("invoke", "Call a method by using the method name as input 
parameter", "", MORE_THAN_ONE_ARG_N, Command_Execute)
     .add_option("--params", "-p", "Parameters to be passed in the request, 
YAML or JSON format", "", MORE_THAN_ONE_ARG_N, "", "")
     .add_example_usage("traffic_ctl rpc invoke foo_bar -p \"numbers: [1, 2, 
3]\"");
 
+  auto create_command = [](ts::Arguments &args) -> 
std::unique_ptr<CtrlCommand> {
+    if (args.get("config")) {
+      if (args.get("cold")) {
+        return std::make_unique<FileConfigCommand>(&args);
+      }
+      return std::make_unique<ConfigCommand>(&args);
+    }
+
+    static const std::map<std::string, 
std::function<std::unique_ptr<CtrlCommand>(ts::Arguments *)>> factories = {
+      {"metric",  [](ts::Arguments *a) { return 
std::make_unique<MetricCommand>(a); }   },
+      {"server",  [](ts::Arguments *a) { return 
std::make_unique<ServerCommand>(a); }   },
+      {"storage", [](ts::Arguments *a) { return 
std::make_unique<StorageCommand>(a); }  },
+      {"plugin",  [](ts::Arguments *a) { return 
std::make_unique<PluginCommand>(a); }   },
+      {"host",    [](ts::Arguments *a) { return 
std::make_unique<HostCommand>(a); }     },
+      {"hostdb",  [](ts::Arguments *a) { return 
std::make_unique<HostDBCommand>(a); }   },
+      {"rpc",     [](ts::Arguments *a) { return 
std::make_unique<DirectRPCCommand>(a); }},
+    };
+
+    for (const auto &[key, factory] : factories) {
+      if (args.get(key)) {
+        return factory(&args);
+      }
+    }
+    return nullptr;
+  };
+
   try {
     // for now we only care about SIGINT(SIGQUIT, ... ?)
     signal_register_handler(SIGINT, handle_signal);
@@ -223,27 +249,8 @@ main([[maybe_unused]] int argc, const char **argv)
     argparser_runroot_handler(args.get("run-root").value(), argv[0]);
     Layout::create();
 
-    if (args.get("config")) {
-      if (args.get("cold")) {
-        // We allow to just change a config file
-        command = std::make_shared<FileConfigCommand>(&args);
-      } else {
-        command = std::make_shared<ConfigCommand>(&args);
-      }
-    } else if (args.get("metric")) {
-      command = std::make_shared<MetricCommand>(&args);
-    } else if (args.get("server")) {
-      command = std::make_shared<ServerCommand>(&args);
-    } else if (args.get("storage")) {
-      command = std::make_shared<StorageCommand>(&args);
-    } else if (args.get("plugin")) {
-      command = std::make_shared<PluginCommand>(&args);
-    } else if (args.get("host")) {
-      command = std::make_shared<HostCommand>(&args);
-    } else if (args.get("hostdb")) {
-      command = std::make_shared<HostDBCommand>(&args);
-    } else if (args.get("rpc")) {
-      command = std::make_shared<DirectRPCCommand>(&args);
+    if (command = create_command(args); !command) {
+      throw std::runtime_error("No valid command provided");
     }
     // Execute
     args.invoke();

Reply via email to