File valkey-fake-client-flag.patch of Package valkey.39739

From 2f09b48e766c899addd241ea14f8a7b7606807a9 Mon Sep 17 00:00:00 2001
From: Binbin <binloveplay1314@qq.com>
Date: Wed, 27 Nov 2024 18:02:07 +0800
Subject: [PATCH] Use fake client flag to replace not conn check (#1198)

The fake client flag was introduced in #1063,
we want this to replace all !conn fake client checks.

Signed-off-by: Binbin <binloveplay1314@qq.com>
Signed-off-by: Jacob Murphy <jkmurphy@google.com>
---
 src/module.c     |  1 +
 src/networking.c | 12 ++++++++++--
 src/server.c     |  3 ++-
 src/server.h     |  7 ++++---
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/module.c b/src/module.c
index 938ae6ba70..0149676ef2 100644
--- a/src/module.c
+++ b/src/module.c
@@ -685,6 +685,7 @@ void moduleReleaseTempClient(client *c) {
     c->bufpos = 0;
     c->raw_flag = 0;
     c->flag.module = 1;
+    c->flag.fake = 1;
     c->user = NULL; /* Root user */
     c->cmd = c->lastcmd = c->realcmd = c->io_parsed_cmd = NULL;
     if (c->bstate.async_rm_call_handle) {
diff --git a/src/networking.c b/src/networking.c
index ed4f3582bc..9f4506c5fe 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -308,7 +308,11 @@ int prepareClientToWrite(client *c) {
      * is set. */
     if (c->flag.primary && !c->flag.primary_force_reply) return C_ERR;
 
-    if (!c->conn) return C_ERR; /* Fake client for AOF loading. */
+    /* Skip the fake client, such as the fake client for AOF loading.
+     * But CLIENT_ID_CACHED_RESPONSE is allowed since it is a fake client
+     * but has a connection to cache the response. */
+    if (c->flag.fake && c->id != CLIENT_ID_CACHED_RESPONSE) return C_ERR;
+    serverAssert(c->conn);
 
     /* 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). */
@@ -342,6 +346,9 @@ sds aggregateClientOutputBuffer(client *c) {
  * It needs be paired with `deleteCachedResponseClient` function to stop caching. */
 client *createCachedResponseClient(int resp) {
     struct client *recording_client = createClient(NULL);
+    /* It is a fake client but with a connection, setting a special client id,
+     * so we can identify it's a fake cached response client. */
+    recording_client->id = CLIENT_ID_CACHED_RESPONSE;
     recording_client->resp = resp;
     /* Allocating the `conn` allows to prepare the caching client before adding
      * data to the clients output buffer by `prepareClientToWrite`. */
@@ -4422,7 +4429,8 @@ int checkClientOutputBufferLimits(client *c) {
  *
  * Returns 1 if client was (flagged) closed. */
 int closeClientOnOutputBufferLimitReached(client *c, int async) {
-    if (!c->conn) return 0; /* It is unsafe to free fake clients. */
+    if (c->flag.fake) return 0; /* It is unsafe to free fake clients. */
+    serverAssert(c->conn);
     serverAssert(c->reply_bytes < SIZE_MAX - (1024 * 64));
     /* Note that c->reply_bytes is irrelevant for replica clients
      * (they use the global repl buffers). */
diff --git a/src/server.c b/src/server.c
index 1bdf2dd9e2..4243185b47 100644
--- a/src/server.c
+++ b/src/server.c
@@ -894,9 +894,10 @@ void updateClientMemoryUsage(client *c) {
 }
 
 int clientEvictionAllowed(client *c) {
-    if (server.maxmemory_clients == 0 || c->flag.no_evict || !c->conn) {
+    if (server.maxmemory_clients == 0 || c->flag.no_evict || c->flag.fake) {
         return 0;
     }
+    serverAssert(c->conn);
     int type = getClientType(c);
     return (type == CLIENT_TYPE_NORMAL || type == CLIENT_TYPE_PUBSUB);
 }
diff --git a/src/server.h b/src/server.h
index fceb2894a2..82cec6c7f5 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1102,9 +1102,10 @@ typedef struct {
  * Clients are taken in a linked list. */
 
 #define CLIENT_ID_AOF                                                                                                  \
-    (UINT64_MAX) /* Reserved ID for the AOF client. If you                                                             \
-                    need more reserved IDs use UINT64_MAX-1,                                                           \
-                    -2, ... and so forth. */
+    (UINT64_MAX)                                   /* Reserved ID for the AOF client. If you                           \
+                                                      need more reserved IDs use UINT64_MAX-1,                         \
+                                                      -2, ... and so forth. */
+#define CLIENT_ID_CACHED_RESPONSE (UINT64_MAX - 1) /* Client for cached response, see createCachedResponseClient. */
 
 /* Replication backlog is not a separate memory, it just is one consumer of
  * the global replication buffer. This structure records the reference of
openSUSE Build Service is sponsored by