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

wangdan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pegasus.git


The following commit(s) were added to refs/heads/master by this push:
     new 034d79a0e feat(make_idempotent): support getting/enabling/disabling 
`atomic_idempotent` on shell (#2229)
034d79a0e is described below

commit 034d79a0e47c46934156a635ed7554cbfad21e06
Author: Dan Wang <[email protected]>
AuthorDate: Thu Apr 17 15:56:12 2025 +0800

    feat(make_idempotent): support getting/enabling/disabling 
`atomic_idempotent` on shell (#2229)
    
    https://github.com/apache/incubator-pegasus/issues/2197
    
    Following commands are supported on shell to operate `atomic_idempotent`,
    which decides whether all atomic requests written to a table are 
idempotent":
    - `get_atomic_idempotent`
    - `enable_atomic_idempotent`
    - `disable_atomic_idempotent`
    
    All of these commands are based on a table, thus an argument `app_name`
    is required.
---
 src/shell/commands.h                    |   6 ++
 src/shell/commands/table_management.cpp | 117 +++++++++++++++++++++++++++++---
 src/shell/main.cpp                      |  19 ++++++
 3 files changed, 132 insertions(+), 10 deletions(-)

diff --git a/src/shell/commands.h b/src/shell/commands.h
index f4de53fce..aa577fb34 100644
--- a/src/shell/commands.h
+++ b/src/shell/commands.h
@@ -143,6 +143,12 @@ bool get_max_replica_count(command_executor *e, 
shell_context *sc, arguments arg
 
 bool set_max_replica_count(command_executor *e, shell_context *sc, arguments 
args);
 
+bool get_atomic_idempotent(command_executor *e, shell_context *sc, arguments 
args);
+
+bool enable_atomic_idempotent(command_executor *e, shell_context *sc, 
arguments args);
+
+bool disable_atomic_idempotent(command_executor *e, shell_context *sc, 
arguments args);
+
 // == data operations (see 'commands/data_operations.cpp') == //
 
 bool data_operations(command_executor *e, shell_context *sc, arguments args);
diff --git a/src/shell/commands/table_management.cpp 
b/src/shell/commands/table_management.cpp
index c414e3776..9890234e2 100644
--- a/src/shell/commands/table_management.cpp
+++ b/src/shell/commands/table_management.cpp
@@ -677,7 +677,7 @@ bool create_app(command_executor *e, shell_context *sc, 
arguments args)
 
     argh::parser cmd(args.argc, args.argv, 
argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);
 
-    // Check if the input parameters and flags are valid, and there are exact 
one positional
+    // Check if the input parameters and flags are valid, and there is exact 
one positional
     // argument (i.e. app_name).
     const auto &check = validate_cmd(cmd, params, flags, 1);
     if (!check) {
@@ -686,7 +686,7 @@ bool create_app(command_executor *e, shell_context *sc, 
arguments args)
     }
 
     // Get the only positional argument as app_name.
-    std::string app_name = cmd(1).str();
+    const std::string app_name(cmd(1).str());
 
     int32_t partition_count = 0;
     PARSE_OPT_INT(partition_count, 4, {"-p", "--partition_count"});
@@ -703,14 +703,14 @@ bool create_app(command_executor *e, shell_context *sc, 
arguments args)
     std::map<std::string, std::string> envs;
     PARSE_OPT_KV_MAP(envs, ',', '=', {"-e", "--envs"});
 
-    dsn::error_code err = sc->ddl_client->create_app(app_name,
-                                                     "pegasus",
-                                                     partition_count,
-                                                     replica_count,
-                                                     envs,
-                                                     false,
-                                                     success_if_exist,
-                                                     atomic_idempotent);
+    const dsn::error_code err = sc->ddl_client->create_app(app_name,
+                                                           "pegasus",
+                                                           partition_count,
+                                                           replica_count,
+                                                           envs,
+                                                           false,
+                                                           success_if_exist,
+                                                           atomic_idempotent);
     if (err == ::dsn::ERR_OK) {
         std::cout << "create app \"" << 
pegasus::utils::c_escape_string(app_name) << "\" succeed"
                   << std::endl;
@@ -1068,3 +1068,100 @@ bool set_max_replica_count(command_executor *e, 
shell_context *sc, arguments arg
 
     return true;
 }
+
+bool get_atomic_idempotent(command_executor *e, shell_context *sc, arguments 
args)
+{
+    // get_atomic_idempotent <app_name> [-j|--json]
+
+    // All valid flags are given as follows.
+    static const std::set<std::string> flags = {"j", "json"};
+
+    argh::parser cmd(args.argc, args.argv, 
argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);
+
+    // Check if the input flags are valid, and there is exact one positional 
argument
+    // (i.e. app_name).
+    const auto &check = validate_cmd(cmd, {}, flags, 1);
+    if (!check) {
+        SHELL_PRINTLN_ERROR("{}", check.description());
+        return false;
+    }
+
+    // Get the only positional argument as app_name.
+    const std::string app_name(cmd(1).str());
+
+    const bool json = cmd[{"-j", "--json"}];
+
+    const auto &result = sc->ddl_client->get_atomic_idempotent(app_name);
+    auto status = result.get_error();
+    if (status) {
+        status = FMT_ERR(result.get_value().err, 
result.get_value().hint_message);
+    }
+
+    if (!status) {
+        SHELL_PRINTLN_ERROR("get_atomic_idempotent failed, error={}", status);
+        return true;
+    }
+
+    dsn::utils::table_printer printer("atomic_idempotent");
+    printer.add_row_name_and_data("atomic_idempotent", 
result.get_value().atomic_idempotent);
+    dsn::utils::output(json, printer);
+
+    return true;
+}
+
+namespace {
+
+bool set_atomic_idempotent(command_executor *e,
+                           shell_context *sc,
+                           arguments args,
+                           bool atomic_idempotent)
+{
+    // <enable|disable>_atomic_idempotent <app_name>
+
+    argh::parser cmd(args.argc, args.argv, 
argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);
+
+    // Check if there is exact one positional argument (i.e. app_name).
+    const auto &check = validate_cmd(cmd, {}, {}, 1);
+    if (!check) {
+        SHELL_PRINTLN_ERROR("{}", check.description());
+        return false;
+    }
+
+    // Get the only positional argument as app_name.
+    const std::string app_name(cmd(1).str());
+
+    const auto &result = sc->ddl_client->set_atomic_idempotent(app_name, 
atomic_idempotent);
+    auto status = result.get_error();
+    if (status) {
+        status = FMT_ERR(result.get_value().err, 
result.get_value().hint_message);
+    }
+
+    if (!status) {
+        SHELL_PRINTLN_ERROR("set_atomic_idempotent failed, error={}", status);
+        return true;
+    }
+
+    const auto &resp = result.get_value();
+    SHELL_PRINTLN_OK("set_atomic_idempotent from {} to {}: {}\n",
+                     resp.old_atomic_idempotent,
+                     atomic_idempotent,
+                     resp.hint_message.empty() ? "succeed" : 
resp.hint_message);
+
+    return true;
+}
+
+} // anonymous namespace
+
+bool enable_atomic_idempotent(command_executor *e, shell_context *sc, 
arguments args)
+{
+    // enable_atomic_idempotent <app_name>
+
+    return set_atomic_idempotent(e, sc, args, true);
+}
+
+bool disable_atomic_idempotent(command_executor *e, shell_context *sc, 
arguments args)
+{
+    // disable_atomic_idempotent <app_name>
+
+    return set_atomic_idempotent(e, sc, args, false);
+}
diff --git a/src/shell/main.cpp b/src/shell/main.cpp
index cc43efee1..a8da02179 100644
--- a/src/shell/main.cpp
+++ b/src/shell/main.cpp
@@ -613,6 +613,25 @@ static command_executor commands[] = {
         "<app_name> <replica_count>",
         set_max_replica_count,
     },
+    {
+        "get_atomic_idempotent",
+        "check whether all atomic writes to an app will be made idempotent: 
true means "
+        "made idempotent, while false means kept non-idempotent",
+        "<app_name> [-j|--json]",
+        get_atomic_idempotent,
+    },
+    {
+        "enable_atomic_idempotent",
+        "enable idempotence for all atomic writes to an app",
+        "<app_name>",
+        enable_atomic_idempotent,
+    },
+    {
+        "disable_atomic_idempotent",
+        "disable idempotence for all atomic writes to an app",
+        "<app_name>",
+        disable_atomic_idempotent,
+    },
     {
         "local_partition_split",
         "Split the local partitions offline. It's helpful to split the table 
which has large "


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to