Coverage for an_website / emoji_chat / pub_sub_provider.py: 48.000%
25 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-24 18:51 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-24 18:51 +0000
1# This program is free software: you can redistribute it and/or modify
2# it under the terms of the GNU Affero General Public License as
3# published by the Free Software Foundation, either version 3 of the
4# License, or (at your option) any later version.
5#
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU Affero General Public License for more details.
10#
11# You should have received a copy of the GNU Affero General Public License
12# along with this program. If not, see <https://www.gnu.org/licenses/>.
14"""A provider of the Redis PubSub class."""
17import logging
18from collections.abc import Collection
19from dataclasses import dataclass
20from typing import Any, Final
22from redis.asyncio.client import PubSub, Redis
24from .. import EVENT_REDIS
26LOGGER: Final = logging.getLogger(__name__)
29@dataclass(slots=True)
30class PubSubProvider:
31 """Provide a PubSub object."""
33 channels: Collection[str]
34 settings: dict[str, Any]
35 worker: int | None
36 _ps: PubSub | None = None
37 _redis: Redis[str] | None = None
39 async def __call__(self) -> PubSub:
40 """Get PubSub object."""
41 if not self.settings.get("REDIS"):
42 LOGGER.error("Redis not available on worker %s", self.worker)
44 await EVENT_REDIS.wait()
46 redis: Redis[str] = self.settings["REDIS"]
48 if self._ps:
49 if self._redis == redis:
50 return self._ps
51 LOGGER.info(
52 "Closing old PubSub connection on worker %s", self.worker
53 )
54 await self._ps.close()
56 self._ps = redis.pubsub()
57 self._redis = redis
58 await self._ps.subscribe(*self.channels)
59 return self._ps