taskiq-redis 0.5.3__tar.gz → 0.5.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskiq-redis
3
- Version: 0.5.3
3
+ Version: 0.5.5
4
4
  Summary: Redis integration for taskiq
5
5
  Home-page: https://github.com/taskiq-python/taskiq-redis
6
6
  Keywords: taskiq,tasks,distributed,async,redis,result_backend
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3 :: Only
17
17
  Classifier: Programming Language :: Python :: 3.8
18
18
  Requires-Dist: redis (>=5,<6)
19
- Requires-Dist: taskiq (>=0.10.1,<1)
19
+ Requires-Dist: taskiq (>=0.10.3,<1)
20
20
  Project-URL: Repository, https://github.com/taskiq-python/taskiq-redis
21
21
  Description-Content-Type: text/markdown
22
22
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "taskiq-redis"
3
- version = "0.5.3"
3
+ version = "0.5.5"
4
4
  description = "Redis integration for taskiq"
5
5
  authors = ["taskiq-team <taskiq@norely.com>"]
6
6
  readme = "README.md"
@@ -26,7 +26,7 @@ keywords = [
26
26
 
27
27
  [tool.poetry.dependencies]
28
28
  python = "^3.8.1"
29
- taskiq = ">=0.10.1,<1"
29
+ taskiq = ">=0.10.3,<1"
30
30
  redis = "^5"
31
31
 
32
32
  [tool.poetry.group.dev.dependencies]
@@ -5,7 +5,10 @@ from taskiq_redis.redis_backend import (
5
5
  )
6
6
  from taskiq_redis.redis_broker import ListQueueBroker, PubSubBroker
7
7
  from taskiq_redis.redis_cluster_broker import ListQueueClusterBroker
8
- from taskiq_redis.schedule_source import RedisScheduleSource
8
+ from taskiq_redis.schedule_source import (
9
+ RedisClusterScheduleSource,
10
+ RedisScheduleSource,
11
+ )
9
12
 
10
13
  __all__ = [
11
14
  "RedisAsyncClusterResultBackend",
@@ -14,4 +17,5 @@ __all__ = [
14
17
  "PubSubBroker",
15
18
  "ListQueueClusterBroker",
16
19
  "RedisScheduleSource",
20
+ "RedisClusterScheduleSource",
17
21
  ]
@@ -1,9 +1,9 @@
1
- import dataclasses
2
1
  from typing import Any, List, Optional
3
2
 
4
- from redis.asyncio import ConnectionPool, Redis
3
+ from redis.asyncio import ConnectionPool, Redis, RedisCluster
5
4
  from taskiq import ScheduleSource
6
5
  from taskiq.abc.serializer import TaskiqSerializer
6
+ from taskiq.compat import model_dump, model_validate
7
7
  from taskiq.scheduler.scheduled_task import ScheduledTask
8
8
 
9
9
  from taskiq_redis.serializer import PickleSerializer
@@ -60,7 +60,7 @@ class RedisScheduleSource(ScheduleSource):
60
60
  async with Redis(connection_pool=self.connection_pool) as redis:
61
61
  await redis.set(
62
62
  f"{self.prefix}:{schedule.schedule_id}",
63
- self.serializer.dumpb(dataclasses.asdict(schedule)),
63
+ self.serializer.dumpb(model_dump(schedule)),
64
64
  )
65
65
 
66
66
  async def get_schedules(self) -> List[ScheduledTask]:
@@ -82,7 +82,7 @@ class RedisScheduleSource(ScheduleSource):
82
82
  if buffer:
83
83
  schedules.extend(await redis.mget(buffer))
84
84
  return [
85
- ScheduledTask(**self.serializer.loadb(schedule))
85
+ model_validate(ScheduledTask, self.serializer.loadb(schedule))
86
86
  for schedule in schedules
87
87
  if schedule
88
88
  ]
@@ -95,3 +95,82 @@ class RedisScheduleSource(ScheduleSource):
95
95
  async def shutdown(self) -> None:
96
96
  """Shut down the schedule source."""
97
97
  await self.connection_pool.disconnect()
98
+
99
+
100
+ class RedisClusterScheduleSource(ScheduleSource):
101
+ """
102
+ Source of schedules for redis cluster.
103
+
104
+ This class allows you to store schedules in redis.
105
+ Also it supports dynamic schedules.
106
+
107
+ :param url: url to redis cluster.
108
+ :param prefix: prefix for redis schedule keys.
109
+ :param buffer_size: buffer size for redis scan.
110
+ This is how many keys will be fetched at once.
111
+ :param max_connection_pool_size: maximum number of connections in pool.
112
+ :param serializer: serializer for data.
113
+ :param connection_kwargs: additional arguments for RedisCluster.
114
+ """
115
+
116
+ def __init__(
117
+ self,
118
+ url: str,
119
+ prefix: str = "schedule",
120
+ buffer_size: int = 50,
121
+ serializer: Optional[TaskiqSerializer] = None,
122
+ **connection_kwargs: Any,
123
+ ) -> None:
124
+ self.prefix = prefix
125
+ self.redis: RedisCluster[bytes] = RedisCluster.from_url(
126
+ url,
127
+ **connection_kwargs,
128
+ )
129
+ self.buffer_size = buffer_size
130
+ if serializer is None:
131
+ serializer = PickleSerializer()
132
+ self.serializer = serializer
133
+
134
+ async def delete_schedule(self, schedule_id: str) -> None:
135
+ """Remove schedule by id."""
136
+ await self.redis.delete(f"{self.prefix}:{schedule_id}") # type: ignore[attr-defined]
137
+
138
+ async def add_schedule(self, schedule: ScheduledTask) -> None:
139
+ """
140
+ Add schedule to redis.
141
+
142
+ :param schedule: schedule to add.
143
+ :param schedule_id: schedule id.
144
+ """
145
+ await self.redis.set( # type: ignore[attr-defined]
146
+ f"{self.prefix}:{schedule.schedule_id}",
147
+ self.serializer.dumpb(model_dump(schedule)),
148
+ )
149
+
150
+ async def get_schedules(self) -> List[ScheduledTask]:
151
+ """
152
+ Get all schedules from redis.
153
+
154
+ This method is used by scheduler to get all schedules.
155
+
156
+ :return: list of schedules.
157
+ """
158
+ schedules = []
159
+ buffer = []
160
+ async for key in self.redis.scan_iter(f"{self.prefix}:*"): # type: ignore[attr-defined]
161
+ buffer.append(key)
162
+ if len(buffer) >= self.buffer_size:
163
+ schedules.extend(await self.redis.mget(buffer)) # type: ignore[attr-defined]
164
+ buffer = []
165
+ if buffer:
166
+ schedules.extend(await self.redis.mget(buffer)) # type: ignore[attr-defined]
167
+ return [
168
+ model_validate(ScheduledTask, self.serializer.loadb(schedule))
169
+ for schedule in schedules
170
+ if schedule
171
+ ]
172
+
173
+ async def post_send(self, task: ScheduledTask) -> None:
174
+ """Delete a task after it's completed."""
175
+ if task.time is not None:
176
+ await self.delete_schedule(task.schedule_id)
File without changes