Coverage for an_website/emoji_chat/pub_sub_provider.py: 48.000%
25 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-10 18:56 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-10 18:56 +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."""
16import logging
17from collections.abc import Collection
18from dataclasses import dataclass
19from typing import Any, Final
21from redis.asyncio.client import PubSub, Redis
23from .. import EVENT_REDIS
25LOGGER: Final = logging.getLogger(__name__)
28@dataclass(slots=True)
29class PubSubProvider:
30 """Provide a PubSub object."""
32 channels: Collection[str]
33 settings: dict[str, Any]
34 worker: int | None
35 _ps: PubSub | None = None
36 _redis: Redis[str] | None = None
38 async def __call__(self) -> PubSub:
39 """Get PubSub object."""
40 if not self.settings.get("REDIS"):
41 LOGGER.error("Redis not available on worker %s", self.worker)
43 await EVENT_REDIS.wait()
45 redis: Redis[str] = self.settings["REDIS"]
47 if self._ps:
48 if self._redis == redis:
49 return self._ps
50 LOGGER.info(
51 "Closing old PubSub connection on worker %s", self.worker
52 )
53 await self._ps.close()
55 self._ps = redis.pubsub()
56 self._redis = redis
57 await self._ps.subscribe(*self.channels)
58 return self._ps