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
12 changes: 7 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@ jobs:
strategy:
fail-fast: false
matrix:
framework: [net8.0, net9.0]
framework: [net8.0, net9.0, net10.0]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.ref || github.ref }}
- name: Install dotnet SDKs
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Scan for Vulnerabilities
shell: bash
run: |
Expand All @@ -57,7 +58,7 @@ jobs:
name: publish
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v5
with:
ref: ${{ github.event.inputs.ref || github.ref }}
fetch-depth: 0
Expand All @@ -78,11 +79,12 @@ jobs:
echo "version=${version}" >> $GITHUB_OUTPUT

- name: Install dotnet SDKs
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x

- name: Dotnet Pack
shell: bash
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ jobs:
strategy:
fail-fast: false
matrix:
framework: [ net8.0, net9.0 ]
framework: [ net8.0, net9.0, net10.0 ]
test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement, Security, Diagnostics, Misc ]

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand All @@ -117,11 +117,12 @@ jobs:
password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }}

- name: Install dotnet SDKs
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x

- name: Run Tests
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFrameworks>net48;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net48;net8.0;net9.0;net10.0</TargetFrameworks>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<Nullable>enable</Nullable>
<NullableContextOptions>enable</NullableContextOptions>
Expand Down
8 changes: 7 additions & 1 deletion src/KurrentDB.Client/KurrentDB.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<PackageReference Include="Grpc.Net.Client" Version="2.67.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0"/>
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.0"/>
<PackageReference Include="System.Linq.Async" Version="6.0.1"/>
<PackageReference Include="OpenTelemetry.Api" Version="1.12.0"/>

<PackageReference Include="Grpc.StatusProto" Version="2.71.0" />
Expand All @@ -22,6 +21,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

<PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down Expand Up @@ -73,4 +74,9 @@
<ItemGroup>
<None Remove="KurrentDB.Client.csproj.DotSettings"/>
</ItemGroup>

<ItemGroup>
<Compile Remove="Core\Common\Shims\Index.cs" />
<Compile Remove="Core\Common\Shims\Range.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal static async Task<PersistentSubscription> Confirm(
.Messages
.GetAsyncEnumerator(cancellationToken);

var result = await enumerator.MoveNextAsync(cancellationToken).ConfigureAwait(false);
var result = await enumerator.MoveNextAsync().ConfigureAwait(false);

return (result, enumerator.Current) switch {
(true, PersistentSubscriptionMessage.SubscriptionConfirmation (var subscriptionId)) =>
Expand Down Expand Up @@ -118,7 +118,7 @@ private async Task Subscribe() {
_log.LogDebug("Persistent Subscription {subscriptionId} confirmed.", SubscriptionId);

try {
while (await _enumerator.MoveNextAsync(_cts.Token).ConfigureAwait(false)) {
while (await _enumerator.MoveNextAsync().ConfigureAwait(false)) {
if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, var retryCount)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// ReSharper disable once CheckNamespace
namespace KurrentDB.Client.Tests;

public static class AsyncEnumerableExtensions {
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ForEachAwaitAsync extension method lacks XML documentation comments. Public extension methods should include XML documentation that describes the method's purpose, parameters, return value, and any exceptions that may be thrown.

Suggested change
public static class AsyncEnumerableExtensions {
public static class AsyncEnumerableExtensions {
/// <summary>
/// Asynchronously enumerates the elements of the source sequence and invokes the specified asynchronous action on each element.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <param name="source">The asynchronous sequence to enumerate.</param>
/// <param name="action">An asynchronous delegate to invoke on each element.</param>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
/// <exception cref="OperationCanceledException">The operation was canceled.</exception>
/// <exception cref="Exception">Any exception thrown by the <paramref name="action"/> delegate.</exception>

Copilot uses AI. Check for mistakes.
public static async Task ForEachAwaitAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, Task> action, CancellationToken cancellationToken = default) {
await foreach (var element in source.WithCancellation(cancellationToken)) {
await action(element);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ public async Task connect_with_retries() {
// Act
var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root);
var retryCount = await subscription.Messages.OfType<PersistentSubscriptionMessage.Event>()
.SelectAwait(
async e => {
.Select(
async (PersistentSubscriptionMessage.Event e, CancellationToken _) => {
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lambda signature change from async e => to async (PersistentSubscriptionMessage.Event e, CancellationToken _) => indicates a breaking API change in the async LINQ library. However, since the replacement package System.Linq.AsyncEnumerable at version 10.0.0 does not exist, this change cannot work. You should verify the actual API requirements of the async LINQ library being used.

Suggested change
async (PersistentSubscriptionMessage.Event e, CancellationToken _) => {
async e => {

Copilot uses AI. Check for mistakes.
if (e.RetryCount > 4) {
await subscription.Ack(e.ResolvedEvent);
} else {
Expand Down Expand Up @@ -430,8 +430,8 @@ await Fixture.Subscriptions.CreateToAllAsync(
}

await subscription!.Messages.OfType<PersistentSubscriptionMessage.Event>()
.SelectAwait(
async e => {
.Select(
async (PersistentSubscriptionMessage.Event e, CancellationToken ct) => {
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lambda signature change from async e => to async (PersistentSubscriptionMessage.Event e, CancellationToken ct) => indicates a breaking API change in the async LINQ library. However, since the replacement package System.Linq.AsyncEnumerable at version 10.0.0 does not exist, this change cannot work. You should verify the actual API requirements of the async LINQ library being used.

Suggested change
async (PersistentSubscriptionMessage.Event e, CancellationToken ct) => {
async e => {

Copilot uses AI. Check for mistakes.
await subscription.Ack(e.ResolvedEvent);
return e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ await Fixture.Subscriptions.CreateToStreamAsync(
await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root);
await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events);
var retryCount = await subscription.Messages.OfType<PersistentSubscriptionMessage.Event>()
.SelectAwait(
async e => {
.Select(
async (PersistentSubscriptionMessage.Event e, CancellationToken _) => {
Comment on lines +341 to +342
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lambda signature change from async e => to async (PersistentSubscriptionMessage.Event e, CancellationToken _) => indicates a breaking API change in the async LINQ library. This suggests that .Select() now requires a different signature than .SelectAwait() did. However, since the replacement package System.Linq.AsyncEnumerable at version 10.0.0 does not exist, this change cannot work. You should verify the actual API requirements of the async LINQ library being used.

Suggested change
.Select(
async (PersistentSubscriptionMessage.Event e, CancellationToken _) => {
.SelectAwait(
async e => {

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong suggestion, the API conforms to the System.Linq.AsyncEnumerable API

if (e.RetryCount > 4) {
await subscription.Ack(e.ResolvedEvent);
} else {
Expand Down