buz 2.15.7__py3-none-any.whl → 2.15.8rc1__py3-none-any.whl

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,3 +1,4 @@
1
+ from collections import defaultdict
1
2
  import json
2
3
  import traceback
3
4
  from abc import abstractmethod
@@ -39,6 +40,7 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
39
40
  __SECONDS_BETWEEN_EXECUTIONS_IF_THERE_ARE_NO_TASKS_IN_THE_QUEUE = 1
40
41
  __SECONDS_BETWEEN_POLLS_IF_THERE_ARE_TASKS_IN_THE_QUEUE = 1
41
42
  __SECONDS_BETWEEN_POLLS_IF_THERE_ARE_NO_NEW_TASKS = 1
43
+ __SECONDS_TO_WAIT_BETWEEN_REBALANCING_IN_PROGRESS = 0.1
42
44
  __MAX_NUMBER_OF_CONCURRENT_POLLING_TASKS = 20
43
45
 
44
46
  def __init__(
@@ -103,8 +105,9 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
103
105
  )
104
106
  self.__wait_for_connection_to_cluster_ms: Optional[int] = wait_for_connection_to_cluster_ms
105
107
  self.__polling_tasks_semaphore = Semaphore(self.__max_number_of_concurrent_polling_tasks)
106
- self.__task_execution_mutex = Lock()
108
+ self.__consumer_and_partition_mutex: dict[str, Lock] = defaultdict(Lock)
107
109
  self.__is_worked_initialized = False
110
+ self.__number_of_rebalancing_processes_in_progress: int = 0
108
111
 
109
112
  async def configure_http_check_server(self, health_check_port: int) -> web.TCPSite:
110
113
  self._logger.info(f"Starting health check server on port {health_check_port}")
@@ -303,29 +306,59 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
303
306
  last_consumer, _ = next(consumer_queues_cyclic_iterator)
304
307
 
305
308
  while not self.__should_stop.is_set():
309
+ if self.is_rebalancing_in_progress():
310
+ self._logger.info("Waiting for rebalancing")
311
+ await sleep(self.__SECONDS_TO_WAIT_BETWEEN_REBALANCING_IN_PROGRESS)
312
+ continue
313
+
306
314
  if await self.__all_queues_are_empty():
307
315
  await sleep(self.__seconds_between_executions_if_there_are_no_tasks_in_the_queue)
308
316
  continue
309
317
 
310
- async with self.__task_execution_mutex:
311
- consumer: Optional[AIOKafkaConsumer] = None
318
+ consumer: Optional[AIOKafkaConsumer] = None
319
+
320
+ while consumer != last_consumer:
321
+ consumer, queue = next(consumer_queues_cyclic_iterator)
322
+ kafka_poll_record = queue.pop()
323
+
324
+ if kafka_poll_record is not None:
325
+ consuming_task = ConsumingTask(consumer, kafka_poll_record)
326
+ async with self.__get_partition_mutex(
327
+ consumer_fqn=consuming_task.consumer.get_consumer_group(),
328
+ partition=kafka_poll_record.partition,
329
+ ):
330
+ yield consuming_task
312
331
 
313
- while consumer != last_consumer:
314
- consumer, queue = next(consumer_queues_cyclic_iterator)
315
- kafka_poll_record = queue.pop()
332
+ last_consumer = consumer
333
+ break
316
334
 
317
- if kafka_poll_record is not None:
318
- yield ConsumingTask(consumer, kafka_poll_record)
319
- last_consumer = consumer
320
- break
335
+ def __get_partition_mutex(self, consumer_fqn: str, partition: int) -> Lock:
336
+ mutex_key = f"consumer_{consumer_fqn}_partition_{partition}"
337
+ return self.__consumer_and_partition_mutex[mutex_key]
321
338
 
322
339
  async def __all_queues_are_empty(self) -> bool:
323
340
  return all([queue.is_totally_empty() for queue in self.__queue_per_consumer_mapper.values()])
324
341
 
325
342
  async def __on_partition_revoked(self, consumer: AIOKafkaConsumer, topics_partitions: set[TopicPartition]) -> None:
326
- async with self.__task_execution_mutex:
327
- for topic_partition in topics_partitions:
343
+ self._logger.info(f"rebalancing in progress, revoking partitions {topics_partitions}")
344
+
345
+ self.increase_number_of_rebalancing_in_progress()
346
+ for topic_partition in topics_partitions:
347
+ async with self.__get_partition_mutex(
348
+ consumer_fqn=consumer.get_consumer_group(),
349
+ partition=topic_partition.partition,
350
+ ):
328
351
  self.__queue_per_consumer_mapper[consumer].clear(topic_partition)
352
+ self.decrease_number_of_rebalancing_in_progress()
353
+
354
+ def increase_number_of_rebalancing_in_progress(self) -> None:
355
+ self.__number_of_rebalancing_processes_in_progress += 1
356
+
357
+ def decrease_number_of_rebalancing_in_progress(self) -> None:
358
+ self.__number_of_rebalancing_processes_in_progress -= 1
359
+
360
+ def is_rebalancing_in_progress(self) -> bool:
361
+ return self.__number_of_rebalancing_processes_in_progress > 0
329
362
 
330
363
  def request_stop(self) -> None:
331
364
  self.__should_stop.set()
@@ -163,10 +163,7 @@ class AIOKafkaConsumer:
163
163
  self,
