Scenario: Key-Shared Advanced
Objective
Test advanced Key-Shared subscription features beyond basic per-key affinity — including glob-based key filtering, Key-Shared on partitioned topics, and poison message handling with failure policies.
When to Use
- User wants to test "key filtering", "glob filter", "key-shared filter", "routing filter"
- User wants to test Key-Shared on partitioned topics
- User wants to test poison message handling with Key-Shared
- User wants to test consumer eviction for inactive Key-Shared consumers
- User has already tested basic Key-Shared (via
core-messaging) and wants to go deeper
Compatible Infrastructure
| Setup Method |
Standalone |
Cluster |
Notes |
| Local Binary |
✅ |
✅ |
danube-admin needed for topic creation and failure policies |
| Local Source |
✅ |
✅ |
Same |
| Docker Compose |
✅ |
✅ |
Use exposed ports |
| Kubernetes |
— |
✅ |
Use port-forwarded addresses |
Key filtering and poison handling work on standalone. Partitioned Key-Shared benefits from a cluster for better distribution but works on standalone.
AI Decision Flow
1. Which Key-Shared feature to test?
Present these options to the user exactly as listed:
Key Filtering: Consumers with glob-based key filters receive only matching keys. Tests both pure filtering (all consumers have filters) and mixed mode (one filtered, one unfiltered — the unfiltered consumer gets remaining keys). Verify total messages across all consumers equals total sent.
Partitioned Key-Shared: Key-Shared subscription on a partitioned topic. Verify per-key affinity is maintained across partitions and messages distribute across consumers. Includes consumer churn — a new consumer joins mid-traffic, keys may redistribute but per-key ordering is preserved.
Poison Handling: Test failure policies on Key-Shared with reliable dispatch — drop (poisoned message skipped, key unblocked for new messages) and block (only the affected key stalls, other keys continue). Also verifies NACK redelivery preserves key affinity (same key → same consumer).
Each aspect maps to the corresponding Step 2x in Execution Steps below.
2. Tool or Client Language?
| User says |
Choice |
| "python", "rust", "go", "java" |
Client library — read clients/<lang>/SKILL.md |
| (unclear) |
Default: Python |
Note: All Key-Shared advanced tests require a client library. The CLI does not support Key-Shared subscriptions, key filters, or programmatic NACK.
3. Reliable or non-reliable?
| User says |
Choice |
| "reliable", "at-least-once" |
Reliable — topic created with --dispatch-strategy reliable, producer uses .with_reliable_dispatch() |
| "non-reliable", "fire and forget", "fast" |
Non-reliable — default dispatch |
| (unclear) |
Default: Non-reliable for filtering, Reliable for poison handling |
Execution Steps
Step 1: Create the Topic
# Non-reliable
danube-admin topics create /default/ks-advanced-test
# Reliable (required for poison handling)
danube-admin topics create /default/ks-advanced-test --dispatch-strategy reliable
# Partitioned
danube-admin topics create /default/ks-advanced-test --partitions 3
# Partitioned + reliable
danube-admin topics create /default/ks-advanced-test --dispatch-strategy reliable --partitions 3
Step 2a: Key Filtering (if selected)
Pure Filtering
Two consumers with different glob filters on the same Key-Shared subscription.
Generate a script that:
- Creates a producer
- Creates Consumer A with
.with_key_filter("user-*") (or with_key_filters(["eu-*", "ap-*"]))
- Creates Consumer B with
.with_key_filter("order-*") (or with_key_filters(["us-*", "af-*"]))
- Both consumers use the same subscription name with
SubType::KeyShared
- Producer sends messages with keys:
user-1, user-2, order-1, order-2 (or eu-west, ap-tokyo, us-east, af-cape)
- Verify: Consumer A only receives
user-* messages, Consumer B only receives order-* messages
Filter pattern examples:
"user-*" — matches user-1, user-admin, user-anything
"eu-*" — matches eu-west, eu-east
"ship?" — matches ship1, shipA (single char wildcard)
Mixed Filters
One consumer with a filter, one without (accepts all keys):
- Consumer A: no filter (accepts all keys)
- Consumer B:
.with_key_filter("vip-*") (only VIP keys)
- Producer sends:
vip-gold, vip-platinum, regular-1, regular-2
- Verify: Consumer B gets all
vip-* messages, Consumer A gets regular-* messages
- Total messages across both consumers = total sent
Step 2b: Partitioned Key-Shared (if selected)
Key-Shared on a partitioned topic:
- Create topic with
--partitions 3
- Create 2 Key-Shared consumers on the same subscription
- Producer sends messages with routing keys across partitions
- Verify: per-key affinity maintained (same key → same consumer across all partitions)
- Verify: messages distributed across multiple consumers
With consumer churn:
- Start with 1 consumer
- Send first batch of messages
- 2nd consumer joins the same Key-Shared subscription
- Send second batch of messages
- Verify: keys may be redistributed, but per-key ordering is preserved within each consumer
Step 2c: Poison Handling (if selected)
Key-Shared with failure policies — tests what happens when a consumer NACKs a message until retries are exhausted.
NACK Redelivery (Key Affinity)
- Set failure policy with retries allowed
- Send message with key, consumer NACKs
- Verify: same message redelivered to the SAME consumer (key affinity preserved)
- Consumer acks on second attempt
Drop Policy (skip poisoned message, continue with same key)
danube-admin topics set-failure-policy /default/ks-advanced-test \
--subscription ks-test-sub \
--max-redelivery-count 1 \
--ack-timeout-ms 5000 \
--base-redelivery-delay-ms 50 \
--max-redelivery-delay-ms 50 \
--backoff-strategy fixed \
--poison-policy drop
- Create reliable producer + Key-Shared consumer
- Send message with key "payment", consumer NACKs it
- Message is redelivered (1 retry allowed)
- Consumer NACKs again → retries exhausted, message dropped
- Send another message with same key "payment"
- Verify: new message delivered (key is unblocked)
Block Policy (stalls only the affected key)
danube-admin topics set-failure-policy /default/ks-advanced-test \
--subscription ks-test-sub \
--max-redelivery-count 0 \
--ack-timeout-ms 5000 \
--base-redelivery-delay-ms 50 \
--max-redelivery-delay-ms 50 \
--backoff-strategy fixed \
--poison-policy block
- Create reliable producer + 2 Key-Shared consumers
- Send message with key "poison-key", consumer NACKs it → blocked
- Send message with different key "healthy-key"
- Verify: "healthy-key" message IS delivered (different key, different slot)
- Verify: "poison-key" is stalled (blocked)
Verification
| Test |
Pass Criteria |
| Key Filtering (Pure) |
Each consumer only receives messages matching its glob pattern |
| Key Filtering (Mixed) |
Filtered consumer gets matching keys, unfiltered gets the rest, total = sent |
| Partitioned Key-Shared |
Per-key affinity across partitions, distribution across consumers |
| Consumer Churn |
Keys redistributed, per-key ordering preserved |
| NACK Redelivery |
Same message redelivered to same consumer (key affinity) |
| Drop Policy |
Poisoned message skipped, key unblocked for new messages |
| Block Policy |
Only affected key stalled, other keys continue normally |
# Inspect topic state
danube-admin topics describe /default/ks-advanced-test
danube-admin topics subscriptions /default/ks-advanced-test
# Check failure policy
danube-admin topics get-failure-policy /default/ks-advanced-test \
--subscription ks-test-sub --output json
Cleanup
This scenario only cleans up topics it created. See setups/SKILL.md → Cleanup for cluster teardown.
danube-admin topics delete /default/ks-advanced-test
1---2name: key-shared-advanced3description: Advanced Key-Shared subscription tests: glob key filtering, partitioned key-shared, and poison message handling with failure policies.4---56# Scenario: Key-Shared Advanced78## Objective910Test advanced Key-Shared subscription features beyond basic per-key affinity — including glob-based key filtering, Key-Shared on partitioned topics, and poison message handling with failure policies.1112## When to Use1314- User wants to test "key filtering", "glob filter", "key-shared filter", "routing filter"15- User wants to test Key-Shared on partitioned topics16- User wants to test poison message handling with Key-Shared17- User wants to test consumer eviction for inactive Key-Shared consumers18- User has already tested basic Key-Shared (via `core-messaging`) and wants to go deeper1920## Compatible Infrastructure2122| Setup Method | Standalone | Cluster | Notes |23|-------------|:----------:|:-------:|-------|24| Local Binary | ✅ | ✅ | `danube-admin` needed for topic creation and failure policies |25| Local Source | ✅ | ✅ | Same |26| Docker Compose | ✅ | ✅ | Use exposed ports |27| Kubernetes | — | ✅ | Use port-forwarded addresses |2829Key filtering and poison handling work on standalone. Partitioned Key-Shared benefits from a cluster for better distribution but works on standalone.3031## AI Decision Flow3233### 1. Which Key-Shared feature to test?3435Present these options to the user **exactly as listed**:36371. **Key Filtering**: Consumers with glob-based key filters receive only matching keys. Tests both pure filtering (all consumers have filters) and mixed mode (one filtered, one unfiltered — the unfiltered consumer gets remaining keys). Verify total messages across all consumers equals total sent.38392. **Partitioned Key-Shared**: Key-Shared subscription on a partitioned topic. Verify per-key affinity is maintained across partitions and messages distribute across consumers. Includes consumer churn — a new consumer joins mid-traffic, keys may redistribute but per-key ordering is preserved.40413. **Poison Handling**: Test failure policies on Key-Shared with reliable dispatch — drop (poisoned message skipped, key unblocked for new messages) and block (only the affected key stalls, other keys continue). Also verifies NACK redelivery preserves key affinity (same key → same consumer).4243Each aspect maps to the corresponding `Step 2x` in Execution Steps below.4445### 2. Tool or Client Language?4647| User says | Choice |48|-----------|--------|49| "python", "rust", "go", "java" | **Client library** — read `clients/<lang>/SKILL.md` |50| *(unclear)* | Default: **Python** |5152**Note:** All Key-Shared advanced tests require a client library. The CLI does not support Key-Shared subscriptions, key filters, or programmatic NACK.5354### 3. Reliable or non-reliable?5556| User says | Choice |57|-----------|------|58| "reliable", "at-least-once" | **Reliable** — topic created with `--dispatch-strategy reliable`, producer uses `.with_reliable_dispatch()` |59| "non-reliable", "fire and forget", "fast" | **Non-reliable** — default dispatch |60| *(unclear)* | Default: **Non-reliable** for filtering, **Reliable** for poison handling |6162## Execution Steps6364### Step 1: Create the Topic6566```bash67# Non-reliable68danube-admin topics create /default/ks-advanced-test6970# Reliable (required for poison handling)71danube-admin topics create /default/ks-advanced-test --dispatch-strategy reliable7273# Partitioned74danube-admin topics create /default/ks-advanced-test --partitions 37576# Partitioned + reliable77danube-admin topics create /default/ks-advanced-test --dispatch-strategy reliable --partitions 378```7980### Step 2a: Key Filtering (if selected)8182#### Pure Filtering8384Two consumers with different glob filters on the same Key-Shared subscription.8586Generate a script that:871. Creates a producer882. Creates Consumer A with `.with_key_filter("user-*")` (or `with_key_filters(["eu-*", "ap-*"])`)893. Creates Consumer B with `.with_key_filter("order-*")` (or `with_key_filters(["us-*", "af-*"])`)904. Both consumers use the same subscription name with `SubType::KeyShared`915. Producer sends messages with keys: `user-1`, `user-2`, `order-1`, `order-2` (or `eu-west`, `ap-tokyo`, `us-east`, `af-cape`)926. Verify: Consumer A only receives `user-*` messages, Consumer B only receives `order-*` messages9394**Filter pattern examples:**95- `"user-*"` — matches `user-1`, `user-admin`, `user-anything`96- `"eu-*"` — matches `eu-west`, `eu-east`97- `"ship?"` — matches `ship1`, `shipA` (single char wildcard)9899#### Mixed Filters100101One consumer with a filter, one without (accepts all keys):1021031. Consumer A: no filter (accepts all keys)1042. Consumer B: `.with_key_filter("vip-*")` (only VIP keys)1053. Producer sends: `vip-gold`, `vip-platinum`, `regular-1`, `regular-2`1064. Verify: Consumer B gets all `vip-*` messages, Consumer A gets `regular-*` messages1075. Total messages across both consumers = total sent108109### Step 2b: Partitioned Key-Shared (if selected)110111Key-Shared on a partitioned topic:1121131. Create topic with `--partitions 3`1142. Create 2 Key-Shared consumers on the same subscription1153. Producer sends messages with routing keys across partitions1164. Verify: per-key affinity maintained (same key → same consumer across all partitions)1175. Verify: messages distributed across multiple consumers118119**With consumer churn:**1201211. Start with 1 consumer1222. Send first batch of messages1233. 2nd consumer joins the same Key-Shared subscription1244. Send second batch of messages1255. Verify: keys may be redistributed, but per-key ordering is preserved within each consumer126127### Step 2c: Poison Handling (if selected)128129Key-Shared with failure policies — tests what happens when a consumer NACKs a message until retries are exhausted.130131#### NACK Redelivery (Key Affinity)1321331. Set failure policy with retries allowed1342. Send message with key, consumer NACKs1353. Verify: same message redelivered to the SAME consumer (key affinity preserved)1364. Consumer acks on second attempt137138#### Drop Policy (skip poisoned message, continue with same key)139140```bash141danube-admin topics set-failure-policy /default/ks-advanced-test \142 --subscription ks-test-sub \143 --max-redelivery-count 1 \144 --ack-timeout-ms 5000 \145 --base-redelivery-delay-ms 50 \146 --max-redelivery-delay-ms 50 \147 --backoff-strategy fixed \148 --poison-policy drop149```1501511. Create reliable producer + Key-Shared consumer1522. Send message with key "payment", consumer NACKs it1533. Message is redelivered (1 retry allowed)1544. Consumer NACKs again → retries exhausted, message dropped1555. Send another message with same key "payment"1566. Verify: new message delivered (key is unblocked)157158#### Block Policy (stalls only the affected key)159160```bash161danube-admin topics set-failure-policy /default/ks-advanced-test \162 --subscription ks-test-sub \163 --max-redelivery-count 0 \164 --ack-timeout-ms 5000 \165 --base-redelivery-delay-ms 50 \166 --max-redelivery-delay-ms 50 \167 --backoff-strategy fixed \168 --poison-policy block169```1701711. Create reliable producer + 2 Key-Shared consumers1722. Send message with key "poison-key", consumer NACKs it → blocked1733. Send message with different key "healthy-key"1744. Verify: "healthy-key" message IS delivered (different key, different slot)1755. Verify: "poison-key" is stalled (blocked)176177## Verification178179| Test | Pass Criteria |180|------|--------------|181| **Key Filtering (Pure)** | Each consumer only receives messages matching its glob pattern |182| **Key Filtering (Mixed)** | Filtered consumer gets matching keys, unfiltered gets the rest, total = sent |183| **Partitioned Key-Shared** | Per-key affinity across partitions, distribution across consumers |184| **Consumer Churn** | Keys redistributed, per-key ordering preserved |185| **NACK Redelivery** | Same message redelivered to same consumer (key affinity) |186| **Drop Policy** | Poisoned message skipped, key unblocked for new messages |187| **Block Policy** | Only affected key stalled, other keys continue normally |188189```bash190# Inspect topic state191danube-admin topics describe /default/ks-advanced-test192danube-admin topics subscriptions /default/ks-advanced-test193194# Check failure policy195danube-admin topics get-failure-policy /default/ks-advanced-test \196 --subscription ks-test-sub --output json197```198199## Cleanup200201This scenario only cleans up topics it created. See `setups/SKILL.md` → **Cleanup** for cluster teardown.202203```bash204danube-admin topics delete /default/ks-advanced-test205```