sentry-arroyo 2.20.6__py3-none-any.whl → 2.20.8__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,12 +1,24 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ import time
4
5
  from abc import ABC, abstractmethod, abstractproperty
5
6
  from concurrent.futures import Future
6
- from typing import Callable, Generic, Mapping, Optional, Sequence, Union
7
+ from typing import (
8
+ Callable,
9
+ Generic,
10
+ Mapping,
11
+ Optional,
12
+ Protocol,
13
+ Sequence,
14
+ TypeVar,
15
+ Union,
16
+ )
7
17
 
8
18
  from arroyo.types import BrokerValue, Partition, Topic, TStrategyPayload
9
19
 
20
+ T = TypeVar("T")
21
+
10
22
  logger = logging.getLogger(__name__)
11
23
 
12
24
 
@@ -175,11 +187,72 @@ class Consumer(Generic[TStrategyPayload], ABC):
175
187
  raise NotImplementedError
176
188
 
177
189
 
190
+ class ProducerFuture(Protocol, Generic[T]):
191
+ """
192
+ An abstract interface for a kind of Future. Stdlib futures are too slow to
193
+ construct, so we use these.
194
+ """
195
+
196
+ def done(self) -> bool:
197
+ ...
198
+
199
+ def result(self, timeout: float | None = None) -> T:
200
+ """
201
+ Return result or raise exception. May block, but does not have to.
202
+ """
203
+ ...
204
+
205
+ def set_result(self, result: T) -> None:
206
+ ...
207
+
208
+ def set_exception(self, exception: Exception) -> None:
209
+ ...
210
+
211
+
212
+ class SimpleProducerFuture(Generic[T]):
213
+ """
214
+ A stub for concurrent.futures.Future that does not construct any Condition
215
+ variables, therefore is faster to construct.
216
+ """
217
+
218
+ def __init__(self) -> None:
219
+ self.result_value: T | None = None
220
+ self.result_exception: Exception | None = None
221
+
222
+ def done(self) -> bool:
223
+ return self.result_value is not None or self.result_exception is not None
224
+
225
+ def result(self, timeout: float | None = None) -> T:
226
+ if timeout is not None:
227
+ deadline = time.time() + timeout
228
+ else:
229
+ deadline = None
230
+
231
+ # This implementation is bogus and shouldn't be used in production,
232
+ # only in tests at most. It is only here for the sake of implementing
233
+ # the contract. If you really need result with timeout>0, you should
234
+ # use the stdlib future.
235
+ while deadline is None or time.time() < deadline:
236
+ if self.result_exception is not None:
237
+ raise self.result_exception
238
+ if self.result_value is not None:
239
+ return self.result_value
240
+ time.sleep(0.1)
241
+
242
+ raise TimeoutError()
243
+
244
+ def set_result(self, result: T) -> None:
245
+ self.result_value = result
246
+
247
+ def set_exception(self, exception: Exception) -> None:
248
+ self.result_exception = exception
249
+
250
+
178
251
  class Producer(Generic[TStrategyPayload], ABC):
179
252
  @abstractmethod
180
253
  def produce(
181
254
  self, destination: Union[Topic, Partition], payload: TStrategyPayload
182
- ) -> Future[BrokerValue[TStrategyPayload]]:
255
+ ) -> ProducerFuture[BrokerValue[TStrategyPayload]]:
183
256
  """
184
257
  Produce to a topic or partition.
185
258
  """
@@ -36,7 +36,12 @@ from confluent_kafka import Message as ConfluentMessage
36
36
  from confluent_kafka import Producer as ConfluentProducer
37
37
  from confluent_kafka import TopicPartition as ConfluentTopicPartition
38
38
 
