sentry-arroyo 2.29.7__tar.gz → 2.31.0__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.
Files changed (92) hide show
  1. {sentry_arroyo-2.29.7/sentry_arroyo.egg-info → sentry_arroyo-2.31.0}/PKG-INFO +1 -1
  2. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/kafka/__init__.py +2 -1
  3. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/kafka/consumer.py +52 -2
  4. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/processor.py +7 -1
  5. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0/sentry_arroyo.egg-info}/PKG-INFO +1 -1
  6. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/sentry_arroyo.egg-info/SOURCES.txt +1 -0
  7. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/setup.py +1 -1
  8. sentry_arroyo-2.31.0/tests/backends/test_confluent_producer.py +64 -0
  9. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/LICENSE +0 -0
  10. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/MANIFEST.in +0 -0
  11. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/README.md +0 -0
  12. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/__init__.py +0 -0
  13. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/__init__.py +0 -0
  14. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/abstract.py +0 -0
  15. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/kafka/commit.py +0 -0
  16. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/kafka/configuration.py +0 -0
  17. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/local/__init__.py +0 -0
  18. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/local/backend.py +0 -0
  19. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/local/storages/__init__.py +0 -0
  20. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/local/storages/abstract.py +0 -0
  21. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/backends/local/storages/memory.py +0 -0
  22. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/commit.py +0 -0
  23. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/dlq.py +0 -0
  24. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/errors.py +0 -0
  25. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/__init__.py +0 -0
  26. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/__init__.py +0 -0
  27. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/abstract.py +0 -0
  28. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/batching.py +0 -0
  29. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/buffer.py +0 -0
  30. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/commit.py +0 -0
  31. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/filter.py +0 -0
  32. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/guard.py +0 -0
  33. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/healthcheck.py +0 -0
  34. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/noop.py +0 -0
  35. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/produce.py +0 -0
  36. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/reduce.py +0 -0
  37. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/run_task.py +0 -0
  38. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/run_task_in_threads.py +0 -0
  39. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/run_task_with_multiprocessing.py +0 -0
  40. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/processing/strategies/unfold.py +0 -0
  41. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/py.typed +0 -0
  42. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/types.py +0 -0
  43. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/__init__.py +0 -0
  44. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/clock.py +0 -0
  45. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/codecs.py +0 -0
  46. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/concurrent.py +0 -0
  47. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/logging.py +0 -0
  48. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/metricDefs.json +0 -0
  49. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/metric_defs.py +0 -0
  50. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/metrics.py +0 -0
  51. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/profiler.py +0 -0
  52. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/arroyo/utils/retries.py +0 -0
  53. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/examples/transform_and_produce/__init__.py +0 -0
  54. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/examples/transform_and_produce/batched.py +0 -0
  55. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/examples/transform_and_produce/script.py +0 -0
  56. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/examples/transform_and_produce/simple.py +0 -0
  57. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/requirements.txt +0 -0
  58. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/sentry_arroyo.egg-info/dependency_links.txt +0 -0
  59. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/sentry_arroyo.egg-info/not-zip-safe +0 -0
  60. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/sentry_arroyo.egg-info/requires.txt +0 -0
  61. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/sentry_arroyo.egg-info/top_level.txt +0 -0
  62. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/setup.cfg +0 -0
  63. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/__init__.py +0 -0
  64. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/mixins.py +0 -0
  65. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/test_commit.py +0 -0
  66. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/test_kafka.py +0 -0
  67. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/test_kafka_producer.py +0 -0
  68. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/backends/test_local.py +0 -0
  69. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/__init__.py +0 -0
  70. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/__init__.py +0 -0
  71. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_all.py +0 -0
  72. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_batching.py +0 -0
  73. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_buffer.py +0 -0
  74. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_commit.py +0 -0
  75. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_filter.py +0 -0
  76. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_guard.py +0 -0
  77. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_noop.py +0 -0
  78. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_produce.py +0 -0
  79. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_reduce.py +0 -0
  80. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_run_task.py +0 -0
  81. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_run_task_in_threads.py +0 -0
  82. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_run_task_with_multiprocessing.py +0 -0
  83. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/strategies/test_unfold.py +0 -0
  84. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/processing/test_processor.py +0 -0
  85. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/test_commit.py +0 -0
  86. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/test_dlq.py +0 -0
  87. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/test_kip848_e2e.py +0 -0
  88. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/test_types.py +0 -0
  89. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/utils/__init__.py +0 -0
  90. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/utils/test_concurrent.py +0 -0
  91. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/utils/test_metrics.py +0 -0
  92. {sentry_arroyo-2.29.7 → sentry_arroyo-2.31.0}/tests/utils/test_retries.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry-arroyo
