sentry-arroyo 2.20.5__tar.gz → 2.20.7__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.
- {sentry_arroyo-2.20.5/sentry_arroyo.egg-info → sentry_arroyo-2.20.7}/PKG-INFO +1 -1
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/abstract.py +75 -2
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/kafka/consumer.py +20 -6
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/dlq.py +5 -5
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/processor.py +9 -5
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/produce.py +3 -4
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/unfold.py +1 -1
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7/sentry_arroyo.egg-info}/PKG-INFO +1 -1
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/setup.py +1 -1
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/backends/test_kafka.py +5 -4
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_unfold.py +7 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/test_processor.py +0 -1
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/LICENSE +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/MANIFEST.in +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/README.md +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/kafka/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/kafka/commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/kafka/configuration.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/local/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/local/backend.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/local/storages/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/local/storages/abstract.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/backends/local/storages/memory.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/errors.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/abstract.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/batching.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/buffer.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/filter.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/guard.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/healthcheck.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/noop.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/reduce.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/run_task.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/run_task_in_threads.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/run_task_with_multiprocessing.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/py.typed +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/types.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/clock.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/codecs.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/concurrent.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/logging.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/metricDefs.json +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/metric_defs.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/metrics.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/profiler.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/utils/retries.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/examples/transform_and_produce/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/examples/transform_and_produce/batched.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/examples/transform_and_produce/script.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/examples/transform_and_produce/simple.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/requirements.txt +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/sentry_arroyo.egg-info/SOURCES.txt +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/sentry_arroyo.egg-info/dependency_links.txt +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/sentry_arroyo.egg-info/not-zip-safe +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/sentry_arroyo.egg-info/requires.txt +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/sentry_arroyo.egg-info/top_level.txt +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/setup.cfg +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/backends/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/backends/mixins.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/backends/test_commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/backends/test_local.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_all.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_batching.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_buffer.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_filter.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_guard.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_noop.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_produce.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_reduce.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_run_task.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_run_task_in_threads.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/processing/strategies/test_run_task_with_multiprocessing.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/test_commit.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/test_dlq.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/test_kip848_e2e.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/test_types.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/utils/__init__.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/utils/test_concurrent.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/utils/test_metrics.py +0 -0
- {sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/tests/utils/test_retries.py +0 -0
|
@@ -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
|
|
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
|
-
) ->
|
|
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
|
|
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__(
|
|
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:
|
|
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
|
-
) ->
|
|
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:
|
|
717
|
-
|
|
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,
|
|
@@ -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
|
-
) ->
|
|
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
|
-
) ->
|
|
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
|
-
) ->
|
|
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
|
-
|
|
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[
|
|
148
|
-
|
|
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(
|
|
385
|
-
|
|
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[
|
|
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[
|
|
94
|
+
future: Optional[ProducerFuture[BrokerValue[TStrategyPayload]]] = None
|
|
96
95
|
|
|
97
96
|
if not isinstance(message.payload, FilteredPayload):
|
|
98
97
|
try:
|
|
@@ -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
|
-
|
|
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:
|
|
@@ -49,6 +49,13 @@ def test_message_rejected() -> None:
|
|
|
49
49
|
call(Message(Value(0, {}, NOW))),
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
# poll again, to show that it does not block (regression)
|
|
53
|
+
strategy.poll()
|
|
54
|
+
assert next_step.submit.call_args_list == [
|
|
55
|
+
call(Message(Value(0, {}, NOW))),
|
|
56
|
+
call(Message(Value(0, {}, NOW))),
|
|
57
|
+
]
|
|
58
|
+
|
|
52
59
|
# clear the side effect, both messages should be submitted now
|
|
53
60
|
next_step.submit.reset_mock(side_effect=True)
|
|
54
61
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sentry_arroyo-2.20.5 → sentry_arroyo-2.20.7}/arroyo/processing/strategies/run_task_in_threads.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|