Skip to content

Commit 7d842bb

Browse files
committed
Add tests
- Test recovery with multiple input topics - Test state with concatenated SDFs
1 parent 237ed49 commit 7d842bb

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

tests/test_quixstreams/test_app.py

+85
Original file line numberDiff line numberDiff line change
@@ -2712,3 +2712,88 @@ def revoke_partition(store, partition):
27122712
consumer_group,
27132713
state_dir,
27142714
)
2715+
2716+
@pytest.mark.parametrize("store_type", SUPPORTED_STORES, indirect=True)
2717+
def test_concatenated_sdfs_stateful(
2718+
self,
2719+
app_factory,
2720+
executor,
2721+
state_manager_factory,
2722+
tmp_path,
2723+
):
2724+
def on_message_processed(*_):
2725+
# Set the callback to track total messages processed
2726+
# The callback is not triggered if processing fails
2727+
nonlocal processed_count
2728+
2729+
processed_count += 1
2730+
# Stop processing after consuming all the messages
2731+
if processed_count == total_messages:
2732+
done.set_result(True)
2733+
2734+
processed_count = 0
2735+
2736+
consumer_group = str(uuid.uuid4())
2737+
state_dir = (tmp_path / "state").absolute()
2738+
partition_num = 0
2739+
app = app_factory(
2740+
commit_interval=0,
2741+
consumer_group=consumer_group,
2742+
auto_offset_reset="earliest",
2743+
state_dir=state_dir,
2744+
on_message_processed=on_message_processed,
2745+
use_changelog_topics=True,
2746+
)
2747+
input_topic_a = app.topic(
2748+
str(uuid.uuid4()), value_deserializer=JSONDeserializer()
2749+
)
2750+
input_topic_b = app.topic(
2751+
str(uuid.uuid4()), value_deserializer=JSONDeserializer()
2752+
)
2753+
input_topics = [input_topic_a, input_topic_b]
2754+
messages_per_topic = 3
2755+
total_messages = messages_per_topic * len(input_topics)
2756+
2757+
# Define a function that counts incoming Rows using state
2758+
def count(_, state: State):
2759+
total = state.get("total", 0)
2760+
total += 1
2761+
state.set("total", total)
2762+
2763+
sdf_a = app.dataframe(input_topic_a)
2764+
sdf_b = app.dataframe(input_topic_b)
2765+
2766+
sdf_concat = sdf_a.concat(sdf_b)
2767+
sdf_concat.update(count, stateful=True)
2768+
2769+
# Produce messages to the topic and flush
2770+
message_key = b"key"
2771+
data = {
2772+
"key": message_key,
2773+
"value": dumps({"key": "value"}),
2774+
"partition": partition_num,
2775+
}
2776+
with app.get_producer() as producer:
2777+
for topic in input_topics:
2778+
for _ in range(messages_per_topic):
2779+
producer.produce(topic.name, **data)
2780+
2781+
done = Future()
2782+
# Stop app when the future is resolved
2783+
executor.submit(_stop_app_on_future, app, done, 10.0)
2784+
2785+
stores = {}
2786+
2787+
def revoke_partition(store_, partition):
2788+
stores[store_.stream_id] = store_
2789+
2790+
with patch("quixstreams.state.base.Store.revoke_partition", revoke_partition):
2791+
app.run()
2792+
2793+
assert processed_count == total_messages
2794+
2795+
store = stores[sdf_concat.stream_id]
2796+
partition = store.partitions[partition_num]
2797+
with partition.begin() as tx:
2798+
assert tx.get("total", prefix=message_key) == total_messages
2799+
store.revoke_partition(partition_num)

tests/test_quixstreams/test_state/test_recovery/test_recovery_partition.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,24 @@ def test_recover_from_changelog_message_with_processed_offset_behind_committed(
170170
assert tx.get(user_store_key, prefix=kafka_key) == 10
171171
assert store_partition.get_changelog_offset() == changelog_msg.offset()
172172

173+
@pytest.mark.parametrize(
174+
"processed_offsets, committed_offsets",
175+
# Processed offsets should be strictly lower than committed offsets for
176+
# the change to be applied
177+
[
178+
({"topic1": 2}, {"topic1": 1}),
179+
({"topic1": 2}, {"topic1": 2}),
180+
({"topic1": 2, "topic2": 2}, {"topic1": 3, "topic2": 2}),
181+
({"topic1": 2, "topic2": 2}, {"topic1": 1, "topic2": 3}),
182+
({"topic1": 2, "topic2": 2}, {"topic1": 1, "topic2": 1}),
183+
],
184+
)
173185
def test_recover_from_changelog_message_with_processed_offset_ahead_committed(
174-
self, store_partition, recovery_partition_factory
186+
self,
187+
store_partition,
188+
recovery_partition_factory,
189+
processed_offsets,
190+
committed_offsets,
175191
):
176192
"""
177193
Test that changes from the changelog topic are NOT applied if the
@@ -186,11 +202,6 @@ def test_recover_from_changelog_message_with_processed_offset_ahead_committed(
186202
kafka_key = b"my_key"
187203
user_store_key = "count"
188204

189-
# Processed offset should be strictly lower than committed offset for
190-
# the change to be applied
191-
processed_offsets = {"topic": 2}
192-
committed_offsets = {"topic": 2}
193-
194205
recovery_partition = recovery_partition_factory(
195206
store_partition=store_partition, committed_offsets=committed_offsets
196207
)

0 commit comments

Comments
 (0)