Commit 25b3898
feat: MM2 features, string/cache transforms, hardened error handling
## New features
### MirrorMaker 2 parity
- Topic regex subscription: `input: "^payments.*"` subscribes to all matching
topics and picks up newly created ones automatically (rdkafka native support)
- Output topic templates: `output: "mirror.{source_topic}"` resolves per-message
from the envelope source topic with lazy partition-count caching
### Cache transforms (CACHE_PUT / CACHE_LOOKUP)
- `SyncLookupCache` / `SyncCacheManager` — sync Moka cache shared across the
transform pipeline; named stores auto-created on first reference
- `CACHE_PUT:/key,store[,/valuePath]` — write message (or a field) to a named
store; message passes through unchanged
- `CACHE_LOOKUP:/key,store,field|MERGE` — enrich message from cache; pass
through on miss or missing key
### String transforms (STRING:*)
- UPPER, LOWER, TRIM, TRIM_START, TRIM_END, LENGTH, SUBSTRING, REPLACE,
REPLACE_ALL, REGEX_REPLACE, SPLIT, CONCAT (12 operations)
- All accept an optional `,outputField` to write result without touching original
### Single-destination transform support
- New `transform: <expr>` top-level config field for single-destination mode
- Full DSL (including CACHE_*) available without switching to routing mode
## Error handling hardening
### Fail-soft on data — all transforms pass through on missing/null fields
- Missing field, null value, or wrong type for the operation → message passes
through unchanged with a debug log; pipeline never halted for data issues
- Applies to: JsonPath, ArrayMap, Arithmetic, Hash, String, Concat, CacheLookup,
CachePut transforms
- Config errors (invalid regex, empty `from`, empty CONCAT parts) still fail
at parse time
### Additional fixes
- `resolve_topic`: template + no source topic → error (was silent `mirror.unknown`)
- `get_or_fetch_partitions`: blocking `fetch_metadata` wrapped in `block_in_place`
- `partition_cache` mutex uses `unwrap_or_else(|e| e.into_inner())` for poison recovery
- `flush()`: errors now propagate via `MirrorMakerError::Kafka` (was `let _ = ...`)
- `flush_all`: attempts all sinks, collects errors, never abandons remaining sinks
- `parse_input_topics`: warns on apparent regex patterns without `^` prefix
- `STRING:REPLACE`: empty `from` rejected at parse time (prevents per-char insertion)
- `STRING:CONCAT`: empty parts rejected at parse time (trailing/double commas)
- `STRING:CONCAT`: empty `outputField` rejected at parse time
- `routing` + `transform` both set: `warn!` that top-level transform is ignored
## README
- Comprehensive comparison vs MirrorMaker 1 and MirrorMaker 2 (feature matrix,
performance table, when-to-choose guidance)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>1 parent 4231cac commit 25b3898
10 files changed
Lines changed: 1924 additions & 439 deletions
File tree
- src
- filter
- kafka
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
186 | 186 | | |
187 | 187 | | |
188 | 188 | | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
189 | 295 | | |
190 | 296 | | |
191 | 297 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
37 | 45 | | |
38 | 46 | | |
39 | 47 | | |
| |||
0 commit comments