Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 8 additions & 17 deletions sources/Valkey.Glide/Abstract/ValkeyBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,23 @@ internal override async Task<T> Command<R, T>(Cmd<R, T> command, Route? route =
: (T)batchResult[idx]!;
}

protected virtual bool PreExecCheck() => true;

protected async Task ExecuteImpl()
{
if (_tcs.Task.Status == TaskStatus.RanToCompletion)
{
// a batch is already executed
return;
}
if (PreExecCheck())
{
if (_commands.Count == 0)
{
_tcs.SetResult([]);
return;
}
Batch b = new(_isAtomic);
b.Commands.AddRange(_commands);

object?[]? res = await _client.Batch(b, false);
_tcs.SetResult(res);
}
else
if (_commands.Count == 0)
{
_tcs.SetResult(null);
_tcs.SetResult([]);
return;
}
Batch b = new(_isAtomic);
b.Commands.AddRange(_commands);

object?[]? res = await _client.Batch(b, false);
_tcs.SetResult(res);
}

public void Execute() => ExecuteImpl().GetAwaiter().GetResult();
Expand Down
31 changes: 18 additions & 13 deletions sources/Valkey.Glide/Abstract/ValkeyTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,33 @@ public bool Execute(CommandFlags flags = CommandFlags.None)
public async Task<bool> ExecuteAsync(CommandFlags flags = CommandFlags.None)
{
GuardClauses.ThrowIfCommandFlags(flags);
await ExecuteImpl();
return _tcs.Task.Result is not null;
}

protected override bool PreExecCheck()
{
bool allConditionsPassed = true;
// Evaluate all conditions asynchronously before submitting the transaction.
// This replaces the former sync-over-async PreExecCheck() override in the
// base class, keeping transaction-specific logic here rather than leaking
// it into ValkeyBatch.
foreach (ConditionResult condition in _conditions)
{
// We can't access internals of batch, but we can create a transaction, "downcast" it to batch and patch it
ValkeyTransaction b = new(_client)
// Execute the condition commands in a non-atomic batch to check the
// current state of the watched keys.
ValkeyTransaction conditionBatch = new(_client)
{
_isAtomic = false
};
b._commands.AddRange(condition.Condition.CreateCommands());
b.ExecuteImpl().GetAwaiter().GetResult();
condition.WasSatisfied = condition.Condition.Validate(b._tcs.Task.Result);
conditionBatch._commands.AddRange(condition.Condition.CreateCommands());
await conditionBatch.ExecuteImpl();

condition.WasSatisfied = condition.Condition.Validate(conditionBatch._tcs.Task.Result);
if (!condition.WasSatisfied)
{
allConditionsPassed = false;
// At least one condition failed — cancel the transaction without
// submitting the MULTI/EXEC block.
_tcs.SetResult(null);
return false;
}
}
return allConditionsPassed;

await ExecuteImpl();
return _tcs.Task.Result is not null;
}
}
Loading