Skip to content

Commit b7a7ef8

Browse files
authored
Propagate database changes from scripting engine temp client (#2959)
**Problem:** temp client does not preserve db between VM_Call() calls. SELECT changes the database context of a temporary client created for that specific call. However, this database change is not propagated back to the context client, so subsequent commands in the same script will execute in the wrong database. Behaviour on unstable: ``` 127.0.0.1:6379> eval "server.call('SELECT', '1'); return server.call('SET', 'lua_test', 'incorrect')" 0 OK 127.0.0.1:6379> select 0 OK 127.0.0.1:6379> get lua_test "incorrect" 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> get lua_test (nil) ``` Behaviour with fixes: ``` 127.0.0.1:6379> eval "server.call('SELECT', '1'); return server.call('SET', 'lua_test', 'correct')" 0 OK 127.0.0.1:6379> select 0 OK 127.0.0.1:6379> get lua_test (nil) 127.0.0.1:6379> select 1 OK 127.0.0.1:6379[1]> get lua_test "correct" ``` Signed-off-by: Daniil Kashapov <daniil.kashapov.ykt@gmail.com>
1 parent a571ac5 commit b7a7ef8

4 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/module.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6765,6 +6765,12 @@ ValkeyModuleCallReply *VM_Call(ValkeyModuleCtx *ctx, const char *cmdname, const
67656765
}
67666766
call(c, call_flags);
67676767

6768+
/* Propagate database changes from the temporary client back to the context client
6769+
* when running in script mode to make next commands execute in the correct db */
6770+
if (c && (flags & VALKEYMODULE_ARGV_SCRIPT_MODE) && is_running_script && c->db != ctx->client->db) {
6771+
ctx->client->db = c->db;
6772+
}
6773+
67686774
/* We reset errno here because on macOS some system calls set errno even when
67696775
* they succeed. For instance, certain time-related syscalls may set errno
67706776
* to ETIMEDOUT on successful completion.

src/script.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ int scriptPrepareForRun(scriptRunCtx *run_ctx,
211211
run_ctx->original_client = caller;
212212
run_ctx->funcname = funcname;
213213
run_ctx->slot = caller->slot;
214+
run_ctx->original_db = caller->db;
214215

215216
run_ctx->start_time = getMonotonicUs();
216217

@@ -250,6 +251,8 @@ void scriptResetRun(scriptRunCtx *run_ctx) {
250251
unprotectClient(run_ctx->original_client);
251252
}
252253

254+
run_ctx->original_client->db = run_ctx->original_db;
255+
253256
run_ctx->slot = -1;
254257

255258
preventCommandPropagation(run_ctx->original_client);

src/script.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct scriptRunCtx {
7777
scriptingEngine *engine;
7878
const char *funcname;
7979
client *original_client;
80+
serverDb *original_db;
8081
int flags;
8182
int repl_flags;
8283
monotime start_time;

tests/unit/scripting.tcl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,4 +2598,38 @@ start_server {tags {"scripting"}} {
25982598
r eval "error({})" 0
25992599
}
26002600
}
2601+
2602+
test {EVAL - SELECT inside script affects subsequent commands in same script} {
2603+
r select 0
2604+
r del testkey
2605+
r set testkey "db0_value"
2606+
2607+
# Run script that:
2608+
# 1. Reads from DB 0
2609+
# 2. Switches to DB 1
2610+
# 3. Sets a key in DB 1
2611+
# 4. Returns the value from DB 1
2612+
set result [run_script {
2613+
local db0_val = server.call('get', 'testkey')
2614+
server.call('select', '1')
2615+
server.call('set', 'testkey', 'db1_value')
2616+
return server.call('get', 'testkey')
2617+
} 1 testkey]
2618+
2619+
# Script returned the DB 1 value
2620+
assert_equal "db1_value" $result
2621+
2622+
# Verify we're back in DB 0 after script
2623+
assert_equal "db0_value" [r get testkey]
2624+
2625+
# Verify DB 1 has the new value that was set by the script
2626+
r select 1
2627+
assert_equal "db1_value" [r get testkey]
2628+
2629+
# Cleanup
2630+
r del testkey
2631+
r select 0
2632+
r del testkey
2633+
set _ {}
2634+
} {} {singledb:skip}
26012635
}

0 commit comments

Comments
 (0)