Skip to content

Refactor some of ASM and slot-stats functions#26

Open
tomerqodo wants to merge 3 commits intoqodo_action_req_1_base_refactor_some_of_asm_and_slot-stats_functions_pr4from
qodo_action_req_1_head_refactor_some_of_asm_and_slot-stats_functions_pr4
Open

Refactor some of ASM and slot-stats functions#26
tomerqodo wants to merge 3 commits intoqodo_action_req_1_base_refactor_some_of_asm_and_slot-stats_functions_pr4from
qodo_action_req_1_head_refactor_some_of_asm_and_slot-stats_functions_pr4

Conversation

@tomerqodo
Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#4

@qodo-code-review
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. clusterDeleteKeysInUnownedSlots() not static 📘 Rule violation ⛯ Reliability
Description
clusterDeleteKeysInUnownedSlots() is defined without static even though it appears to be an
  internal helper used only within src/cluster.c.
• Leaving it non-static unnecessarily exports the symbol and increases the chance of symbol
  collisions or unintended external use.
Code

src/cluster.c[2146]

+void clusterDeleteKeysInUnownedSlots(void) {
Evidence
The checklist requires internal helper functions (used only within a single source file) to be
declared static. The function is defined in src/cluster.c as a non-static global.

AGENTS.md
src/cluster.c[2143-2148]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`clusterDeleteKeysInUnownedSlots()` is an internal helper but is exported as a global symbol because it is not declared `static`.

## Issue Context
This function is used as a helper from within `src/cluster.c` (e.g., by `verifyClusterConfigWithData()`). It should not be externally visible.

## Fix Focus Areas
- src/cluster.c[2143-2214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Deletes unassigned-slot keys 🐞 Bug ✓ Correctness
Description
• clusterDeleteKeysInUnownedSlots() deletes keys for any slot that has keys, is not “my slot”, and
  is not importing; this also matches slots with no owner (unassigned), so keys in unassigned slots
  can be deleted at startup.
• verifyClusterConfigWithData() then calls clusterClaimUnassignedSlots(), but it can no longer claim
  those slots because the keys were deleted.
• Impact: silent data loss on restart when node.conf lacks slot ownership but DB0 contains keys for
  those slots.
Code

src/cluster.c[R2146-2168]

+void clusterDeleteKeysInUnownedSlots(void) {
+    if (clusterNodeIsSlave(getMyClusterNode())) return;
+
+    /* Check that all the slots we have keys for are assigned to us. Otherwise,
+     * delete the keys. */
+    for (int i = 0; i < CLUSTER_SLOTS; i++) {
+        /* Skip if: no keys in the slot, it's our slot, or we are importing it. */
+        if (!countKeysInSlot(i) ||
+            clusterIsMySlot(i) ||
+            getImportingSlotSource(i))
+        {
+            continue;
+        }
+
+        serverLog(LL_NOTICE, "I have keys for slot %d, but the slot is "
+                             "assigned to another node. "
+                             "Deleting keys in the slot.", i);
+        /* With atomic slot migration, it is safe to drop keys from slots
+         * that are not owned. This will not result in data loss under the
+         * legacy slot migration approach either, since the importing state
+         * has already been persisted in node.conf. */
+        clusterDelKeysInSlot(i, 0);
+    }
Evidence
Unassigned slots have NULL owners (getNodeBySlot(slot) returns server.cluster->slots[slot]).
clusterIsMySlot(slot) is defined as getMyClusterNode()==getNodeBySlot(slot), which is false when the
slot is unassigned. Therefore, for an unassigned slot with keys and not importing, the skip
condition in clusterDeleteKeysInUnownedSlots() evaluates false and the code deletes keys.
clusterClaimUnassignedSlots() only claims when the slot is unassigned AND has keys; after deletion,
the claim won’t trigger.

src/cluster.c[2146-2168]
src/cluster.c[2209-2213]
src/cluster.c[1722-1724]
src/cluster_legacy.c[6499-6501]
src/cluster_legacy.c[5266-5283]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`clusterDeleteKeysInUnownedSlots()` currently deletes keys for slots that have keys, are not owned by this node, and are not importing. This condition also matches *unassigned* slots (owner == NULL), which means keys in unassigned slots can be deleted before `clusterClaimUnassignedSlots()` gets a chance to take ownership.

### Issue Context
This runs during `verifyClusterConfigWithData()` after loading data, so it can cause silent data loss at startup.

### Fix Focus Areas
- src/cluster.c[2146-2168]
- src/cluster.c[2209-2213]
- src/cluster.c[1722-1724]
- src/cluster_legacy.c[5266-5283]
- src/cluster_legacy.c[6499-6501]

### Implementation notes
- Add an explicit `if (getNodeBySlot(i) == NULL) continue;` (or equivalent helper) before deleting.
- Consider swapping the order in `verifyClusterConfigWithData()` to claim first, then delete unowned (owned-by-other) slots.
- Update the log text to avoid claiming &quot;assigned to another node&quot; when the slot is actually unassigned.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment thread src/cluster.c
/* This function is called after the node startup in order to check if there
* are any slots that we have keys for, but are not assigned to us. If so,
* we delete the keys. */
void clusterDeleteKeysInUnownedSlots(void) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. clusterdeletekeysinunownedslots() not static 📘 Rule violation ⛯ Reliability

clusterDeleteKeysInUnownedSlots() is defined without static even though it appears to be an
  internal helper used only within src/cluster.c.
• Leaving it non-static unnecessarily exports the symbol and increases the chance of symbol
  collisions or unintended external use.
Agent prompt
## Issue description
`clusterDeleteKeysInUnownedSlots()` is an internal helper but is exported as a global symbol because it is not declared `static`.

## Issue Context
This function is used as a helper from within `src/cluster.c` (e.g., by `verifyClusterConfigWithData()`). It should not be externally visible.

## Fix Focus Areas
- src/cluster.c[2143-2214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/cluster.c
Comment on lines +2146 to +2168
void clusterDeleteKeysInUnownedSlots(void) {
if (clusterNodeIsSlave(getMyClusterNode())) return;

/* Check that all the slots we have keys for are assigned to us. Otherwise,
* delete the keys. */
for (int i = 0; i < CLUSTER_SLOTS; i++) {
/* Skip if: no keys in the slot, it's our slot, or we are importing it. */
if (!countKeysInSlot(i) ||
clusterIsMySlot(i) ||
getImportingSlotSource(i))
{
continue;
}

serverLog(LL_NOTICE, "I have keys for slot %d, but the slot is "
"assigned to another node. "
"Deleting keys in the slot.", i);
/* With atomic slot migration, it is safe to drop keys from slots
* that are not owned. This will not result in data loss under the
* legacy slot migration approach either, since the importing state
* has already been persisted in node.conf. */
clusterDelKeysInSlot(i, 0);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Deletes unassigned-slot keys 🐞 Bug ✓ Correctness

• clusterDeleteKeysInUnownedSlots() deletes keys for any slot that has keys, is not “my slot”, and
  is not importing; this also matches slots with no owner (unassigned), so keys in unassigned slots
  can be deleted at startup.
• verifyClusterConfigWithData() then calls clusterClaimUnassignedSlots(), but it can no longer claim
  those slots because the keys were deleted.
• Impact: silent data loss on restart when node.conf lacks slot ownership but DB0 contains keys for
  those slots.
Agent prompt
### Issue description
`clusterDeleteKeysInUnownedSlots()` currently deletes keys for slots that have keys, are not owned by this node, and are not importing. This condition also matches *unassigned* slots (owner == NULL), which means keys in unassigned slots can be deleted before `clusterClaimUnassignedSlots()` gets a chance to take ownership.

### Issue Context
This runs during `verifyClusterConfigWithData()` after loading data, so it can cause silent data loss at startup.

### Fix Focus Areas
- src/cluster.c[2146-2168]
- src/cluster.c[2209-2213]
- src/cluster.c[1722-1724]
- src/cluster_legacy.c[5266-5283]
- src/cluster_legacy.c[6499-6501]

### Implementation notes
- Add an explicit `if (getNodeBySlot(i) == NULL) continue;` (or equivalent helper) before deleting.
- Consider swapping the order in `verifyClusterConfigWithData()` to claim first, then delete unowned (owned-by-other) slots.
- Update the log text to avoid claiming "assigned to another node" when the slot is actually unassigned.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants