aws / aws/event-ruler

Machine.deleteRule ghost/strand defect also affects anything-but wildcard patterns (follow-up to #255/#256)

Open
#259 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Java
Stars
615
Forks
82
Avg merge
1d 22h
Merged PRs (30d)
7

Description

## Describe the bug

#256 fixed `deleteRule` isolation for rules sharing byte-identical wildcard clauses (ghost: deleted rule keeps matching; strand: surviving sibling stops matching — see #255). The same defect class also affects `anything-but: {wildcard: ...}` patterns and is not covered by that fix.

Mechanism: `ByteMachine.findAllPatterns` routes `ANYTHING_BUT_WILDCARD` (and the other `ANYTHING_BUT*` types) to the `default:` single-NameState path. Anything-but-wildcard values are wildcard-parsed into the ByteMachine, so the add path's refusal to reuse indeterminate-prefix / self-loop composite states (`canReuseNextByteState`) applies — byte-identical anything-but-wildcard clauses accumulate one `NameState` per rule over shared transitions, and the single-NameState delete path picks an arbitrary one (ghost) or tears down shared transitions still referenced by a sibling (strand).

This is pre-existing: the repro below fails identically on `main` before and after #256 — #256 did not introduce or worsen it.

## To Reproduce

Non-deterministic ~50% per trial (HashSet iteration order), so run over many fresh machines:

```java
@Test
public void anythingButWildcard_sharedClause_deleteIsolation() throws Exception {
String ruleJson = "{\"name\":[\"test\"],\"properties.foo\":[{\"anything-but\":{\"wildcard\":\"*bar*\"}}]}";
String event = "{\"name\":\"test\",\"properties\":{\"foo\":\"nomatchhere\"}}";

for (int i = 0; i < 200; i++) {
Machine machine = Machine.builder().build();
machine.addRule("rule1", ruleJson);
machine.addRule("rule2", ruleJson);
assertEquals(2, machine.rulesForJSONEvent(event).size());

machine.deleteRule("rule1", ruleJson);

List after = machine.rulesForJSONEvent(event);
assertFalse("rule1 should be deleted (ghost)", after.contains("rule1"));
assertTrue("rule2 should still match (strand)", after.contains("rule2"));
}
}
```

Also reproduces with different-shaped rules sharing the same anything-but-wildcard clause on one field.

## Expected behavior

Same as #255: `deleteRule` removes only the named rule; siblings sharing the clause keep matching; result independent of add order.

## Proposed fix

Extend `findAllPatterns` to cover the `ANYTHING_BUT*` types (and audit `NUMERIC_RANGE`). The anything-but find paths are multi-value — each value in the set is looked up individually and the results are asserted to converge to a single NameState (`findAnythingButPattern` / `findAnythingButValuesSetPattern`) — so the extension needs per-value `findAllMatchPattern` with union semantics rather than the simple single-value delegation #256 added for value patterns. The teardown guard from #256 (`noNameStateContainsPattern`) already generalizes.

I'll take this as a stacked change on top of #256.

## Environment

- event-ruler current `main` (also reproduces on the #256 branch and on 1.8.x)

Contributor guide

Open the contributing guide

Research direction

Start at ByteMachine.findAllPatterns and trace the ANYTHING_BUT_WILDCARD paths through findAnythingButPattern and findAnythingButValuesSetPattern, including canReuseNextByteState and noNameStateContainsPattern. Add and run the anythingButWildcard_sharedClause_deleteIsolation test over fresh machines, then verify that deleting one rule leaves only its sibling matching regardless of add order.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.