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

Code before:
                best_replica = replica;
            }
        }

        if (best_replica) {
            /* Send the CLUSTER FAILOVER FORCE REPLICAID node-id to all replicas since
             * it is a shared replication buffer, but only the replica with the matching
             * node-id will execute it. The caller will call flushReplicasOutputBuffers,
             * so in here it is a best effort. */
            char buf[128];
            size_t buflen = snprintf(buf, sizeof(buf),
                                     "*5\r\n$7\r\nCLUSTER\r\n"
                                     "$8\r\nFAILOVER\r\n"
                                     "$5\r\nFORCE\r\n"
                                     "$9\r\nREPLICAID\r\n"
                                     "$%d\r\n%s\r\n",
                                     CLUSTER_NAMELEN,
                                     (char *)best_replica->name->ptr);
            /* Must install write handler for all replicas first before feeding
             * replication stream. */
            prepareReplicasToWrite();
            feedReplicationBuffer(buf, buflen);
            serverLog(LL_NOTICE, "Perform auto failover to replica %s on shutdown.", (char *)best_replica->name->ptr);
        } else {
            if (old_replica) {
                serverLog(LL_NOTICE, "Unable to perform auto failover on shutdown since there are old replicas.");
            } else {
                serverLog(LL_NOTICE, "Unable to find a replica to perform the auto failover on shutdown.");
            }
        }
    }

    /* The error logs have been logged in the save function if the save fails. */
    serverLog(LL_NOTICE, "Saving the cluster configuration file before exiting.");
    clusterSaveConfig(1);

#if !defined(__sun)
    /* Unlock the cluster config file before shutdown, see clusterLockConfig.
     *
     * This is needed if you shutdown a very large server process, it will take
     * a while for the OS to release resources and unlock the cluster configuration
     * file. Therefore, if we immediately try to restart the server process, it
     * may not be able to acquire the lock on the cluster configuration file and
     * fail to start. We explicitly releases the lock on the cluster configuration
     * file on shutdown, rather than relying on the OS to release the lock, which
     * is a cleaner and safer way to release acquired resources. */
    if (server.cluster_config_file_lock_fd != -1) {
        flock(server.cluster_config_file_lock_fd, LOCK_UN | LOCK_NB);
    }
#endif /* __sun */
}

Review comment (bug):
```suggestion
                serverLog(LL_NOTICE, "Unable to perform auto failover on shutdown since there are legacy replicas.");
```

Code after:
        }
        if (replica->repl_data->repl_state == REPLICA_STATE_ONLINE &&
            replica->repl_data->repl_ack_off == server.primary_repl_offset &&
            replica->repl_data->replica_nodeid && sdslen(replica->repl_data->replica_nodeid) == CLUSTER_NAMELEN) {
            best_replica = replica;
        }
    }

    /* We are not able to find the replica to do the auto failover. */
    if (best_replica == NULL) {
        if (legacy_replica) {
            serverLog(LL_NOTICE, "Unable to perform auto failover on shutdown since there are legacy replicas.");
        } else {
            serverLog(LL_NOTICE, "Unable to find a replica to perform the auto failover on shutdown.");
        }
        return;
    }

    /* Send the CLUSTER FAILOVER FORCE REPLICAID node-id to all replicas since
     * it is a shared replication buffer, but only the replica with the matching
     * node-id will execute it. The caller will call flushReplicasOutputBuffers,
     * so in here it is a best effort. */
    char buf[128];
    size_t buflen = snprintf(buf, sizeof(buf),
                             "*5\r\n$7\r\nCLUSTER\r\n"
                             "$8\r\nFAILOVER\r\n"
                             "$5\r\nFORCE\r\n"
                             "$9\r\nREPLICAID\r\n"
                             "$%d\r\n%.*s\r\n",
                             CLUSTER_NAMELEN,
                             CLUSTER_NAMELEN,
                             best_replica->repl_data->replica_nodeid);
    serverAssert(buflen <= 128);
    /* Must install write handler for all replicas first before feeding
     * replication stream. */
    prepareReplicasToWrite();
    feedReplicationBuffer(buf, buflen);
    serverLog(LL_NOTICE, "Perform auto failover to replica %s on shutdown.", best_replica->repl_data->replica_nodeid);
}

/* Called when a cluster node receives SHUTDOWN. */
void clusterHandleServerShutdown(void) {
    /* Check if we are able to do the auto failover on shutdown. */
    clusterAutoFailoverOnShutdown();

    /* The error logs have been logged in the save function if the save fails. */
    serverLog(LL_NOTICE, "Saving the cluster configuration file before exiting.");
    clusterSaveConfig(1);

#if !defined(__sun)
    /* Unlock the cluster config file before shutdown, see clusterLockConfig.