Skip to content

fix(client): ScriptInvokeAsync defaults to AllPrimaries instead of key-based routing #496

Description

@currantw

Summary

ScriptInvokeAsync defaults to Route.AllPrimaries when no route is provided via ClusterScriptOptions. This sends the script to every primary node, which is incorrect for key-targeted scripts.

Description

In cluster mode, all keys in a script must hash to the same slot (CROSSSLOT error otherwise). Glide-core's default routing for EVALSHA is ThirdArgAfterKeyCount — it routes by the first key's slot, or falls back to Random if no keys are provided.

Current behavior:

Route route = options.Route ?? Route.AllPrimaries;

When ClusterScriptOptions.Route is null, the script is sent to all primaries regardless of whether keys are provided.

Expected behavior:

The cluster client should follow the same pattern as Python, Node, Go, and Java:

  • Key-based invocation (inherited from BaseClient): takes keys + args, glide-core routes by key slot, returns single value
  • Route-based invocation (cluster-only): takes args + explicit Route parameter, returns ClusterValue<T>

Proposed Solution

Remove:

  • ClusterScriptOptions class entirely (sources/Valkey.Glide/scripting/ClusterScriptOptions.cs)
  • IGlideClusterClient.ScriptInvokeAsync(Script, ClusterScriptOptions, CancellationToken) — interface declaration
  • GlideClusterClient.ScriptInvokeAsync(Script, ClusterScriptOptions, CancellationToken) — implementation

Keep (already exists, inherited by cluster client):

  • BaseClient.ScriptInvokeAsync(Script, CancellationToken)Task<ValkeyResult> — no keys, no args
  • BaseClient.ScriptInvokeAsync(Script, ScriptOptions, CancellationToken)Task<ValkeyResult> — with keys + args, glide-core routes by key slot

Add (new, cluster-only — for explicit route-based invocation without keys):

  • IGlideClusterClient.ScriptInvokeAsync(Script, Route, CancellationToken)Task<ClusterValue<ValkeyResult>>
  • IGlideClusterClient.ScriptInvokeAsync(Script, string[], Route, CancellationToken)Task<ClusterValue<ValkeyResult>> — with args

Effort & Severity Estimates

  • Effort: medium
  • Severity: medium

Related

Metadata

Metadata

Assignees

Labels

breakingIntroduces a breaking changecoreCore library (`sources/Valkey.Glide/`)triageNeeds triage — not yet reviewed

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions