Files
Chris LuandGitHub 0f6c6b0524 feat(s3/lifecycle): shard-aware meta-log reader (Phase 3 PR-B) (#9354)
feat(s3/lifecycle): shard-aware meta-log reader

- ShardCount=16; ShardID(bucket,key)=top-4-bits of sha256(bucket||/||key)
- Reader subscribes via SubscribeMetadata starting at Cursor.MinTsNs(),
  filters events by shard, emits to caller-owned Events channel
- Cursor: per-(shard, ActionKey) position with monotonic Advance, Freeze
  for blocked actions, MinTsNs for subscription resume
- Persister interface with InMemoryPersister for tests; filer-backed
  impl lands with the worker integration
2026-05-07 15:42:37 -07:00

47 lines
1.2 KiB
Go

package s3lifecycle
import "testing"
func TestShardIDInRange(t *testing.T) {
cases := []struct{ bucket, key string }{
{"", ""},
{"a", "b"},
{"my-bucket", "path/to/object.txt"},
{"日本語", "キー"},
{"bucket-with-dash", ""},
}
for _, c := range cases {
got := ShardID(c.bucket, c.key)
if got < 0 || got >= ShardCount {
t.Fatalf("ShardID(%q,%q)=%d outside [0,%d)", c.bucket, c.key, got, ShardCount)
}
}
}
func TestShardIDDeterministic(t *testing.T) {
a := ShardID("bucket", "key")
b := ShardID("bucket", "key")
if a != b {
t.Fatalf("non-deterministic: %d vs %d", a, b)
}
}
func TestShardIDDistinctFromBucket(t *testing.T) {
// Same key, different buckets must be free to land on different shards.
// (Statistical: with 16 shards, picking 16 distinct buckets should hit
// at least 4 different shards.)
seen := map[int]struct{}{}
for i := 0; i < 16; i++ {
buckets := []string{
"alpha", "bravo", "charlie", "delta",
"echo", "foxtrot", "golf", "hotel",
"india", "juliet", "kilo", "lima",
"mike", "november", "oscar", "papa",
}
seen[ShardID(buckets[i], "samekey")] = struct{}{}
}
if len(seen) < 4 {
t.Fatalf("expected >=4 distinct shards across 16 buckets, got %d", len(seen))
}
}