2018-05-14 20:09:25 +02:00
|
|
|
import json
|
2024-04-05 02:54:45 +02:00
|
|
|
from typing import Any, Dict, Optional, Union
|
2018-05-14 20:09:25 +02:00
|
|
|
|
|
|
|
from redis import Redis
|
|
|
|
|
|
|
|
from platypush.backend import Backend
|
|
|
|
from platypush.message import Message
|
2024-04-05 02:54:45 +02:00
|
|
|
from platypush.utils import get_redis_conf
|
2018-05-14 20:09:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
class RedisBackend(Backend):
|
|
|
|
"""
|
2018-06-26 00:16:39 +02:00
|
|
|
Backend that reads messages from a configured Redis queue (default:
|
2024-04-05 02:54:45 +02:00
|
|
|
``platypush/backend/redis``) and forwards them to the application bus.
|
|
|
|
|
|
|
|
Useful when you have plugin whose code is executed in another process
|
2018-05-14 20:09:25 +02:00
|
|
|
and can't post events or requests to the application bus.
|
|
|
|
"""
|
|
|
|
|
2024-04-05 02:54:45 +02:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
*args,
|
|
|
|
queue: str = 'platypush/backend/redis',
|
|
|
|
redis_args: Optional[Dict[str, Any]] = None,
|
|
|
|
**kwargs
|
|
|
|
):
|
2018-05-14 20:09:25 +02:00
|
|
|
"""
|
2024-04-05 02:54:45 +02:00
|
|
|
:param queue: Name of the Redis queue to listen to (default:
|
|
|
|
``platypush/backend/redis``).
|
2018-06-26 00:16:39 +02:00
|
|
|
|
2024-04-05 02:54:45 +02:00
|
|
|
:param redis_args: Arguments that will be passed to the redis-py
|
|
|
|
constructor (e.g. host, port, password). See
|
|
|
|
https://redis-py.readthedocs.io/en/latest/connections.html#redis.Redis
|
|
|
|
for supported parameters.
|
2018-05-14 20:09:25 +02:00
|
|
|
"""
|
|
|
|
super().__init__(*args, **kwargs)
|
2024-04-05 02:54:45 +02:00
|
|
|
self.redis_args = redis_args or get_redis_conf()
|
2018-05-14 20:09:25 +02:00
|
|
|
self.queue = queue
|
2021-07-26 01:06:35 +02:00
|
|
|
self.redis: Optional[Redis] = None
|
2018-05-14 20:09:25 +02:00
|
|
|
|
2023-02-05 22:00:50 +01:00
|
|
|
def send_message(
|
|
|
|
self, msg: Union[str, Message], queue_name: Optional[str] = None, **_
|
|
|
|
):
|
|
|
|
"""
|
|
|
|
Send a message to a Redis queue.
|
|
|
|
|
|
|
|
:param msg: Message to send, as a ``Message`` object or a string.
|
2024-04-05 02:54:45 +02:00
|
|
|
:param queue_name: Queue name to send the message to (default:
|
|
|
|
configured ``queue`` value).
|
2023-02-05 22:00:50 +01:00
|
|
|
"""
|
|
|
|
if not self.redis:
|
|
|
|
self.logger.warning('The Redis backend is not yet running.')
|
|
|
|
return
|
|
|
|
|
|
|
|
self.redis.rpush(queue_name or self.queue, str(msg))
|
2018-06-29 10:21:16 +02:00
|
|
|
|
2024-04-05 02:54:45 +02:00
|
|
|
def get_message(self, queue_name: Optional[str] = None) -> Optional[Message]:
|
2018-06-29 10:21:16 +02:00
|
|
|
queue = queue_name or self.queue
|
2024-04-05 02:54:45 +02:00
|
|
|
assert self.redis, 'The Redis backend is not yet running.'
|
2021-02-23 23:07:35 +01:00
|
|
|
data = self.redis.blpop(queue, timeout=1)
|
|
|
|
if data is None:
|
2024-04-05 02:54:45 +02:00
|
|
|
return None
|
2018-06-29 10:21:16 +02:00
|
|
|
|
2021-02-23 23:07:35 +01:00
|
|
|
msg = data[1].decode()
|
2018-06-29 10:21:16 +02:00
|
|
|
try:
|
2021-02-23 23:07:35 +01:00
|
|
|
msg = Message.build(msg)
|
2021-04-05 00:58:44 +02:00
|
|
|
except Exception as e:
|
|
|
|
self.logger.debug(str(e))
|
2018-06-29 11:09:28 +02:00
|
|
|
try:
|
2024-04-05 02:54:45 +02:00
|
|
|
msg = json.loads(msg)
|
2021-04-05 00:58:44 +02:00
|
|
|
except Exception as ee:
|
2024-04-05 02:54:45 +02:00
|
|
|
self.logger.exception(ee)
|
2018-06-29 10:21:16 +02:00
|
|
|
|
|
|
|
return msg
|
2018-05-14 20:09:25 +02:00
|
|
|
|
2018-10-25 20:45:58 +02:00
|
|
|
def run(self):
|
|
|
|
super().run()
|
2023-02-05 22:00:50 +01:00
|
|
|
self.logger.info(
|
|
|
|
'Initialized Redis backend on queue %s with arguments %s',
|
|
|
|
self.queue,
|
|
|
|
self.redis_args,
|
|
|
|
)
|
2018-05-14 20:09:25 +02:00
|
|
|
|
2021-07-26 01:06:35 +02:00
|
|
|
with Redis(**self.redis_args) as self.redis:
|
|
|
|
while not self.should_stop():
|
|
|
|
try:
|
|
|
|
msg = self.get_message()
|
|
|
|
if not msg:
|
|
|
|
continue
|
|
|
|
|
2023-02-05 22:00:50 +01:00
|
|
|
self.logger.info('Received message on the Redis backend: %s', msg)
|
2021-07-26 01:06:35 +02:00
|
|
|
self.on_message(msg)
|
|
|
|
except Exception as e:
|
|
|
|
self.logger.exception(e)
|
2018-05-14 20:09:25 +02:00
|
|
|
|
2021-02-23 23:07:35 +01:00
|
|
|
self.logger.info('Redis backend terminated')
|
|
|
|
|
2018-05-14 20:09:25 +02:00
|
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|