Skip to content

Commit ac24245

Browse files
committed
Merge branch 'main' into queryService
# Conflicts: # examples/src/BasicExample/FillData.cs # src/Ydb.Sdk/src/Services/Table/Session.cs # src/Ydb.Sdk/src/Services/Table/SessionPool.cs
2 parents e03800a + 5f82083 commit ac24245

File tree

7 files changed

+140
-17
lines changed

7 files changed

+140
-17
lines changed

.github/workflows/lint.yml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ on:
88

99
jobs:
1010
autoformatter:
11+
strategy:
12+
matrix:
13+
source-dir: ["./src/", "./examples/src/"]
14+
include:
15+
- source-dir: "./src/"
16+
solutionFile: "YdbSdk.sln"
17+
- source-dir: "./examples/src/"
18+
solutionFile: "YdbExamples.sln"
1119
name: autoformat check
12-
concurrency:
13-
group: lint-autoformat-${{ github.ref }}
14-
cancel-in-progress: true
1520
runs-on: ubuntu-latest
1621
steps:
1722
- name: Checkout
@@ -21,15 +26,18 @@ jobs:
2126
with:
2227
dotnet-version: '6.0.x'
2328
- name: Restore
24-
run: dotnet restore ./src/YdbSdk.sln
29+
run: dotnet restore ${{ matrix.source-dir }}${{ matrix.solutionFile }}
2530
- name: Install ReSharper
2631
run: dotnet tool install -g JetBrains.ReSharper.GlobalTools --version 2023.2.1
2732
- name: format all files with auto-formatter
28-
run: bash ./.github/scripts/format-all-dotnet-code.sh ./src/ YdbSdk.sln "Custom Cleanup"
33+
run: bash ./.github/scripts/format-all-dotnet-code.sh ${{ matrix.source-dir }} ${{ matrix.solutionFile }} "Custom Cleanup"
2934
- name: Check repository diff
3035
run: bash ./.github/scripts/check-work-copy-equals-to-committed.sh "auto-format broken"
3136

3237
inspection:
38+
strategy:
39+
matrix:
40+
solutionPath: ["./src/YdbSdk.sln", "./examples/src/YdbExamples.sln"]
3341
runs-on: ubuntu-latest
3442
name: Inspection
3543
steps:
@@ -40,11 +48,11 @@ jobs:
4048
with:
4149
dotnet-version: '6.0.x'
4250
- name: Restore
43-
run: dotnet restore ./src/YdbSdk.sln
51+
run: dotnet restore ${{ matrix.solutionPath }}
4452
- name: Inspect code
4553
uses: muno92/resharper_inspectcode@v1
4654
with:
47-
solutionPath: ./src/YdbSdk.sln
55+
solutionPath: ${{ matrix.solutionPath }}
4856
version: 2023.2.1
4957
include: |
5058
**.cs

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v0.1.5
2+
- Fix timeout error on create session
3+
- Fix transport error on delete session
4+
15
## v0.1.4
26
- Add exception throwing when results truncated
37
- lint: add line feed at file end

src/Ydb.Sdk/src/Driver.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,19 @@ internal async Task<UnaryResponse<TResponse>> UnaryCall<TRequest, TResponse>(
117117

118118
try
119119
{
120-
var data = await callInvoker.AsyncUnaryCall(
120+
using var call = callInvoker.AsyncUnaryCall(
121121
method: method,
122122
host: null,
123123
options: GetCallOptions(settings, false),
124124
request: request);
125125

126+
var data = await call.ResponseAsync;
127+
var trailers = call.GetTrailers();
128+
126129
return new UnaryResponse<TResponse>(
127130
data: data,
128-
usedEndpoint: endpoint);
131+
usedEndpoint: endpoint,
132+
trailers: trailers);
129133
}
130134
catch (RpcException e)
131135
{
@@ -312,17 +316,20 @@ private static Status ConvertStatus(Grpc.Core.Status rpcStatus)
312316

313317
internal sealed class UnaryResponse<TResponse>
314318
{
315-
internal UnaryResponse(
316-
TResponse data,
317-
string usedEndpoint)
319+
internal UnaryResponse(TResponse data,
320+
string usedEndpoint,
321+
Grpc.Core.Metadata? trailers)
318322
{
319323
Data = data;
320324
UsedEndpoint = usedEndpoint;
325+
Trailers = trailers;
321326
}
322327

323328
public TResponse Data { get; }
324329

325330
public string UsedEndpoint { get; }
331+
332+
public Grpc.Core.Metadata? Trailers { get; }
326333
}
327334

328335
internal sealed class StreamIterator<TResponse>

src/Ydb.Sdk/src/Metadata.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@ internal static class Metadata
77
public const string RpcRequestTypeHeader = "x-ydb-request-type";
88
public const string RpcTraceIdHeader = "x-ydb-trace-id";
99
public const string RpcSdkInfoHeader = "x-ydb-sdk-build-info";
10+
public const string RpcServerHintsHeader = "x-ydb-server-hints";
11+
12+
public const string GracefulShutdownHint = "session-close";
1013
}

src/Ydb.Sdk/src/Services/Table/Session.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,22 @@ private void OnResponseStatus(Status status)
2323
}
2424
}
2525