39
- from arroyo.backends.abstract import Consumer, Producer
39
+ from arroyo.backends.abstract import (
40
+ Consumer,
41
+ Producer,
42
+ ProducerFuture,
43
+ SimpleProducerFuture,
44
+ )
40
45
  from arroyo.errors import (
41
46
  ConsumerError,
42
47
  EndOfPartition,
@@ -645,7 +650,9 @@ class KafkaConsumer(Consumer[KafkaPayload]):
645
650
 
646
651
 
647
652
  class KafkaProducer(Producer[KafkaPayload]):
648
- def __init__(self, configuration: Mapping[str, Any]) -> None:
653
+ def __init__(
654
+ self, configuration: Mapping[str, Any], use_simple_futures: bool = False
655
+ ) -> None:
649
656
  self.__configuration = configuration
650
657
 
651
658
  self.__producer = ConfluentProducer(configuration)
@@ -656,6 +663,8 @@ class KafkaProducer(Producer[KafkaPayload]):
656
663
  # ``produce(...).result()`` could result in a deadlock.
657
664
  self.__result = execute(self.__worker, daemon=True)
658
665
 
666
+ self.use_simple_futures = use_simple_futures
667
+
659
668
  def __worker(self) -> None:
660
669
  """
661
670
  Continuously polls the producer to ensure that delivery callbacks are
@@ -670,7 +679,7 @@ class KafkaProducer(Producer[KafkaPayload]):
670
679
 
671
680
  def __delivery_callback(
672
681
  self,
673
- future: Future[BrokerValue[KafkaPayload]],
682
+ future: ProducerFuture[BrokerValue[KafkaPayload]],
674
683
  payload: KafkaPayload,
675
684
  error: KafkaError,
676
685
  message: ConfluentMessage,
@@ -698,7 +707,7 @@ class KafkaProducer(Producer[KafkaPayload]):
698
707
  self,
699
708
  destination: Union[Topic, Partition],
700
709
  payload: KafkaPayload,
701
- ) -> Future[BrokerValue[KafkaPayload]]:
710
+ ) -> ProducerFuture[BrokerValue[KafkaPayload]]:
702
711
  if self.__shutdown_requested.is_set():
703
712
  raise RuntimeError("producer has been closed")
704
713
 
@@ -713,8 +722,13 @@ class KafkaProducer(Producer[KafkaPayload]):
713
722
  else:
714
723
  raise TypeError("invalid destination type")
715
724
 
716
- future: Future[BrokerValue[KafkaPayload]] = Future()
717
- future.set_running_or_notify_cancel()
725
+ future: ProducerFuture[BrokerValue[KafkaPayload]]
726
+ if self.use_simple_futures:
727
+ future = SimpleProducerFuture()
728
+ else:
729
+ future = Future()
730
+ future.set_running_or_notify_cancel()
731
+
718
732
  produce(
719
733
  value=payload.value,
720
734
  key=payload.key,
arroyo/dlq.py CHANGED
@@ -16,7 +16,7 @@ from typing import (
16
16
  Tuple,
17
17
  )
18
18
 
19
- from arroyo.backends.abstract import Producer
19
+ from arroyo.backends.abstract import Producer, ProducerFuture
20
20
  from arroyo.backends.kafka import KafkaPayload
21
21
  from arroyo.types import (
22
22
  FILTERED_PAYLOAD,
@@ -186,7 +186,7 @@ class DlqProducer(ABC, Generic[TStrategyPayload]):
186
186
  @abstractmethod
187
187
  def produce(
188
188
  self, value: BrokerValue[TStrategyPayload], reason: Optional[str] = None
189
- ) -> Future[BrokerValue[TStrategyPayload]]:
189
+ ) -> ProducerFuture[BrokerValue[TStrategyPayload]]:
190
190
  """
191
191
  Produce a message to DLQ.
192
192
  """
@@ -212,7 +212,7 @@ class NoopDlqProducer(DlqProducer[Any]):
212
212
  self,
213
213
  value: BrokerValue[KafkaPayload],
214
214
  reason: Optional[str] = None,
215
- ) -> Future[BrokerValue[KafkaPayload]]:
215
+ ) -> ProducerFuture[BrokerValue[KafkaPayload]]:
216
216
  future: Future[BrokerValue[KafkaPayload]] = Future()
217
217
  future.set_running_or_notify_cancel()
218
218
  future.set_result(value)
@@ -242,7 +242,7 @@ class KafkaDlqProducer(DlqProducer[KafkaPayload]):
242
242
  self,
243
243
  value: BrokerValue[KafkaPayload],
244
244
  reason: Optional[str] = None,
245
- ) -> Future[BrokerValue[KafkaPayload]]:
245
+ ) -> ProducerFuture[BrokerValue[KafkaPayload]]:
246
246
  value.payload.headers.append(
247
247
  ("original_partition", f"{value.partition.index}".encode("utf-8"))
248
248
  )
@@ -381,7 +381,7 @@ class DlqPolicyWrapper(Generic[TStrategyPayload]):
381
381
  Deque[
382
382
  Tuple[
383
383
  BrokerValue[TStrategyPayload],
384
- Future[BrokerValue[TStrategyPayload]],
384
+ ProducerFuture[BrokerValue[TStrategyPayload]],
385
385
  ]
386
386
  ],
387
387
  ] = defaultdict(deque)
@@ -144,9 +144,9 @@ class StreamProcessor(Generic[TStrategyPayload]):
144
144
  self.__processor_factory = processor_factory
145
145
  self.__metrics_buffer = MetricsBuffer()
146
146
 
147
- self.__processing_strategy: Optional[ProcessingStrategy[TStrategyPayload]] = (
148
- None
149
- )
147
+ self.__processing_strategy: Optional[
148
+ ProcessingStrategy[TStrategyPayload]
149
+ ] = None
150
150
 
151
151
  self.__message: Optional[BrokerValue[TStrategyPayload]] = None
152
152
 
@@ -381,8 +381,12 @@ class StreamProcessor(Generic[TStrategyPayload]):
381
381
  try:
382
382
  self.__dlq_policy.produce(invalid_message, exc.reason)
383
383
  except Exception:
384
- logger.exception(f"Failed to produce message (partition: {exc.partition} offset: {exc.offset}) to DLQ topic, dropping")
385
- self.__metrics_buffer.incr_counter("arroyo.consumer.dlq.dropped_messages", 1)
384
+ logger.exception(
385
+ f"Failed to produce message (partition: {exc.partition} offset: {exc.offset}) to DLQ topic, dropping"
386
+ )
387
+ self.__metrics_buffer.incr_counter(
388
+ "arroyo.consumer.dlq.dropped_messages", 1
389
+ )
386
390
 
387
391
  self.__metrics_buffer.incr_timing(
388
392
  "arroyo.consumer.dlq.time", time.time() - start_dlq
@@ -1,10 +1,9 @@
1
1
  import logging
2
2
  import time
3
3
  from collections import deque
4
- from concurrent.futures import Future
5
4
  from typing import Deque, Optional, Tuple, Union
6
5
 
7
- from arroyo.backends.abstract import Producer
6
+ from arroyo.backends.abstract import Producer, ProducerFuture
8
7
  from arroyo.processing.strategies.abstract import MessageRejected, ProcessingStrategy
9
8
  from arroyo.types import (
10
9
  BrokerValue,
@@ -52,7 +51,7 @@ class Produce(ProcessingStrategy[Union[FilteredPayload, TStrategyPayload]]):
52
51
  self.__queue: Deque[
53
52
  Tuple[
54
53
  Message[Union[FilteredPayload, TStrategyPayload]],
55
- Optional[Future[BrokerValue[TStrategyPayload]]],
54
+ Optional[ProducerFuture[BrokerValue[TStrategyPayload]]],
56
55
  ]
57
56
  ] = deque()
58
57
 
@@ -92,7 +91,7 @@ class Produce(ProcessingStrategy[Union[FilteredPayload, TStrategyPayload]]):
92
91
  if len(self.__queue) >= self.__max_buffer_size:
93
92
  raise MessageRejected
94
93
 
95
- future: Optional[Future[BrokerValue[TStrategyPayload]]] = None
94
+ future: Optional[ProducerFuture[BrokerValue[TStrategyPayload]]] = None
96
95
 
97
96
  if not isinstance(message.payload, FilteredPayload):
98
97
  try:
@@ -581,7 +581,7 @@ class RunTaskWithMultiprocessing(
581
581
  self.__metrics.increment("sigchld.detected")
582
582
  raise ChildProcessTerminated(signum)
583
583
 
584
- signal.signal(signal.SIGCHLD, handle_sigchld)
584
+ self.original_sigchld = signal.signal(signal.SIGCHLD, handle_sigchld)
585
585
 
586
586
  def __submit_batch(self, input_block_too_small: bool) -> None:
587
587
  assert self.__batch_builder is not None
@@ -839,14 +839,19 @@ class RunTaskWithMultiprocessing(
839
839
  # compression.)
840
840
  self.__batch_builder.append(message)
841
841
 
842
- def close(self) -> None:
842
+ def _do_close(self) -> None:
843
843
  self.__closed = True
844
844
 
845
+ signal.signal(signal.SIGCHLD, self.original_sigchld)
846
+
847
+ def close(self) -> None:
848
+ self._do_close()
849
+
845
850
  if self.__batch_builder is not None and len(self.__batch_builder) > 0:
846
851
  self.__submit_batch(False)
847
852
 
848
853
  def terminate(self) -> None:
849
- self.__closed = True
854
+ self._do_close()
850
855
 
851
856
  logger.info("Terminating %r...", self.__pool)
852
857
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry-arroyo
3
- Version: 2.20.6
3
+ Version: 2.20.8
4
4
  Summary: Arroyo is a Python library for working with streaming data.
5
5
  Home-page: https://github.com/getsentry/arroyo
6
6
  Author: Sentry
@@ -1,22 +1,22 @@
1
1
  arroyo/__init__.py,sha256=fcpHZd2P3MxWl6PJJ8n__fM_NRIfiUE8tKN-orv6lb0,187
2
2
  arroyo/commit.py,sha256=oFihWUW8fLsjomWh0o085qIHe9vwVNgoOJC6JQdFM7M,2235
3
- arroyo/dlq.py,sha256=kWDQ-6NwzQEFBzsAWfahRXL1_FvJDl-nDaNQd-xGQOM,16790
3
+ arroyo/dlq.py,sha256=QwWyYQElNObu5SugLWwVp_ADs_BDtvHsaPPb6h15KPQ,16838
4
4
  arroyo/errors.py,sha256=IbtoIbz_m5QrxNRBLOxiy-hOfJQTEwNPCyq6yqedJYk,1059
5
5
  arroyo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  arroyo/types.py,sha256=sLY0x030np4UmbaW5C1KH1se7Z2pjQiPvAe5x2sXf7A,5684
7
7
  arroyo/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- arroyo/backends/abstract.py,sha256=PicUWWsgH-41XpHDcuq86P4PpPx7GWgLWdwnw4B0obo,7582
8
+ arroyo/backends/abstract.py,sha256=qnyuAcbxTIImEXTDA9T1V0Vh4GH_CImnXezK0E3tH5E,9539
9
9
  arroyo/backends/kafka/__init__.py,sha256=TZ0omd3LFXcZUaN_soFTuTgbjNEQYF1mF_i6_KIfCNo,306
10
10
  arroyo/backends/kafka/commit.py,sha256=LPsjvX5PPXR62DT6sa5GuSF78qk9F_L--Fz4kw7-m-s,3060
11
11
  arroyo/backends/kafka/configuration.py,sha256=D9zre9H2xagUsk7qBA-bm38V3_4Mg_X5hpKsKx2BkM8,3048
12
- arroyo/backends/kafka/consumer.py,sha256=fo5a0tCq0XFvMA9drVCUCBMAXuA_x5KlpBU4G2LsNIo,27728
12
+ arroyo/backends/kafka/consumer.py,sha256=VFjMz4T7JDWIh8B1GMDzpWw7IMtakvsB3O3I64wj0Rg,28031
13
13
  arroyo/backends/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  arroyo/backends/local/backend.py,sha256=7odjCnzoGgdo8JHLgG1ntaXa-ZR9GteGkquiA2WAWmM,13880
15
15
  arroyo/backends/local/storages/__init__.py,sha256=AGYujdAAcn3osoj9jq84IzTywYbkIDv9wRg2rLhLXeg,104
16
16
  arroyo/backends/local/storages/abstract.py,sha256=1qVQp6roxHkK6XT2aklZyZk1qq7RzcPN6Db_CA5--kg,2901
17
17
  arroyo/backends/local/storages/memory.py,sha256=AoKDsVZzBXkOJyWArKWp3vfGfU9xLlKFXE9gsJiMIzQ,2613
18
18
  arroyo/processing/__init__.py,sha256=vZVg0wJvJfoVzlzGvnL59bT6YNIRJNQ5t7oU045Qbk4,87
19
- arroyo/processing/processor.py,sha256=WqWKOsMZYqzrk89Cn-gkPSIbeafHm8lTXsk46kXg7H4,20352
19
+ arroyo/processing/processor.py,sha256=mfPyqG0ZvBiucN_c2jfaYP8YjygXV2HXfHWfx4TpRi8,20426
20
20
  arroyo/processing/strategies/__init__.py,sha256=EU_JMb54eOxMxaC5mIFpI-sAF-X2ZScbE8czBZ7bQkY,1106
21
21
  arroyo/processing/strategies/abstract.py,sha256=nu7juEz_aQmQIH35Z8u--FBuLjkK8_LQ1hIG2xpw9AA,4808
22
22
  arroyo/processing/strategies/batching.py,sha256=s89xC6lQpBseEaApu1iNTipXGKeO95OMwinj2VBKn9s,4778
@@ -26,11 +26,11 @@ arroyo/processing/strategies/filter.py,sha256=dzx9BaIVigxFGfsrNYAWJYTDCanIp3RiV9
26
26
  arroyo/processing/strategies/guard.py,sha256=W2Nsy8LW6RWYPh-_ReljR8_lkPgipOG8LhtDR-DDlto,4878
27
27
  arroyo/processing/strategies/healthcheck.py,sha256=fEVB516nZVZWvZLzi4_ImaE6F7QQQJIymW6HgiUYUSA,1775
28
28
  arroyo/processing/strategies/noop.py,sha256=BtWkC93QpZCKAB4qTsXLaqrYsllE1Olp6mY2YeuK9ag,726
29
- arroyo/processing/strategies/produce.py,sha256=v1mJv5rbyXal7ESIfsihbTGW-vZ0_niJnBgdqcA-zHQ,4619
29
+ arroyo/processing/strategies/produce.py,sha256=LUsg2bsVsguc2fTbueTbqLeg3mbnk_FOf_98GvPnI10,4613
30
30
  arroyo/processing/strategies/reduce.py,sha256=xv9bYisgHHyS8fVD1PdGi4TJsaK-4RAhMEDh4WHhYfI,3933
31
31
  arroyo/processing/strategies/run_task.py,sha256=MGe2UcIWN7FkPc9plKzRVUNbZ7Sk0jWjw1z2vVOFI_I,2160
32
32
  arroyo/processing/strategies/run_task_in_threads.py,sha256=f1sb2AG-BLz11X78jfhtERIkdFogrV8vtdT3pyJdkx0,6144
33
- arroyo/processing/strategies/run_task_with_multiprocessing.py,sha256=jNb_e3hcXDlnLE0XCgVjbLHXrob8V53aPGeMWtu4ToI,34417
33
+ arroyo/processing/strategies/run_task_with_multiprocessing.py,sha256=jOL6SKLyrTuCsOkFDl5eOLQzr79bo_yZiuE1d9rhnfA,34558
34
34
  arroyo/processing/strategies/unfold.py,sha256=bi47pwmKGT0Irsx0HdB7Bhc5hb-yYqLF_xcv3g1ewTk,4231
35
35
  arroyo/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  arroyo/utils/clock.py,sha256=r2EMO4nL5qIb1xnAd1sTAk2yK1UltyUi04lk5BqWKIc,944
@@ -46,14 +46,14 @@ examples/transform_and_produce/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
46
46
  examples/transform_and_produce/batched.py,sha256=st2R6qTneAtV0JFbKP30Ti3sJDYj8Jkbmta9JckKdZU,2636
47
47
  examples/transform_and_produce/script.py,sha256=8kSMIjQNqGYEVyE0PvrfJh-a_UYCrJSstTp_De7kyyg,2306
48
48
  examples/transform_and_produce/simple.py,sha256=H7xqxItjl4tx34wVW5dy6mB9G39QucAtxkJSBzVmjgA,1637
49
- sentry_arroyo-2.20.6.dist-info/licenses/LICENSE,sha256=0Ng3MFdEcnz0sVD1XvGBBzbavvNp_7OAM5yVObB46jU,10829
49
+ sentry_arroyo-2.20.8.dist-info/licenses/LICENSE,sha256=0Ng3MFdEcnz0sVD1XvGBBzbavvNp_7OAM5yVObB46jU,10829
50
50
  tests/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  tests/backends/mixins.py,sha256=sfNyE0VTeiD3GHOnBYl-9urvPuURI2G1BWke0cz7Dvc,20445
52
52
  tests/backends/test_commit.py,sha256=iTHfK1qsBxim0XwxgMvNNSMqDUMEHoYkYBDcgxGBFbs,831
53
- tests/backends/test_kafka.py,sha256=mNwisb5PQPlBs5TIZtk6hL_eSbwAdwZ0RDD05WxDYps,12188
53
+ tests/backends/test_kafka.py,sha256=XGljy72Juesc1qbVs0D02OJitFnry72fRWQdbTqmBp4,12371
54
54
  tests/backends/test_local.py,sha256=Mfd4DFuWVSVtl1GomQ6TIoWuJNcAliKqKU0BShPlEMY,3363
55
55
  tests/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- tests/processing/test_processor.py,sha256=3uBfMN1tbm37VtwUx7wtCz42fN5TZRUya1ovwL0mC40,20782
56
+ tests/processing/test_processor.py,sha256=PDCrmhWAt_wZKwYlBzDuEGsd8PnjKM-p4ySaPvVd11k,20781
57
57
  tests/processing/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  tests/processing/strategies/test_all.py,sha256=ahAF-nbdmqVkYGNCg0OFCD6fzNTA-XxYrW8NQHajCDU,10167
59
59
  tests/processing/strategies/test_batching.py,sha256=nyyX0y6qYHX7jT4gCgsUjT5RzBMDrBp790SCmOizQ0Q,11787
@@ -66,13 +66,13 @@ tests/processing/strategies/test_produce.py,sha256=UQ03quIAvfnsg8Og7US6D4ERs-J8n
66
66
  tests/processing/strategies/test_reduce.py,sha256=crPFtGp7cyD8QOsmfVsyYh8KLOTzb8ryI7XtYg0vQSQ,1101
67
67
  tests/processing/strategies/test_run_task.py,sha256=bWIy4U6QyOBtqdiJdGLMAadlEME-W2aE_ZzDbU_BsGo,2805
68
68
  tests/processing/strategies/test_run_task_in_threads.py,sha256=5nwzF1iV6MTK1xETzWvMEOwAcZWrMOQaIPSWbiAjKFo,1457
69
- tests/processing/strategies/test_run_task_with_multiprocessing.py,sha256=iy4etaU9WLa8AfMIFUXRnS70Dj7jlpotIX7s-BhTWH0,21914
69
+ tests/processing/strategies/test_run_task_with_multiprocessing.py,sha256=eyv3O5XhVSlJZXli_WG3v_ULHJ4YXrvW7vb4X5EeZVg,22111
70
70
  tests/processing/strategies/test_unfold.py,sha256=mbC4XhT6GkJRuC7vPR0h7jqwt4cu20q7Z114EJ6J9mQ,2009
71
71
  tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  tests/utils/test_concurrent.py,sha256=Gwdzym2UZ1HO3rhOSGmzxImWcLFygY8P7MXHT3Q0xTE,455
73
73
  tests/utils/test_metrics.py,sha256=bI0EtGgPokMQyEqX58i0-8zvLfxRP2nWaWr2wLMaJ_o,917
74
74
  tests/utils/test_retries.py,sha256=AxJLkXWeL9AjHv_p1n0pe8CXXJp24ZQIuYBHfNcmiz4,3075
75
- sentry_arroyo-2.20.6.dist-info/METADATA,sha256=d9kyjf-g8Wu1M0MJgI-6-OKrIqzQjGcDZDnuhC1hCas,2200
76
- sentry_arroyo-2.20.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
77
- sentry_arroyo-2.20.6.dist-info/top_level.txt,sha256=DVdMZKysL_iIxm5aY0sYgZtP5ZXMg9YBaBmGQHVmDXA,22
78
- sentry_arroyo-2.20.6.dist-info/RECORD,,
75
+ sentry_arroyo-2.20.8.dist-info/METADATA,sha256=Tfi9HVQkH631_WJQGu-PjVUNjmljc9LLuuN_2rBFT8Q,2200
76
+ sentry_arroyo-2.20.8.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
77
+ sentry_arroyo-2.20.8.dist-info/top_level.txt,sha256=DVdMZKysL_iIxm5aY0sYgZtP5ZXMg9YBaBmGQHVmDXA,22
78
+ sentry_arroyo-2.20.8.dist-info/RECORD,,
@@ -131,8 +131,8 @@ class TestKafkaStreams(StreamsTestMixin[KafkaPayload]):
131
131
 
132
132
  return KafkaConsumer(configuration)
133
133
 
134
- def get_producer(self) -> KafkaProducer:
135
- return KafkaProducer(self.configuration)
134
+ def get_producer(self, use_simple_futures: bool = False) -> KafkaProducer:
135
+ return KafkaProducer(self.configuration, use_simple_futures=use_simple_futures)
136
136
 
137
137
  def get_payloads(self) -> Iterator[KafkaPayload]:
138
138
  for i in itertools.count():
@@ -150,9 +150,10 @@ class TestKafkaStreams(StreamsTestMixin[KafkaPayload]):
150
150
  assert isinstance(value, BrokerValue)
151
151
  assert value.payload.value == b"0"
152
152
 
153
- def test_auto_offset_reset_latest(self) -> None:
153
+ @pytest.mark.parametrize("use_simple_futures", [True, False])
154
+ def test_auto_offset_reset_latest(self, use_simple_futures: bool) -> None:
154
155
  with self.get_topic() as topic:
155
- with closing(self.get_producer()) as producer:
156
+ with closing(self.get_producer(use_simple_futures)) as producer:
156
157
  producer.produce(topic, next(self.get_payloads())).result(5.0)
157
158
 
158
159
  with closing(self.get_consumer(auto_offset_reset="latest")) as consumer:
@@ -1,8 +1,9 @@
1
1
  import multiprocessing
2
+ import signal
2
3
  import time
3
4
  from datetime import datetime
4
5
  from multiprocessing.managers import SharedMemoryManager
5
- from typing import Any
6
+ from typing import Any, Generator
6
7
  from unittest.mock import Mock, call
7
8
 
8
9
  import pytest
@@ -25,6 +26,12 @@ from tests.metrics import TestingMetricsBackend
25
26
  from tests.metrics import Timing as TimingCall
26
27
 
27
28
 
29
+ @pytest.fixture(autouse=True)
30
+ def does_not_leak_sigchild_handler() -> Generator[None, None, None]:
31
+ yield
32
+ assert isinstance(signal.getsignal(signal.SIGCHLD), int)
33
+
34
+
28
35
  def test_message_batch() -> None:
29
36
  partition = Partition(Topic("test"), 0)
30
37
 
@@ -583,7 +583,6 @@ def test_dlq() -> None:
583
583
  assert dlq_policy.producer.produce.call_count == 1
584
584
 
585
585
 
586
-
587
586
  def test_healthcheck(tmpdir: py.path.local) -> None:
588
587
  """
589
588
  Test healthcheck strategy e2e with StreamProcessor, to ensure the