* test(s3/lifecycle): bundle dispatcher + engine edge-case coverage
Two-package bundle covering uncovered branches in production code that
the existing happy-path tests don't reach. Dispatcher 58.1% → 60.2%
and engine 81.0% → 81.7% (engine lift modest because most branches
were already hit; the nil-rule defensive case is otherwise unreachable
from a Compile flow).
dispatcher (4 tests):
- FilerPersister.Load with nil Store errors with a "nil Store"
message rather than panicking at the Read call.
- FilerPersister.Save with nil Store same.
- FilerPersister.Load with a non-NotFound transport error wraps the
shard ID into the message AND keeps the underlying error
recoverable via errors.Is.
- FilerPersister.Load with successful empty []byte returns an empty
map, not a JSON-decode error — pinning that an existing-but-empty
cursor file is treated as "no entries".
- Tick initializes the retries map on first call without panic so a
freshly-constructed Dispatcher works.
- Tick with already-canceled ctx re-queues the popped Match, returns
zero, and never invokes the LifecycleDelete client — the Match
must not be lost across worker restart.
engine (4 tests):
- rulePredicateSensitive(nil) returns false rather than panicking on
the FilterTags dereference. The non-nil paths run through Compile,
but a defensive nil-rule arrival isn't reachable that way.
- rule with no FilterTags / empty FilterTags map returns false (the
check is len(FilterTags) > 0, so empty must classify as
non-sensitive — pinning catches a flipped >= comparison).
- rule with a populated FilterTags returns true.
* fix(s3/lifecycle): Tick must requeue every drained Match on shutdown
Per codex review on #9413: Tick called Schedule.Drain to pop ALL due
matches at once, then iterated. If ctx canceled mid-loop, only the
current Match was re-added — everything past that index was silently
lost across the worker restart. With N due matches, up to N-1 were
dropped.
Fix: on cancellation, re-add due[i:] (current + remaining) before
returning. Matches already dispatched (due[:i]) stay processed; the
schedule is left exactly as it would be if Drain had returned only
the dispatched prefix.
Strengthen the existing test to enqueue three due matches and assert
sched.Len()==3 after a pre-canceled Tick. Pre-fix the test would have
seen Len()==1 because only the first popped Match was re-added.
see https://blog.aqwari.net/xml-schema-go/
1. go get aqwari.net/xml/cmd/xsdgen
2. Add EncodingType element for ListBucketResult in AmazonS3.xsd
3. xsdgen -o s3api_xsd_generated.go -pkg s3api AmazonS3.xsd
4. Remove empty Grantee struct in s3api_xsd_generated.go
5. Remove xmlns: sed s'/http:\/\/s3.amazonaws.com\/doc\/2006-03-01\/\ //' s3api_xsd_generated.go