26+
private void OnResponseTrailers(Grpc.Core.Metadata? trailers)
27+
{
28+
if (trailers is null)
29+
{
30+
return;
31+
}
32+
33+
foreach (var hint in trailers.GetAll(Metadata.RpcServerHintsHeader))
34+
{
35+
if (hint.Value == Metadata.GracefulShutdownHint)
36+
{
37+
_sessionPool?.InvalidateSession(Id);
38+
}
39+
}
40+
}
41+
2642

2743
protected override void Dispose(bool disposing)
2844
{
@@ -37,11 +53,12 @@ protected override void Dispose(bool disposing)
3753
{
3854
Logger.LogTrace($"Closing detached session on dispose: {Id}");
3955

40-
var client = new TableClient(Driver, new NoPool<Session>());
41-
_ = client.DeleteSession(Id, new DeleteSessionSettings
56+
var client = new TableClient(Driver, new NoPool());
57+
var task = client.DeleteSession(Id, new DeleteSessionSettings
4258
{
4359
TransportTimeout = DeleteSessionTimeout
4460
});
61+
task.Wait();
4562
}
4663
else
4764
{
@@ -52,18 +69,20 @@ protected override void Dispose(bool disposing)
5269
Disposed = true;
5370
}
5471

55-
internal Task<Driver.UnaryResponse<TResponse>> UnaryCall<TRequest, TResponse>(
72+
internal async Task<Driver.UnaryResponse<TResponse>> UnaryCall<TRequest, TResponse>(
5673
Method<TRequest, TResponse> method,
5774
TRequest request,
5875
RequestSettings settings)
5976
where TRequest : class
6077
where TResponse : class
6178
{
62-
return Driver.UnaryCall(
79+
var response = await Driver.UnaryCall(
6380
method: method,
6481
request: request,
6582
settings: settings,
6683
preferredEndpoint: Endpoint
6784
);
85+
OnResponseTrailers(response.Trailers);
86+
return response;
6887
}
6988
}

src/Ydb.Sdk/src/Version.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ public static class Verison
44
{
55
public const uint Major = 0;
66
public const uint Minor = 1;
7-
public const uint Patch = 4;
7+
public const uint Patch = 5;
88
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using Microsoft.Extensions.Logging;
2+
using Microsoft.Extensions.Logging.Abstractions;
3+
using Xunit;
4+
using Ydb.Sdk.Services.Table;
5+
6+
namespace Ydb.Sdk.Tests.Table;
7+
8+
[Trait("Category", "Integration")]
9+
public class TestGracefulShutdown
10+
{
11+
private readonly ILoggerFactory _loggerFactory;
12+
13+
private readonly DriverConfig _driverConfig = new(
14+
endpoint: "grpc://localhost:2136",
15+
database: "/local"
16+
);
17+
18+
private const string ShutdownUrl = "http://localhost:8765/actors/kqp_proxy?force_shutdown=all";
19+
20+
public TestGracefulShutdown()
21+
{
22+
_loggerFactory = Utils.GetLoggerFactory() ?? NullLoggerFactory.Instance;
23+
}
24+
25+
[Fact]
26+
public async Task Test()
27+
{
28+
await using var driver = await Driver.CreateInitialized(_driverConfig, _loggerFactory);
29+
using var tableClient = new TableClient(driver);
30+
31+
32+
var session1 = "";
33+
await tableClient.SessionExec(
34+
async session =>
35+
{
36+
session1 = session.Id;
37+
return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit());
38+
}
39+
);
40+
41+
var session2 = "";
42+
await tableClient.SessionExec(
43+
async session =>
44+
{
45+
session2 = session.Id;
46+
return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit());
47+
}
48+
);
49+
50+
// control check
51+
Assert.NotEqual("", session1);
52+
Assert.Equal(session1, session2);
53+
54+
// SHUTDOWN
55+
using var httpClient = new HttpClient();
56+
await httpClient.GetAsync(ShutdownUrl);
57+
58+
// new session
59+
var session3 = "";
60+
await tableClient.SessionExec(
61+
async session =>
62+
{
63+
session3 = session.Id;
64+
return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit());
65+
}
66+
);
67+
68+
Assert.Equal(session2, session3);
69+
70+
var session4 = "";
71+
await tableClient.SessionExec(
72+
async session =>
73+
{
74+
session4 = session.Id;
75+
return await session.ExecuteDataQuery("SELECT 1", TxControl.BeginSerializableRW().Commit());
76+
}
77+
);
78+
79+
Assert.NotEqual("", session3);
80+
Assert.NotEqual(session3, session4);
81+
}
82+
}

0 commit comments

Comments
 (0)