Skip to content

Commit

Permalink
chore: Forbid replicating a replica (#3779)
Browse files Browse the repository at this point in the history
* chore: Forbid replicating a replica

We do not support connecting a replica to a replica, but before this PR
we allowed doing so. This PR disables that behavior.

Fixes #3679

* `replicaof_mu_`
  • Loading branch information
chakaz authored Sep 24, 2024
1 parent 9aadc0c commit 526bce4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/server/server_family.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2839,6 +2839,13 @@ void ServerFamily::ReplTakeOver(CmdArgList args, ConnectionContext* cntx) {
}

void ServerFamily::ReplConf(CmdArgList args, ConnectionContext* cntx) {
{
util::fb2::LockGuard lk(replicaof_mu_);
if (!ServerState::tlocal()->is_master) {
return cntx->SendError("Replicating a replica is unsupported");
}
}

if (args.size() % 2 == 1)
goto err;
for (unsigned i = 0; i < args.size(); i += 2) {
Expand Down
22 changes: 22 additions & 0 deletions tests/dragonfly/replication_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2663,3 +2663,25 @@ async def check_master_status():
assert await seeder.compare(capture, port=master.port)

await disconnect_clients(c_master, c_replica)


@pytest.mark.asyncio
async def test_replica_of_replica(df_factory):
# Can't connect a replica to a replica, but OK to connect 2 replicas to the same master
master = df_factory.create(proactor_threads=2)
replica = df_factory.create(proactor_threads=2)
replica2 = df_factory.create(proactor_threads=2)

df_factory.start_all([master, replica, replica2])

c_replica = replica.client()
c_replica2 = replica2.client()

assert await c_replica.execute_command(f"REPLICAOF localhost {master.port}") == "OK"

with pytest.raises(redis.exceptions.ResponseError):
await c_replica2.execute_command(f"REPLICAOF localhost {replica.port}")

assert await c_replica2.execute_command(f"REPLICAOF localhost {master.port}") == "OK"

await disconnect_clients(c_replica, c_replica2)

0 comments on commit 526bce4

Please sign in to comment.