Update redis, and implement a custom channel layer to send datetime/decimal objects
This commit is contained in:
parent
461ab6c7a1
commit
9dc049d04f
3 changed files with 47 additions and 2 deletions
|
@ -148,7 +148,7 @@ CACHES = {
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
CHANNEL_LAYERS = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
"BACKEND": "shared.channels.ChannelLayer",
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
"hosts": [
|
"hosts": [
|
||||||
(
|
(
|
||||||
|
|
|
@ -5,7 +5,7 @@ psycopg2<2.8
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
django-redis-cache==3.0.*
|
django-redis-cache==3.0.*
|
||||||
redis~=2.10.6
|
redis==3.5.*
|
||||||
channels-redis==3.4.*
|
channels-redis==3.4.*
|
||||||
|
|
||||||
# ASGI protocol and HTTP server
|
# ASGI protocol and HTTP server
|
||||||
|
|
45
shared/channels.py
Normal file
45
shared/channels.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import datetime
|
||||||
|
import random
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
import msgpack
|
||||||
|
from channels_redis.core import RedisChannelLayer
|
||||||
|
|
||||||
|
|
||||||
|
def encode_kf(obj):
|
||||||
|
if isinstance(obj, Decimal):
|
||||||
|
return {"__decimal__": True, "as_str": str(obj)}
|
||||||
|
elif isinstance(obj, datetime.datetime):
|
||||||
|
return {"__datetime__": True, "as_str": obj.strftime("%Y%m%dT%H:%M:%S.%f")}
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def decode_kf(obj):
|
||||||
|
if "__decimal__" in obj:
|
||||||
|
obj = Decimal(obj["as_str"])
|
||||||
|
elif "__datetime__" in obj:
|
||||||
|
obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class ChannelLayer(RedisChannelLayer):
|
||||||
|
def serialize(self, message):
|
||||||
|
"""Serializes to a byte string."""
|
||||||
|
value = msgpack.packb(message, default=encode_kf, use_bin_type=True)
|
||||||
|
|
||||||
|
if self.crypter:
|
||||||
|
value = self.crypter.encrypt(value)
|
||||||
|
|
||||||
|
# As we use an sorted set to expire messages
|
||||||
|
# we need to guarantee uniqueness, with 12 bytes.
|
||||||
|
random_prefix = random.getrandbits(8 * 12).to_bytes(12, "big")
|
||||||
|
return random_prefix + value
|
||||||
|
|
||||||
|
def deserialize(self, message):
|
||||||
|
"""Deserializes from a byte string."""
|
||||||
|
# Removes the random prefix
|
||||||
|
message = message[12:]
|
||||||
|
|
||||||
|
if self.crypter:
|
||||||
|
message = self.crypter.decrypt(message, self.expiry + 10)
|
||||||
|
return msgpack.unpackb(message, object_hook=decode_kf, raw=False)
|
Loading…
Reference in a new issue