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

Code before:

    if (!c->conn) return C_ERR; /* Fake client for AOF loading. */

    /* Schedule the client to write the output buffers to the socket, unless
     * it should already be setup to do so (it has already pending data).
     *
     * If CLIENT_PENDING_READ is set, we're in an IO thread and should
     * not put the client in pending write queue. Instead, it will be
     * done by handleClientsWithPendingReadsUsingThreads() upon return.
     */
    if (!clientHasPendingReplies(c) && io_threads_op == IO_THREADS_OP_IDLE)
        putClientInPendingWriteQueue(c);

    /* Authorize the caller to queue in the output buffer of this client. */
    return C_OK;
}

/* Returns everything in the client reply linked list in a SDS format. */
static sds getClientOutputBuffer(client *c) {
    sds cmd_response = sdsempty();
    listIter li;
    listNode *ln;
    clientReplyBlock *val_block;
    listRewind(c->reply,&li);
    
    serverAssert(c->bufpos == 0);
    while ((ln = listNext(&li)) != NULL) {
        val_block = (clientReplyBlock *)listNodeValue(ln);
        cmd_response = sdscatlen(cmd_response, val_block->buf,val_block->used);
    }
    return cmd_response;
}

/* This function creates and returns a fake client for recording the command response 
 * to initiate caching of any command response.
 *
 * It needs be paired with `stopCaching` function to stop caching. */
client *createCachedResponseClient(void) {
    struct client *recording_client = createClient(NULL);
    /* Allocating the `conn` allows to prepare the caching client before adding
     * data to the clients output buffer by `prepareClientToWrite`. */
    recording_client->conn  = zcalloc(sizeof(connection));
    return recording_client;
}

/* This function is used to stop caching of any command response after `createCachedResponseClient` is called.
 * It returns the command response as SDS from the recording_client's reply buffer. */
sds stopCaching(client *recording_client) {
    zfree(recording_client->conn);
    recording_client->conn = NULL;
    sds output_buff = getClientOutputBuffer(recording_client);

Review comment (suggestion):
I think it might not be clear why `c->bufpos` would be `0` here. We should call out this method should only be used for fake recording client where the statically allocated block isn't used.

Code after:

    if (!c->conn) return C_ERR; /* Fake client for AOF loading. */

    /* Schedule the client to write the output buffers to the socket, unless
     * it should already be setup to do so (it has already pending data).
     *
     * If CLIENT_PENDING_READ is set, we're in an IO thread and should
     * not put the client in pending write queue. Instead, it will be
     * done by handleClientsWithPendingReadsUsingThreads() upon return.
     */
    if (!clientHasPendingReplies(c) && io_threads_op == IO_THREADS_OP_IDLE)
        putClientInPendingWriteQueue(c);

    /* Authorize the caller to queue in the output buffer of this client. */
    return C_OK;
}

/* Returns everything in the client reply linked list in a SDS format.
 * This should only be used only with a caching client. */
sds aggregateClientOutputBuffer(client *c) {
    sds cmd_response = sdsempty();
    listIter li;
    listNode *ln;
    clientReplyBlock *val_block;
    listRewind(c->reply,&li);

    /* Here, c->buf is not used, thus we confirm c->bufpos remains 0. */
    serverAssert(c->bufpos == 0);
    while ((ln = listNext(&li)) != NULL) {
        val_block = (clientReplyBlock *)listNodeValue(ln);
        cmd_response = sdscatlen(cmd_response, val_block->buf,val_block->used);
    }
    return cmd_response;
}

/* This function creates and returns a fake client for recording the command response 
 * to initiate caching of any command response.
 *
 * It needs be paired with `deleteCachedResponseClient` function to stop caching. */
client *createCachedResponseClient(void) {
    struct client *recording_client = createClient(NULL);
    /* Allocating the `conn` allows to prepare the caching client before adding
     * data to the clients output buffer by `prepareClientToWrite`. */
    recording_client->conn  = zcalloc(sizeof(connection));
    return recording_client;
}

/* This function is used to stop caching of any command response after `createCachedResponseClient` is called.
 * It returns the command response as SDS from the recording_client's reply buffer. */
void deleteCachedResponseClient(client *recording_client) {
    zfree(recording_client->conn);