Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 19df7c3

Browse files
authored
feat: support pattern subscription non persistent topic. (#134)
1 parent ac4fcf0 commit 19df7c3

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

pulsar/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
import _pulsar
4949

5050
from _pulsar import Result, CompressionType, ConsumerType, InitialPosition, PartitionsRoutingMode, BatchingType, \
51-
LoggerLevel, BatchReceivePolicy, KeySharedPolicy, KeySharedMode, ProducerAccessMode # noqa: F401
51+
LoggerLevel, BatchReceivePolicy, KeySharedPolicy, KeySharedMode, ProducerAccessMode, RegexSubscriptionMode # noqa: F401
5252

5353
from pulsar.__about__ import __version__
5454

@@ -707,6 +707,7 @@ def subscribe(self, topic, subscription_name,
707707
batch_receive_policy=None,
708708
key_shared_policy=None,
709709
batch_index_ack_enabled=False,
710+
regex_subscription_mode=RegexSubscriptionMode.PersistentOnly,
710711
):
711712
"""
712713
Subscribe to the given topic and subscription combination.
@@ -796,6 +797,14 @@ def my_listener(consumer, message):
796797
batch_index_ack_enabled: Enable the batch index acknowledgement.
797798
It should be noted that this option can only work when the broker side also enables the batch index
798799
acknowledgement. See the `acknowledgmentAtBatchIndexLevelEnabled` config in `broker.conf`.
800+
regex_subscription_mode: RegexSubscriptionMode, optional
801+
Set the regex subscription mode for use when the topic is a regex pattern.
802+
803+
Supported modes:
804+
805+
* PersistentOnly: By default only subscribe to persistent topics.
806+
* NonPersistentOnly: Only subscribe to non-persistent topics.
807+
* AllTopics: Subscribe to both persistent and non-persistent topics.
799808
"""
800809
_check_type(str, subscription_name, 'subscription_name')
801810
_check_type(ConsumerType, consumer_type, 'consumer_type')
@@ -818,9 +827,11 @@ def my_listener(consumer, message):
818827
_check_type_or_none(ConsumerBatchReceivePolicy, batch_receive_policy, 'batch_receive_policy')
819828
_check_type_or_none(ConsumerKeySharedPolicy, key_shared_policy, 'key_shared_policy')
820829
_check_type(bool, batch_index_ack_enabled, 'batch_index_ack_enabled')
830+
_check_type(RegexSubscriptionMode, regex_subscription_mode, 'regex_subscription_mode')
821831

822832
conf = _pulsar.ConsumerConfiguration()
823833
conf.consumer_type(consumer_type)
834+
conf.regex_subscription_mode(regex_subscription_mode)
824835
conf.read_compacted(is_read_compacted)
825836
if message_listener:
826837
conf.message_listener(_listener_wrapper(message_listener, schema))

src/config.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ void export_config(py::module_& m) {
265265
.def("property", &ConsumerConfiguration::setProperty, return_value_policy::reference)
266266
.def("subscription_initial_position", &ConsumerConfiguration::getSubscriptionInitialPosition)
267267
.def("subscription_initial_position", &ConsumerConfiguration::setSubscriptionInitialPosition)
268+
.def("regex_subscription_mode", &ConsumerConfiguration::setRegexSubscriptionMode)
269+
.def("regex_subscription_mode", &ConsumerConfiguration::getRegexSubscriptionMode, return_value_policy::reference)
268270
.def("crypto_key_reader", &ConsumerConfiguration::setCryptoKeyReader, return_value_policy::reference)
269271
.def("replicate_subscription_state_enabled",
270272
&ConsumerConfiguration::setReplicateSubscriptionStateEnabled)

src/enums.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ void export_enums(py::module_& m) {
120120
.value("Latest", InitialPositionLatest)
121121
.value("Earliest", InitialPositionEarliest);
122122

123+
enum_<RegexSubscriptionMode>(m, "RegexSubscriptionMode", "Regex subscription mode")
124+
.value("PersistentOnly", PersistentOnly)
125+
.value("NonPersistentOnly", NonPersistentOnly)
126+
.value("AllTopics", AllTopics);
127+
123128
enum_<ProducerConfiguration::BatchingType>(m, "BatchingType", "Supported batching types")
124129
.value("Default", ProducerConfiguration::DefaultBatching)
125130
.value("KeyBased", ProducerConfiguration::KeyBasedBatching);

tests/pulsar_test.py

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from unittest import TestCase, main
2525
import time
2626
import os
27+
import re
2728
import pulsar
2829
import uuid
2930
from datetime import timedelta
@@ -46,7 +47,7 @@
4647
)
4748
from pulsar.schema import JsonSchema, Record, Integer
4849

49-
from _pulsar import ProducerConfiguration, ConsumerConfiguration
50+
from _pulsar import ProducerConfiguration, ConsumerConfiguration, RegexSubscriptionMode
5051

5152
from schema_test import *
5253

@@ -1100,7 +1101,6 @@ def test_topics_consumer(self):
11001101
client.close()
11011102

11021103
def test_topics_pattern_consumer(self):
1103-
import re
11041104

11051105
client = Client(self.serviceUrl)
11061106

@@ -1717,6 +1717,77 @@ def test_batch_index_ack(self):
17171717

17181718
client.close()
17191719

1720+
def test_regex_subscription(self):
1721+
client = Client(self.serviceUrl)
1722+
topic1 = "persistent://public/default/test-regex-sub-1"
1723+
topic2 = "persistent://public/default/test-regex-sub-2"
1724+
topic3 = "non-persistent://public/default/test-regex-sub-3"
1725+
topic4 = "persistent://public/default/no-match-test-regex-sub-3" # no match pattern rule topic.
1726+
1727+
producer1 = client.create_producer(topic1)
1728+
producer2 = client.create_producer(topic2)
1729+
producer3 = client.create_producer(topic3)
1730+
producer4 = client.create_producer(topic4)
1731+
1732+
consumer_all = client.subscribe(
1733+
re.compile('public/default/test-regex-sub-.*'), "regex-sub-all",
1734+
consumer_type=ConsumerType.Shared, regex_subscription_mode=RegexSubscriptionMode.AllTopics
1735+
)
1736+
1737+
consumer_persistent = client.subscribe(
1738+
re.compile('public/default/test-regex-sub-.*'), "regex-sub-persistent",
1739+
consumer_type=ConsumerType.Shared, regex_subscription_mode=RegexSubscriptionMode.PersistentOnly
1740+
)
1741+
1742+
consumer_non_persistent = client.subscribe(
1743+
re.compile('public/default/test-regex-sub-.*'), "regex-sub-non-persistent",
1744+
consumer_type=ConsumerType.Shared, regex_subscription_mode=RegexSubscriptionMode.NonPersistentOnly
1745+
)
1746+
1747+
num = 10
1748+
for i in range(num):
1749+
producer1.send(b"hello-1-%d" % i)
1750+
producer2.send(b"hello-2-%d" % i)
1751+
producer3.send(b"hello-3-%d" % i)
1752+
producer4.send(b"hello-4-%d" % i)
1753+
1754+
# Assert consumer_all.
1755+
received_topics = set()
1756+
for i in range(3 * num):
1757+
msg = consumer_all.receive(TM)
1758+
topic_name = msg.topic_name()
1759+
self.assertIn(topic_name, [topic1, topic2, topic3])
1760+
received_topics.add(topic_name)
1761+
consumer_all.acknowledge(msg)
1762+
self.assertEqual(received_topics, {topic1, topic2, topic3})
1763+
with self.assertRaises(pulsar.Timeout):
1764+
consumer_all.receive(100)
1765+
1766+
# Assert consumer_persistent.
1767+
received_topics.clear()
1768+
for i in range(2 * num):
1769+
msg = consumer_persistent.receive(TM)
1770+
topic_name = msg.topic_name()
1771+
self.assertIn(topic_name, [topic1, topic2])
1772+
received_topics.add(topic_name)
1773+
consumer_persistent.acknowledge(msg)
1774+
self.assertEqual(received_topics, {topic1, topic2})
1775+
with self.assertRaises(pulsar.Timeout):
1776+
consumer_persistent.receive(100)
1777+
1778+
# Assert consumer_non_persistent.
1779+
received_topics.clear()
1780+
for i in range(num):
1781+
msg = consumer_non_persistent.receive(TM)
1782+
topic_name = msg.topic_name()
1783+
self.assertIn(topic_name, [topic3])
1784+
received_topics.add(topic_name)
1785+
consumer_non_persistent.acknowledge(msg)
1786+
self.assertEqual(received_topics, {topic3})
1787+
with self.assertRaises(pulsar.Timeout):
1788+
consumer_non_persistent.receive(100)
1789+
1790+
client.close()
17201791

17211792
if __name__ == "__main__":
17221793
main()

0 commit comments

Comments
 (0)