Skip to content

Commit 096fde1

Browse files
chakazromange
authored andcommitted
chore: Add Lua force atomicity flag (#4523)
* chore: Add Lua force atomicity flag We accidentally instructed Sidekiq to add `disable-atomicity` to their script, despite them needing to run atomically. This hack-ish PR adds a `--lua_force_atomicity_shas` flag to allow specifying which SHAs are forced to run in an atomic fashion, even if they are marked as non-atomic. Fixes #4522 * fix build on clang
1 parent c056ccb commit 096fde1

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/server/multi_test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ ABSL_DECLARE_FLAG(bool, multi_exec_squash);
2121
ABSL_DECLARE_FLAG(bool, lua_auto_async);
2222
ABSL_DECLARE_FLAG(bool, lua_allow_undeclared_auto_correct);
2323
ABSL_DECLARE_FLAG(std::string, default_lua_flags);
24+
ABSL_DECLARE_FLAG(std::vector<std::string>, lua_force_atomicity_shas);
2425

2526
namespace dfly {
2627

2728
using namespace std;
2829
using namespace util;
2930
using absl::StrCat;
3031
using ::io::Result;
32+
using testing::_;
3133
using testing::ElementsAre;
3234
using testing::HasSubstr;
3335

@@ -1219,4 +1221,27 @@ TEST_F(MultiTest, EvalShaRo) {
12191221
EXPECT_THAT(resp, ErrArg("Write commands are not allowed from read-only scripts"));
12201222
}
12211223

1224+
TEST_F(MultiTest, ForceAtomicityFlag) {
1225+
absl::FlagSaver fs;
1226+
1227+
const string kHash = "bb855c2ecfa3114d222cb11e0682af6360e9712f";
1228+
const string_view kScript = R"(
1229+
--!df flags=disable-atomicity
1230+
redis.call('get', 'x');
1231+
return "OK";
1232+
)";
1233+
1234+
// EVAL the script works due to disable-atomicity flag
1235+
EXPECT_EQ(Run({"eval", kScript, "0"}), "OK");
1236+
1237+
EXPECT_THAT(Run({"script", "list"}), RespElementsAre(kHash, kScript));
1238+
1239+
// Flush scripts to force re-evaluating of flags
1240+
EXPECT_EQ(Run({"script", "flush"}), "OK");
1241+
1242+
// Now it doesn't work, because we force atomicity
1243+
absl::SetFlag(&FLAGS_lua_force_atomicity_shas, {kHash});
1244+
EXPECT_THAT(Run({"eval", kScript, "0"}), ErrArg("undeclared"));
1245+
}
1246+
12221247
} // namespace dfly

src/server/script_mgr.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ ABSL_FLAG(
4747
"Comma-separated list of Lua script SHAs which are allowed to access undeclared keys. SHAs are "
4848
"only looked at when loading the script, and new values do not affect already-loaded script.");
4949

50+
ABSL_FLAG(std::vector<std::string>, lua_force_atomicity_shas,
51+
std::vector<std::string>({
52+
"f8133be7f04abd9dfefa83c3b29a9d837cfbda86", // Sidekiq, see #4522
53+
}),
54+
"Comma-separated list of Lua script SHAs which are forced to run in atomic mode, even if "
55+
"the script specifies disable-atomicity.");
56+
5057
namespace dfly {
5158
using namespace std;
5259
using namespace facade;
@@ -264,6 +271,13 @@ io::Result<string, GenericError> ScriptMgr::Insert(string_view body, Interpreter
264271
return params_opt.get_unexpected();
265272
auto params = params_opt->value_or(default_params_);
266273

274+
if (!params.atomic) {
275+
auto force_atomic_shas = absl::GetFlag(FLAGS_lua_force_atomicity_shas);
276+
if (find(force_atomic_shas.begin(), force_atomic_shas.end(), sha) != force_atomic_shas.end()) {
277+
params.atomic = true;
278+
}
279+
}
280+
267281
auto undeclared_shas = absl::GetFlag(FLAGS_lua_undeclared_keys_shas);
268282
if (find(undeclared_shas.begin(), undeclared_shas.end(), sha) != undeclared_shas.end()) {
269283
params.undeclared_keys = true;

0 commit comments

Comments
 (0)