colinmollenhour / Cm_Cache_Backend_Redis

A Zend_Cache backend for Redis with full support for tags (works great with Magento)
Other
390 stars 142 forks source link

BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE. #141

Open kanevbg opened 5 years ago

kanevbg commented 5 years ago

Here is an error which occurs when Redis is busy (with LUA enabled): CredisException: Uncaught exception 'CredisException' with message 'BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.' in app/code/local/Credis/Client.php:1162

colinmollenhour commented 5 years ago

How do you suggest this error is handled?

kanevbg commented 5 years ago

I guess it should be treated as a kind of operational timeout and do retries based on configuration but I do not have full understanding of the issue because I had no time to examine.

colinmollenhour commented 5 years ago

I think retries would be reasonable. Please submit a PR if you so feel inclined. Thanks!

IJOL commented 1 month ago

We are running in this exact issue, and we end applying this patch


Subject: [PATCH] [UPD] Exportacion en xls
---
Index: Client.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/Client.php b/Client.php
--- a/Client.php    (revision f11a89fd068d3e5db0c2b5a9ba8663bc36162e95)
+++ b/Client.php    (date 1722245007668)
@@ -1226,9 +1226,26 @@
                     throw $e;
                 }
             } else {
-                $this->write_command($command);
-                $response = $this->read_reply($name);
-                $response = $this->decode_reply($name, $response, $trackedArgs);
+                $retryCount = 0;
+                $maxRetries = 5;
+
+                while ($retryCount < $maxRetries) {
+                    try {
+                        $this->write_command($command);
+                        $response = $this->read_reply($name);
+                        $response = $this->decode_reply($name, $response, $trackedArgs);
+                        break; // Exit loop if successful
+                    } catch (CredisException $e) {
+                        if (strpos($e->getMessage(), 'BUSY') === 0) {
+                            $retryCount++;
+                            if ($retryCount >= $maxRetries) {
+                                throw $e; // Rethrow exception after max retries
+                            }
+                        } else {
+                            throw $e; // Rethrow exception if message does not contain 'BUSY'
+                        }
+                    }
+                }
             }

             // Watch mode disables reconnect so error is thrown