Repository: valkey-io/valkey
File: src/cluster_legacy.c (C)

Code before:
 * of failure reports from other nodes.
 *
 * This function scans the radix tree of failure reports (keyed by bucketed
 * timestamps plus sender pointer) for the given node and removes any entries that
 * have expired beyond the cutoff window
 *
 * By expiring entries older than the global node timeout window,
 * we guarantee only fresh votes remain. */
void clusterNodeCleanupFailureReports(clusterNode *node) {
    mstime_t now = mstime();
    mstime_t timeout = server.cluster_node_timeout * CLUSTER_FAIL_REPORT_VALIDITY_MULT;
    mstime_t cutoff = now - timeout;

    raxIterator ri;
    raxStart(&ri, node->fail_reports);
    raxSeek(&ri, "^", NULL, 0);

    while (raxNext(&ri)) {
        mstime_t reported_time;
        clusterNode *reported_node;
        decodeFailureReportKey(ri.key, &reported_time, &reported_node);
        if (reported_time > cutoff) break;
        if (raxRemove(node->fail_reports, ri.key, ri.key_len, NULL)) {
            /* Move directly to the next element after the tree mutation due to removal */
            raxSeek(&ri, ">=", ri.key, ri.key_len);
        }
    }

    raxStop(&ri);
}

/* Remove the failing report for 'node' if it was previously considered
 * failing by 'sender'. This function is called when a node informs us via
 * gossip that a node is OK from its point of view (no FAIL or PFAIL flags).
 *
 * Note that this function is called relatively often as it gets called even
 * when there are no nodes failing, and is O(N), however when the cluster is
 * fine the failure reports list is empty so the function runs in constant
 * time.
 *
 * The function returns 1 if the failure report was found and removed.
 * Otherwise 0 is returned. */
int clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) {
    raxIterator ri;
    raxStart(&ri, node->fail_reports);
    raxSeek(&ri, "^", NULL, 0);

    while (raxNext(&ri)) {
        mstime_t reported_time;
        clusterNode *reported_node;
        decodeFailureReportKey(ri.key, &reported_time, &reported_node);

Review comment (bug):
```suggestion
        int retval = raxRemove(node->fail_reports, ri.key, ri.key_len, NULL));
        serverAssert(retval != 1);
        /* Move directly to the next element after the tree mutation due to removal */
        raxSeek(&ri, ">=", ri.key, ri.key_len);
```
This should never fail right?

Code after:
 * of failure reports from other nodes.
 *
 * This function scans the radix tree of failure reports (keyed by bucketed
 * timestamps plus sender pointer) for the given node and removes any entries that
 * have expired beyond the cutoff window
 *
 * By expiring entries older than the global node timeout window,
 * we guarantee only fresh votes remain. */
void clusterNodeCleanupFailureReports(clusterNode *node) {
    mstime_t now = mstime();
    mstime_t timeout = server.cluster_node_timeout * CLUSTER_FAIL_REPORT_VALIDITY_MULT;
    mstime_t cutoff = now - timeout;

    raxIterator ri;
    raxStart(&ri, node->fail_reports);
    raxSeek(&ri, "^", NULL, 0);

    while (raxNext(&ri)) {
        mstime_t reported_time;
        clusterNode *reported_node;
        decodeFailureReportKey(ri.key, &reported_time, &reported_node);
        if (reported_time > cutoff) break;

        int retval = raxRemove(node->fail_reports, ri.key, ri.key_len, NULL);
        serverAssert(retval == 1);
        /* Move directly to the next element after the tree mutation due to removal */
        raxSeek(&ri, ">=", ri.key, ri.key_len);
    }

    raxStop(&ri);
}

/* Remove the failing report for 'node' if it was previously considered
 * failing by 'sender'. This function is called when a node informs us via
 * gossip that a node is OK from its point of view (no FAIL or PFAIL flags).
 *
 * Note that this function is called relatively often as it gets called even
 * when there are no nodes failing, and is O(N), however when the cluster is
 * fine the failure reports list is empty so the function runs in constant
 * time.
 *
 * The function returns 1 if the failure report was found and removed.
 * Otherwise 0 is returned. */
int clusterNodeDelFailureReport(clusterNode *node, clusterNode *sender) {
    raxIterator ri;
    raxStart(&ri, node->fail_reports);
    raxSeek(&ri, "^", NULL, 0);

    while (raxNext(&ri)) {
        mstime_t reported_time;
        clusterNode *reported_node;