From 14d5b0c69c077cdf18c4f2a932e784e5b08b699c Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Tue, 18 Feb 2020 15:19:51 +0100
Subject: [PATCH] Revert to apline:3.11 to stay on Python 3.7 (3.8 has issues
 with channels)

---
 api/Dockerfile                        |  2 +-
 api/config/settings/common.py         |  2 +-
 api/funkwhale_api/common/cache.py     | 29 +++++++++++++++++++++++++++
 api/funkwhale_api/common/channels.py  |  1 +
 api/funkwhale_api/common/consumers.py | 10 ++++++---
 5 files changed, 39 insertions(+), 5 deletions(-)
 create mode 100644 api/funkwhale_api/common/cache.py

diff --git a/api/Dockerfile b/api/Dockerfile
index 036330368..7a8526e83 100644
--- a/api/Dockerfile
+++ b/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.11
+FROM alpine:3.10
 
 RUN \
     echo 'installing dependencies' && \
diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index a2cbfd64e..45854515c 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -544,7 +544,7 @@ CHANNEL_LAYERS = {
 }
 
 CACHES["default"]["OPTIONS"] = {
-    "CLIENT_CLASS": "django_redis.client.DefaultClient",
+    "CLIENT_CLASS": "funkwhale_api.common.cache.RedisClient",
     "IGNORE_EXCEPTIONS": True,  # mimics memcache behavior.
     # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
 }
diff --git a/api/funkwhale_api/common/cache.py b/api/funkwhale_api/common/cache.py
new file mode 100644
index 000000000..d98b73797
--- /dev/null
+++ b/api/funkwhale_api/common/cache.py
@@ -0,0 +1,29 @@
+import logging
+
+from django_redis.client import default
+
+logger = logging.getLogger(__name__)
+
+
+class RedisClient(default.DefaultClient):
+    def get(self, key, default=None, version=None, client=None):
+        try:
+            return super().get(key, default=None, version=None, client=None)
+        except ValueError as e:
+            if "unsupported pickle protocol" in str(e):
+                # pickle deserialization error
+                logger.warn("Error while deserializing pickle value from cache")
+                return default
+            else:
+                raise
+
+    def get_many(self, *args, **kwargs):
+        try:
+            return super().get_many(*args, **kwargs)
+        except ValueError as e:
+            if "unsupported pickle protocol" in str(e):
+                # pickle deserialization error
+                logger.warn("Error while deserializing pickle value from cache")
+                return {}
+            else:
+                raise
diff --git a/api/funkwhale_api/common/channels.py b/api/funkwhale_api/common/channels.py
index d9422f6fa..4dcf59938 100644
--- a/api/funkwhale_api/common/channels.py
+++ b/api/funkwhale_api/common/channels.py
@@ -8,6 +8,7 @@ from django.core.serializers.json import DjangoJSONEncoder
 logger = logging.getLogger(__name__)
 channel_layer = get_channel_layer()
 group_add = async_to_sync(channel_layer.group_add)
+group_discard = async_to_sync(channel_layer.group_discard)
 
 
 def group_send(group, event):
diff --git a/api/funkwhale_api/common/consumers.py b/api/funkwhale_api/common/consumers.py
index 48c318638..9db4138ff 100644
--- a/api/funkwhale_api/common/consumers.py
+++ b/api/funkwhale_api/common/consumers.py
@@ -14,7 +14,11 @@ class JsonAuthConsumer(JsonWebsocketConsumer):
 
     def accept(self):
         super().accept()
-        for group in self.groups:
-            channels.group_add(group, self.channel_name)
-        for group in self.scope["user"].get_channels_groups():
+        groups = self.scope["user"].get_channels_groups() + self.groups
+        for group in groups:
             channels.group_add(group, self.channel_name)
+
+    def disconnect(self, close_code):
+        groups = self.scope["user"].get_channels_groups() + self.groups
+        for group in groups:
+            channels.group_discard(group, self.channel_name)
-- 
GitLab