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

Code before:
        freeClusterLink(link);
        server.cluster->stat_cluster_links_buffer_limit_exceeded++;
    }
}

/* Free outbound link to a node if its send buffer size exceeded limit. */
static void clusterNodeCronFreeLinkOnBufferLimitReached(clusterNode *node) {
    freeClusterLinkOnBufferLimitReached(node->link);
    freeClusterLinkOnBufferLimitReached(node->inbound_link);
}

/**
 * Compute the maximum number of connection attempts the cluster-cron
 * loop should schedule in a single cron.
 *
 * We want to guarantee that every node is contacted twice within cluster node timeout.
 */
static long long maxConnectionAttemptsPerCron(const int nodes, const long long timeout_ms) {
    if (nodes <= 0 || timeout_ms <= 0)
        return 0;
    /*
     * We run the cron loop every 100 ms.  To reach 100 % of the nodes
     * within the timeout, we need: ceil(nodes * 100 / timeout_ms)
     * We use (a + b − 1) / b to give us the integer-ceil without using floating-point.
     */
    const long long min_nodes_for_coverage = (nodes * 100 + timeout_ms - 1) / timeout_ms;
    /*
     * Increase the coverage budget so each node can be probed 10 times
     * inside the timeout.
     */
    return min_nodes_for_coverage * NODE_CONNECTION_RETRIES_PER_TIMEOUT;
}

/* This is executed 10 times every second */
void clusterCron(void) {
    dictIterator *di;
    dictEntry *de;
    int update_state = 0;
    int orphaned_primaries; /* How many primaries there are without ok replicas. */
    int max_replicas;       /* Max number of ok replicas for a single primary. */
    int this_replicas;      /* Number of ok replicas for our primary (if we are replica). */
    mstime_t min_pong = 0, now = mstime();
    clusterNode *min_pong_node = NULL;
    static unsigned long long iteration = 0;
    int cluster_node_conn_attempts = 0;

    iteration++; /* Number of times this function was called so far. */

    clusterUpdateMyselfHostname();

    /* Clear so clusterNodeCronHandleReconnect can count the number of nodes in PFAIL. */

Review comment (suggestion):
Let's add a macro here. I'm fine with ceil as well, do you see any risk here?

`#define CLUSTER_CRON_PERIOD_MS 100`

Code after:
             * so we claim we actually sent a ping now (that will
             * be really sent as soon as the link is obtained). */
            if (node->ping_sent == 0) node->ping_sent = mstime();
            serverLog(LL_DEBUG,
                      "Unable to connect to "
                      "Cluster Node [%s]:%d -> %s",
                      node->ip, node->cport, server.neterr);

            freeClusterLink(link);
            return 0;
        }
    }
    return 0;
}

static void freeClusterLinkOnBufferLimitReached(clusterLink *link) {
    if (link == NULL || server.cluster_link_msg_queue_limit_bytes == 0) {
        return;
    }

    unsigned long long mem_link = link->send_msg_queue_mem;
    if (mem_link > server.cluster_link_msg_queue_limit_bytes) {
        serverLog(LL_WARNING,
                  "Freeing cluster link(%s node %.40s, used memory: %llu) due to "
                  "exceeding send buffer memory limit.",
                  link->inbound ? "from" : "to", link->node ? link->node->name : "", mem_link);
        freeClusterLink(link);
        server.cluster->stat_cluster_links_buffer_limit_exceeded++;
    }
}

/* Free outbound link to a node if its send buffer size exceeded limit. */
static void clusterNodeCronFreeLinkOnBufferLimitReached(clusterNode *node) {
    freeClusterLinkOnBufferLimitReached(node->link);
    freeClusterLinkOnBufferLimitReached(node->inbound_link);
}

/* Compute the maximum number of connection attempts the clusterCron
 * loop should schedule in a single cron.
 *
 * We want to guarantee that every node is contacted 10 times within node timeout. */
static long long maxConnectionAttemptsPerCron(void) {
    long long reconnect_interval = server.cluster_node_timeout / 2;
    if (reconnect_interval <= 0)
        return 0;
    /* We run the cron loop every 100 ms.  To reach 100 % of the nodes
     * within the timeout, we need: ceil(nodes * 100 / reconnect_interval) */
    const long long min_nodes_for_coverage = dictSize(server.cluster->nodes) * CLUSTER_CRON_PERIOD_MS / reconnect_interval;
    /* Increase the coverage budget so each node can be probed 10 times
     * inside the timeout. */
    return min_nodes_for_coverage * NODE_CONNECTION_RETRIES_PER_TIMEOUT;