3
- Version: 2.29.7
3
+ Version: 2.31.0
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
@@ -3,12 +3,13 @@ from .configuration import (
3
3
  build_kafka_consumer_configuration,
4
4
  build_kafka_producer_configuration,
5
5
  )
6
- from .consumer import KafkaConsumer, KafkaPayload, KafkaProducer
6
+ from .consumer import ConfluentProducer, KafkaConsumer, KafkaPayload, KafkaProducer
7
7
 
8
8
  __all__ = [
9
9
  "build_kafka_configuration",
10
10
  "build_kafka_consumer_configuration",
11
11
  "build_kafka_producer_configuration",
12
+ "ConfluentProducer",
12
13
  "KafkaConsumer",
13
14
  "KafkaPayload",
14
15
  "KafkaProducer",
@@ -33,7 +33,7 @@ from confluent_kafka import (
33
33
  from confluent_kafka import Consumer as ConfluentConsumer
34
34
  from confluent_kafka import KafkaError, KafkaException
35
35
  from confluent_kafka import Message as ConfluentMessage
36
- from confluent_kafka import Producer as ConfluentProducer
36
+ from confluent_kafka import Producer as ConfluentKafkaProducer
37
37
  from confluent_kafka import TopicPartition as ConfluentTopicPartition
38
38
 
39
39
  from arroyo.backends.abstract import (
@@ -50,6 +50,7 @@ from arroyo.errors import (
50
50
  )
51
51
  from arroyo.types import BrokerValue, Partition, Topic
52
52
  from arroyo.utils.concurrent import execute
53
+ from arroyo.utils.metrics import get_metrics
53
54
  from arroyo.utils.retries import BasicRetryPolicy
54
55
 
55
56
  logger = logging.getLogger(__name__)
@@ -657,7 +658,7 @@ class KafkaProducer(Producer[KafkaPayload]):
657
658
  self, configuration: Mapping[str, Any], use_simple_futures: bool = False
658
659
  ) -> None:
659
660
  self.__configuration = configuration
660
- self.__producer = ConfluentProducer(configuration)
661
+ self.__producer = ConfluentKafkaProducer(configuration)
661
662
  self.__shutdown_requested = Event()
662
663
 
663
664
  # The worker must execute in a separate thread to ensure that callbacks
@@ -742,3 +743,52 @@ class KafkaProducer(Producer[KafkaPayload]):
742
743
  def close(self) -> Future[None]:
743
744
  self.__shutdown_requested.set()
744
745
  return self.__result
746
+
747
+
748
+ # Type alias for the delivery callback function
749
+ DeliveryCallback = Callable[[Optional[KafkaError], ConfluentMessage], None]
750
+
751
+
752
+ class ConfluentProducer(ConfluentKafkaProducer): # type: ignore[misc]
753
+ """
754
+ A thin wrapper for confluent_kafka.Producer that adds metrics reporting.
755
+ """
756
+
757
+ def __init__(self, configuration: Mapping[str, Any]) -> None:
758
+ super().__init__(configuration)
759
+ self.__metrics = get_metrics()
760
+
761
+ def __metrics_delivery_callback(
762
+ self,
763
+ error: Optional[KafkaError],
764
+ _message: ConfluentMessage,
765
+ ) -> None:
766
+ if error is not None:
767
+ status = "error"
768
+ else:
769
+ status = "success"
770
+
771
+ self.__metrics.increment(
772
+ "arroyo.producer.produce_status",
773
+ 1,
774
+ tags={"status": status},
775
+ )
776
+
777
+ def __delivery_callback(
778
+ self,
779
+ user_callback: Optional[DeliveryCallback],
780
+ ) -> DeliveryCallback:
781
+ def wrapped(error: Optional[KafkaError], message: ConfluentMessage) -> None:
782
+ self.__metrics_delivery_callback(error, message)
783
+ if user_callback is not None:
784
+ user_callback(error, message)
785
+
786
+ return wrapped
787
+
788
+ def produce(self, *args: Any, **kwargs: Any) -> None:
789
+ # callback and on_delivery are aliases, callback takes precedence over on_delivery
790
+ callback = kwargs.pop("callback", None)
791
+ on_delivery = kwargs.pop("on_delivery", None)
792
+ user_callback = callback or on_delivery
793
+ wrapped_callback = self.__delivery_callback(user_callback)
794
+ super().produce(*args, on_delivery=wrapped_callback, **kwargs)
@@ -35,6 +35,7 @@ logger = logging.getLogger(__name__)
35
35
 
36
36
  METRICS_FREQUENCY_SEC = 1.0 # In seconds
37
37
  BACKPRESSURE_THRESHOLD = 5.0 # In seconds
38
+ DEFAULT_JOIN_TIMEOUT = 25.0 # In seconds
38
39
 
39
40
  F = TypeVar("F", bound=Callable[[Any], Any])
40
41
 
@@ -157,7 +158,12 @@ class StreamProcessor(Generic[TStrategyPayload]):
157
158
  self.__is_paused = False
158
159
 
159
160
  self.__commit_policy_state = commit_policy.get_state_machine()
160
- self.__join_timeout = join_timeout
161
+
162
+ # Default join_timeout to DEFAULT_JOIN_TIMEOUT if not provided
163
+ self.__join_timeout = (
164
+ join_timeout if join_timeout is not None else DEFAULT_JOIN_TIMEOUT
165
+ )
166
+
161
167
  self.__shutdown_requested = False
162
168
  self.__shutdown_strategy_before_consumer = shutdown_strategy_before_consumer
163
169
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry-arroyo
3
- Version: 2.29.7
3
+ Version: 2.31.0
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
@@ -64,6 +64,7 @@ tests/test_types.py
64
64
  tests/backends/__init__.py
65
65
  tests/backends/mixins.py
66
66
  tests/backends/test_commit.py
67
+ tests/backends/test_confluent_producer.py
67
68
  tests/backends/test_kafka.py
68
69
  tests/backends/test_kafka_producer.py
69
70
  tests/backends/test_local.py
@@ -10,7 +10,7 @@ def get_requirements() -> Sequence[str]:
10
10
 
11
11
  setup(
12
12
  name="sentry-arroyo",
13
- version="2.29.7",
13
+ version="2.31.0",
14
14
  author="Sentry",
15
15
  author_email="oss@sentry.io",
16
16
  license="Apache-2.0",
@@ -0,0 +1,64 @@
1
+ from typing import Optional
2
+ from unittest import mock
3
+
4
+ from confluent_kafka import KafkaError
5
+ from confluent_kafka import Message as ConfluentMessage
6
+ from confluent_kafka import Producer as ConfluentKafkaProducer
7
+
8
+ from arroyo.backends.kafka.consumer import ConfluentProducer
9
+ from tests.metrics import Increment, TestingMetricsBackend
10
+
11
+
12
+ class TestConfluentProducer:
13
+ """
14
+ Tests for ConfluentProducer wrapper around confluent_kafka.Producer.
15
+ """
16
+
17
+ def test_init(self) -> None:
18
+ """Test that ConfluentProducer can be instantiated"""
19
+ config = {"bootstrap.servers": "fake:9092"}
20
+ producer = ConfluentProducer(config)
21
+
22
+ assert isinstance(producer, ConfluentProducer)
23
+ assert isinstance(producer, ConfluentKafkaProducer)
24
+
25
+ def test_metrics_callback_records_success(self) -> None:
26
+ """Test that the metrics callback records success metric"""
27
+ producer = ConfluentProducer({"bootstrap.servers": "fake:9092"})
28
+ mock_message = mock.Mock(spec=ConfluentMessage)
29
+ producer._ConfluentProducer__metrics_delivery_callback(None, mock_message)
30
+ assert (
31
+ Increment("arroyo.producer.produce_status", 1, {"status": "success"})
32
+ in TestingMetricsBackend.calls
33
+ )
34
+
35
+ def test_metrics_callback_records_error(self) -> None:
36
+ """Test that the metrics callback records error metric"""
37
+ producer = ConfluentProducer({"bootstrap.servers": "fake:9092"})
38
+ mock_error = mock.Mock(spec=KafkaError)
39
+ mock_message = mock.Mock(spec=ConfluentMessage)
40
+ producer._ConfluentProducer__metrics_delivery_callback(mock_error, mock_message)
41
+ assert (
42
+ Increment("arroyo.producer.produce_status", 1, {"status": "error"})
43
+ in TestingMetricsBackend.calls
44
+ )
45
+
46
+ def test_delivery_callback_wraps_user_callback(self) -> None:
47
+ """Test that the delivery callback wrapper calls both metrics and user callbacks"""
48
+ producer = ConfluentProducer({"bootstrap.servers": "fake:9092"})
49
+ user_callback_invoked = []
50
+
51
+ def user_callback(
52
+ error: Optional[KafkaError], message: ConfluentMessage
53
+ ) -> None:
54
+ user_callback_invoked.append((error, message))
55
+
56
+ wrapped = producer._ConfluentProducer__delivery_callback(user_callback)
57
+ mock_message = mock.Mock(spec=ConfluentMessage)
58
+ wrapped(None, mock_message)
59
+ assert (
60
+ Increment("arroyo.producer.produce_status", 1, {"status": "success"})
61
+ in TestingMetricsBackend.calls
62
+ )
63
+ assert len(user_callback_invoked) == 1
64
+ assert user_callback_invoked[0] == (None, mock_message)
File without changes
File without changes
File without changes