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

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/>. 

13 

14"""A provider of the Redis PubSub class.""" 

15 

16import logging 

17from collections.abc import Collection 

18from dataclasses import dataclass 

19from typing import Any, Final 

20 

21from redis.asyncio.client import PubSub, Redis 

22 

23from .. import EVENT_REDIS 

24 

25LOGGER: Final = logging.getLogger(__name__) 

26 

27 

28@dataclass(slots=True) 

29class PubSubProvider: 

30 """Provide a PubSub object.""" 

31 

32 channels: Collection[str] 

33 settings: dict[str, Any] 

34 worker: int | None 

35 _ps: PubSub | None = None 

36 _redis: Redis[str] | None = None 

37 

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) 

42 

43 await EVENT_REDIS.wait() 

44 

45 redis: Redis[str] = self.settings["REDIS"] 

46 

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() 

54 

55 self._ps = redis.pubsub() 

56 self._redis = redis 

57 await self._ps.subscribe(*self.channels) 

58 return self._ps