What to build
Split the multi-key operations in WorkerRegistry.java and client/RedisTraceWriter.java that mix keys belonging to different logical entities — these can't share a Cluster hash tag and would throw CROSSSLOT under Cluster mode. Two known patterns, same as Python/TS (confirmed to be the same underlying problem, not language-specific):
Mode A — worker admin-state writes that also update the global admin-workers index set in the same call sequence. Split into two independent, non-transactional writes; treat the index as best-effort/eventually-consistent, with the per-worker admin-state key as source of truth for reads.
Mode B — trace writes (RedisTraceWriter.java, jedis.hset(traceKey,...) + jedis.rpush(spanKey,...) + indexTrace(jedis, traceIndexSession(...),...) sequence) that mix the trace group (meta + spans, same entity, stays atomic once tagged in Phase 2a) with session/worker/agent_type index writes (different entities). Split into: (1) an atomic write for trace meta + spans + their TTL, and (2) independent best-effort writes for each index key (session/worker/agent_type index), each individually try/caught and logged on failure without failing the parent trace write. This preserves the existing best-effort trace-writing design principle — it just narrows what's atomic.
Note: the two keys written together by denyWorkerForType (agent_type members + denied) are explicitly NOT part of this split — they already share a hash tag from Phase 2a and keep their existing write-together behavior.
Acceptance criteria
Blocked by
#9
What to build
Split the multi-key operations in
WorkerRegistry.javaandclient/RedisTraceWriter.javathat mix keys belonging to different logical entities — these can't share a Cluster hash tag and would throw CROSSSLOT under Cluster mode. Two known patterns, same as Python/TS (confirmed to be the same underlying problem, not language-specific):Mode A — worker admin-state writes that also update the global admin-workers index set in the same call sequence. Split into two independent, non-transactional writes; treat the index as best-effort/eventually-consistent, with the per-worker admin-state key as source of truth for reads.
Mode B — trace writes (
RedisTraceWriter.java,jedis.hset(traceKey,...)+jedis.rpush(spanKey,...)+indexTrace(jedis, traceIndexSession(...),...)sequence) that mix the trace group (meta + spans, same entity, stays atomic once tagged in Phase 2a) with session/worker/agent_type index writes (different entities). Split into: (1) an atomic write for trace meta + spans + their TTL, and (2) independent best-effort writes for each index key (session/worker/agent_type index), each individually try/caught and logged on failure without failing the parent trace write. This preserves the existing best-effort trace-writing design principle — it just narrows what's atomic.Note: the two keys written together by
denyWorkerForType(agent_type members + denied) are explicitly NOT part of this split — they already share a hash tag from Phase 2a and keep their existing write-together behavior.Acceptance criteria
denyWorkerForTypepath explicitly left untouched (still writes both keys together, now sharing a tag from Phase 2a)Blocked by
#9