164
164
  topics_partitions: set[TopicPartition],
165
165
  ) -> None:
166
- # It could happen that the new partition assigned it was a previous one processed by this consumer, so we need to seek to the last committed offset
167
- self.__consumer.pause(*topics_partitions)
168
- await self.__consumer.seek_to_committed(*topics_partitions)
169
- self.__consumer.resume(*topics_partitions)
166
+ return
170
167
 
171
168
  async def __on_partitions_revoked(
172
169
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: buz
3
- Version: 2.15.7
3
+ Version: 2.15.8rc1
4
4
  Summary: Buz is a set of light, simple and extensible implementations of event, command and query buses.
5
5
  License: MIT
6
6
  Author: Luis Pintado Lozano
@@ -47,7 +47,7 @@ buz/event/exceptions/worker_execution_exception.py,sha256=6mgztvXOCG_9VZ_Jptkk72
47
47
  buz/event/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  buz/event/infrastructure/buz_kafka/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  buz/event/infrastructure/buz_kafka/async_buz_kafka_event_bus.py,sha256=SyLblUVlwWOaNfZzK7vL6Ee4m-85vZVCH0rjOgqVAww,4913
50
- buz/event/infrastructure/buz_kafka/base_buz_aiokafka_async_consumer.py,sha256=FDIz3Usv4ZQrA1_jmfAwv_Nmml3QDHBGt6CyRK0IWiU,18623
50
+ buz/event/infrastructure/buz_kafka/base_buz_aiokafka_async_consumer.py,sha256=13CqXqXk_1tgVJ6SpXpW4nr2SMA7ujpm8l4q3Yhtdsg,20179
51
51
  buz/event/infrastructure/buz_kafka/buz_aiokafka_async_consumer.py,sha256=lLHUnf9DpfAyB0PN7oBjn-Eyyl0zCHsSnrb6QUigruk,6345
52
52
  buz/event/infrastructure/buz_kafka/buz_aiokafka_multi_threaded_consumer.py,sha256=CiuNTns6eifR2JNGhXGNTdWURu-IQVIioe5n_pMSt9s,6288
53
53
  buz/event/infrastructure/buz_kafka/buz_kafka_event_bus.py,sha256=ymRSvcYVgbVCPgHN6rMBVBHQ5heCSwCDl6EffyqGVX8,4601
@@ -164,7 +164,7 @@ buz/kafka/domain/services/kafka_admin_test_client.py,sha256=91l_vFIo1yhJLQQCC_Om
164
164
  buz/kafka/domain/services/kafka_producer.py,sha256=8bLTV328orrPHcARzkc6no4vyJzrArVtCsjmSRXDjos,506
165
165
  buz/kafka/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
166
  buz/kafka/infrastructure/aiokafka/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
- buz/kafka/infrastructure/aiokafka/aiokafka_consumer.py,sha256=xk_812Ah4hxSnAYnpHgbAnwIcvzaCmPY7rBtxo7UcpM,9102
167
+ buz/kafka/infrastructure/aiokafka/aiokafka_consumer.py,sha256=9ORj5couBePn5LtIlTXUlMF2hSOuZ5vmgG0RUbw-BVM,8792
168
168
  buz/kafka/infrastructure/aiokafka/aiokafka_producer.py,sha256=LteHKIHpT6MKplwmwsPYMsd2GWNJCzus65XDHCIdoN8,3823
169
169
  buz/kafka/infrastructure/aiokafka/rebalance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
170
  buz/kafka/infrastructure/aiokafka/rebalance/kafka_callback_rebalancer.py,sha256=3l7NkTrCt3rBktVIS73cTmCOvv6eFguoCbGMYIUfCFc,1774
@@ -250,7 +250,7 @@ buz/serializer/message_to_json_bytes_serializer.py,sha256=RGZJ64t4t4Pz2FCASZZCv-
250
250
  buz/wrapper/__init__.py,sha256=GnRdJFcncn-qp0hzDG9dBHLmTJSbHFVjE_yr-MdW_n4,77
251
251
  buz/wrapper/async_to_sync.py,sha256=OfK-vrVUhuN-LLLvekLdMbQYtH0ue5lfbvuasj6ovMI,698
252
252
  buz/wrapper/event_loop.py,sha256=pfBJ1g-8A2a3YgW8Gf9Fg0kkewoh3-wgTy2KIFDyfHk,266
253
- buz-2.15.7.dist-info/LICENSE,sha256=Jytu2S-2SPEgsB0y6BF-_LUxIWY7402fl0JSh36TLZE,1062
254
- buz-2.15.7.dist-info/METADATA,sha256=-987wNb7KXdP6U8KtilvaxhsAI8ugvrJ5PzVDQfQUzg,1597
255
- buz-2.15.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
256
- buz-2.15.7.dist-info/RECORD,,
253
+ buz-2.15.8rc1.dist-info/LICENSE,sha256=Jytu2S-2SPEgsB0y6BF-_LUxIWY7402fl0JSh36TLZE,1062
254
+ buz-2.15.8rc1.dist-info/METADATA,sha256=EcA5CSIiqruT_bLWz0GS6LaFdRbbbJiG_Stg9zspIug,1600
255
+ buz-2.15.8rc1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
256
+ buz-2.15.8rc1.dist-info/RECORD,,
File without changes