Skip to content

Commit 4768078

Browse files
KirillKurdyukovLiamHamsters
authored andcommitted
fixed unhandled HttpIOException & delete legacy exceptions (ydb-platform#474)
- Fixed bug `Reader`: unhandled exception in `TryReadRequestBytes(long bytes)`. - Handle `YdbException` on `DeleteSession`. - Do not invoke `DeleteSession` if the session is not active. - `YdbException`: Added cancellation token propagation support in `CommitAsync` and `RollbackAsync`. - Deleted legacy exceptions: Driver.TransportException, StatusUnsuccessfulException and InitializationFailureException. - Fixed bug: Unhandled exception System.Net.Http.HttpIOException has now been converted to YdbException ([grpc-dotnet issue](grpc/grpc-dotnet#2638)).
1 parent 6013dee commit 4768078

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+715
-704
lines changed

src/Ydb.Sdk/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
- Added 'x-ydb-client-pid' header to any RPC calls
1+
- Fixed bug `Reader`: unhandled exception in `TryReadRequestBytes(long bytes)`.
2+
- Handle `YdbException` on `DeleteSession`.
3+
- Do not invoke `DeleteSession` if the session is not active.
4+
- `YdbException`: Added cancellation token propagation support in `CommitAsync` and `RollbackAsync`.
5+
- Deleted legacy exceptions: Driver.TransportException, StatusUnsuccessfulException and InitializationFailureException.
6+
- Fixed bug: Unhandled exception System.Net.Http.HttpIOException has now been converted to YdbException ([grpc-dotnet issue](https://github.com/grpc/grpc-dotnet/issues/2638)).
7+
- Added 'x-ydb-client-pid' header to any RPC calls.
28
- Added DisableServerBalancer option to ADO.NET session creation; default false.
39

410
## v0.20.1
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Text;
2+
using Ydb.Issue;
3+
4+
namespace Ydb.Sdk.Ado.Internal;
5+
6+
internal static class IssueMessageUtils
7+
{
8+
internal static string IssuesToString(this IReadOnlyList<IssueMessage> issues) => IssuesToString(issues, 0, 4);
9+
10+
private static string IssuesToString(IEnumerable<IssueMessage> issueMessages, int currentIndent, int indent) =>
11+
string.Join(Environment.NewLine, issueMessages.Select(message =>
12+
{
13+
var sb = new StringBuilder();
14+
sb.Append(' ', currentIndent);
15+
sb.Append($"[{message.IssueCode}] ");
16+
17+
if (message.Position != null)
18+
{
19+
sb.Append(message.Position.PositionToString());
20+
}
21+
22+
sb.Append($"{message.Severity.SeverityToString()}: ");
23+
sb.Append(message.Message);
24+
25+
if (message.Issues.Count > 0)
26+
{
27+
sb.AppendLine();
28+
sb.Append(IssuesToString(message.Issues, currentIndent + indent, indent));
29+
}
30+
31+
return sb.ToString();
32+
}));
33+
34+
private static string SeverityToString(this uint severity) => severity switch
35+
{
36+
0 => "Fatal",
37+
1 => "Error",
38+
2 => "Warning",
39+
3 => "Info",
40+
_ => $"Unknown SeverityCode {severity}"
41+
};
42+
43+
private static string PositionToString(this IssueMessage.Types.Position position)
44+
{
45+
var sb = new StringBuilder();
46+
sb.Append('(');
47+
48+
if (!string.IsNullOrEmpty(position.File))
49+
{
50+
sb.Append(position.File);
51+
sb.Append(':');
52+
}
53+
54+
sb.Append($"{position.Row}:{position.Column}");
55+
sb.Append(") ");
56+
return sb.ToString();
57+
}
58+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Ydb.Issue;
2+
3+
namespace Ydb.Sdk.Ado.Internal;
4+
5+
public static class StatusCodeUtils
6+
{
7+
internal static StatusCode Code(this Grpc.Core.Status rpcStatus) => rpcStatus.StatusCode switch
8+
{
9+
Grpc.Core.StatusCode.Unavailable => StatusCode.ClientTransportUnavailable,
10+
Grpc.Core.StatusCode.DeadlineExceeded => StatusCode.ClientTransportTimeout,
11+
Grpc.Core.StatusCode.ResourceExhausted => StatusCode.ClientTransportResourceExhausted,
12+
Grpc.Core.StatusCode.Unimplemented => StatusCode.ClientTransportUnimplemented,
13+
Grpc.Core.StatusCode.Cancelled => StatusCode.Cancelled,
14+
_ => StatusCode.ClientTransportUnknown
15+
};
16+
17+
internal static StatusCode Code(this StatusIds.Types.StatusCode statusCode) =>
18+
Enum.IsDefined(typeof(StatusCode), (int)statusCode) ? (StatusCode)statusCode : StatusCode.Unavailable;
19+
20+
internal static bool IsNotSuccess(this StatusIds.Types.StatusCode code) =>
21+
code != StatusIds.Types.StatusCode.Success;
22+
23+
internal static string ToMessage(this StatusCode statusCode, IReadOnlyList<IssueMessage> issueMessages) =>
24+
issueMessages.Count == 0
25+
? $"Status: {statusCode}"
26+
: $"Status: {statusCode}, Issues:{Environment.NewLine}{issueMessages.IssuesToString()}";
27+
}

src/Ydb.Sdk/src/Ado/YdbCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBeha
219219
var ydbDataReader = await YdbDataReader.CreateYdbDataReader(
220220
await YdbConnection.Session
221221
.ExecuteQuery(preparedSql.ToString(), ydbParameters, execSettings, transaction?.TransactionControl),
222-
YdbConnection.OnStatus, transaction, cancellationToken
222+
YdbConnection.OnNotSuccessStatusCode, transaction, cancellationToken
223223
);
224224

225225
YdbConnection.LastReader = ydbDataReader;

src/Ydb.Sdk/src/Ado/YdbConnection.cs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,24 +125,7 @@ public override async Task OpenAsync(CancellationToken cancellationToken)
125125
{
126126
ThrowIfConnectionOpen();
127127

128-
try
129-
{
130-
Session = await PoolManager.GetSession(ConnectionStringBuilder, cancellationToken);
131-
}
132-
catch (Exception e)
133-
{
134-
throw e switch
135-
{
136-
OperationCanceledException => throw new YdbException(StatusCode.Cancelled,
137-
$"The connection pool has been exhausted, either raise 'MaxSessionPool' " +
138-
$"(currently {ConnectionStringBuilder.MaxSessionPool}) or 'CreateSessionTimeout' " +
139-
$"(currently {ConnectionStringBuilder.CreateSessionTimeout} seconds) in your connection string.", e
140-
),
141-
Driver.TransportException transportException => new YdbException(transportException),
142-
StatusUnsuccessfulException unsuccessfulException => new YdbException(unsuccessfulException.Status),
143-
_ => e
144-
};
145-
}
128+
Session = await PoolManager.GetSession(ConnectionStringBuilder, cancellationToken);
146129

147130
OnStateChange(ClosedToOpenEventArgs);
148131

@@ -198,9 +181,9 @@ public override string ConnectionString
198181

199182
private ConnectionState ConnectionState { get; set; } = ConnectionState.Closed; // Invoke AsyncOpen()
200183

201-
internal void OnStatus(Status status)
184+
internal void OnNotSuccessStatusCode(StatusCode code)
202185
{
203-
_session.OnStatus(status);
186+
_session.OnNotSuccessStatusCode(code);
204187

205188
if (!_session.IsActive)
206189
{

src/Ydb.Sdk/src/Ado/YdbDataReader.cs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Google.Protobuf.Collections;
33
using Ydb.Issue;
44
using Ydb.Query;
5+
using Ydb.Sdk.Ado.Internal;
56
using Ydb.Sdk.Value;
67

78
namespace Ydb.Sdk.Ado;
@@ -11,7 +12,7 @@ public sealed class YdbDataReader : DbDataReader, IAsyncEnumerable<YdbDataRecord
1112
private readonly IServerStream<ExecuteQueryResponsePart> _stream;
1213
private readonly YdbTransaction? _ydbTransaction;
1314
private readonly RepeatedField<IssueMessage> _issueMessagesInStream = new();
14-
private readonly Action<Status> _onNotSuccessStatus;
15+
private readonly Action<StatusCode> _onNotSuccessStatusCode;
1516

1617
private int _currentRowIndex = -1;
1718
private long _resultSetIndex = -1;
@@ -54,22 +55,22 @@ private enum State
5455

5556
private YdbDataReader(
5657
IServerStream<ExecuteQueryResponsePart> resultSetStream,
57-
Action<Status> onNotSuccessStatus,
58+
Action<StatusCode> onNotSuccessStatusCode,
5859
YdbTransaction? ydbTransaction)
5960
{
6061
_stream = resultSetStream;
61-
_onNotSuccessStatus = onNotSuccessStatus;
62+
_onNotSuccessStatusCode = onNotSuccessStatusCode;
6263
_ydbTransaction = ydbTransaction;
6364
}
6465

6566
internal static async Task<YdbDataReader> CreateYdbDataReader(
6667
IServerStream<ExecuteQueryResponsePart> resultSetStream,
67-
Action<Status> onStatus,
68+
Action<StatusCode> onNotSuccessStatusCode,
6869
YdbTransaction? ydbTransaction = null,
6970
CancellationToken cancellationToken = default
7071
)
7172
{
72-
var ydbDataReader = new YdbDataReader(resultSetStream, onStatus, ydbTransaction);
73+
var ydbDataReader = new YdbDataReader(resultSetStream, onNotSuccessStatusCode, ydbTransaction);
7374
await ydbDataReader.Init(cancellationToken);
7475

7576
return ydbDataReader;
@@ -522,7 +523,7 @@ public override async Task CloseAsync()
522523
return;
523524
}
524525

525-
_onNotSuccessStatus(new Status(StatusCode.SessionBusy));
526+
_onNotSuccessStatusCode(StatusCode.SessionBusy);
526527
_stream.Dispose();
527528

528529
if (_ydbTransaction != null)
@@ -559,20 +560,14 @@ private async ValueTask<State> NextExecPart(CancellationToken cancellationToken)
559560

560561
_issueMessagesInStream.AddRange(part.Issues);
561562

562-
if (part.Status != StatusIds.Types.StatusCode.Success)
563+
if (part.Status.IsNotSuccess())
563564
{
564-
OnFailReadStream();
565-
566565
while (await _stream.MoveNextAsync(cancellationToken))
567566
{
568567
_issueMessagesInStream.AddRange(_stream.Current.Issues);
569568
}
570569

571-
var status = Status.FromProto(part.Status, _issueMessagesInStream);
572-
573-
_onNotSuccessStatus(status);
574-
575-
throw new YdbException(status);
570+
throw YdbException.FromServer(part.Status, _issueMessagesInStream);
576571
}
577572

578573
_currentResultSet = part.ResultSet?.FromProto();
@@ -592,13 +587,13 @@ private async ValueTask<State> NextExecPart(CancellationToken cancellationToken)
592587

593588
return State.NewResultSet;
594589
}
595-
catch (Driver.TransportException e)
590+
catch (YdbException e)
596591
{
597592
OnFailReadStream();
598593

599-
_onNotSuccessStatus(e.Status);
594+
_onNotSuccessStatusCode(e.Code);
600595

601-
throw new YdbException(e);
596+
throw;
602597
}
603598
}
604599

src/Ydb.Sdk/src/Ado/YdbException.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using System.Data.Common;
2+
using Grpc.Core;
3+
using Ydb.Issue;
4+
using Ydb.Sdk.Ado.Internal;
25

36
namespace Ydb.Sdk.Ado;
47

@@ -8,14 +11,17 @@ internal YdbException(string message) : base(message)
811
{
912
}
1013

11-
internal YdbException(Driver.TransportException transportException)
12-
: this(transportException.Status, transportException)
14+
internal YdbException(RpcException e) : this(e.Status.Code(), "Transport RPC call error", e)
1315
{
1416
}
1517

16-
internal YdbException(Status status, Exception? innerException = null)
17-
: this(status.StatusCode, status.ToString(), innerException)
18+
internal static YdbException FromServer(StatusIds.Types.StatusCode statusCode, IReadOnlyList<IssueMessage> issues)
1819
{
20+
var code = statusCode.Code();
21+
22+
var message = code.ToMessage(issues);
23+
24+
return new YdbException(code, message);
1925
}
2026

2127
internal YdbException(StatusCode statusCode, string message, Exception? innerException = null)

src/Ydb.Sdk/src/Ado/YdbSchema.cs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using Ydb.Scheme.V1;
66
using Ydb.Sdk.Ado.Schema;
77
using Ydb.Sdk.Services.Table;
8-
using Ydb.Table;
98

109
namespace Ydb.Sdk.Ado;
1110

@@ -63,24 +62,13 @@ public static async Task<YdbTable> DescribeTable(
6362
var describeResponse = await ydbConnection.Session
6463
.DescribeTable(WithSuffix(ydbConnection.Database) + tableName, describeTableSettings);
6564

66-
var status = Status.FromProto(describeResponse.Operation.Status, describeResponse.Operation.Issues);
67-
68-
if (status.IsNotSuccess)
69-
{
70-
ydbConnection.OnStatus(status);
71-
72-
throw new YdbException(status);
73-
}
74-
75-
var describeRes = describeResponse.Operation.Result.Unpack<DescribeTableResult>();
76-
77-
return new YdbTable(tableName, describeRes);
65+
return new YdbTable(tableName, describeResponse);
7866
}
79-
catch (Driver.TransportException e)
67+
catch (YdbException e)
8068
{
81-
ydbConnection.OnStatus(e.Status);
69+
ydbConnection.OnNotSuccessStatusCode(e.Code);
8270

83-
throw new YdbException(e);
71+
throw;
8472
}
8573
}
8674

@@ -253,19 +241,31 @@ private static async Task AppendDescribeTable(
253241
string? tableType,
254242
Action<YdbTable, string> appendInTable)
255243
{
256-
var ydbTable = await DescribeTable(ydbConnection, tableName, describeTableSettings);
257-
var type = ydbTable.IsSystem
258-
? "SYSTEM_TABLE"
259-
: ydbTable.Type switch
244+
try
245+
{
246+
var describeResponse = await ydbConnection.Session
247+
.DescribeTable(WithSuffix(ydbConnection.Database) + tableName, describeTableSettings);
248+
var ydbTable = new YdbTable(tableName, describeResponse);
249+
250+
var type = ydbTable.IsSystem
251+
? "SYSTEM_TABLE"
252+
: ydbTable.Type switch
253+
{
254+
YdbTable.TableType.Table => "TABLE",
255+
YdbTable.TableType.ColumnTable => "COLUMN_TABLE",
256+
YdbTable.TableType.ExternalTable => "EXTERNAL_TABLE",
257+
_ => throw new ArgumentOutOfRangeException(nameof(tableType))
258+
};
259+
if (type.IsPattern(tableType))
260260
{
261-
YdbTable.TableType.Table => "TABLE",
262-
YdbTable.TableType.ColumnTable => "COLUMN_TABLE",
263-
YdbTable.TableType.ExternalTable => "EXTERNAL_TABLE",
264-
_ => throw new ArgumentOutOfRangeException(nameof(tableType))
265-
};
266-
if (type.IsPattern(tableType))
261+
appendInTable(ydbTable, type);
262+
}
263+
}
264+
catch (YdbException e)
267265
{
268-
appendInTable(ydbTable, type);
266+
ydbConnection.OnNotSuccessStatusCode(e.Code);
267+
268+
throw;
269269
}
270270
}
271271

@@ -417,7 +417,7 @@ CancellationToken cancellationToken
417417

418418
if (status.IsNotSuccess)
419419
{
420-
throw new YdbException(status);
420+
throw YdbException.FromServer(operation.Status, operation.Issues);
421421
}
422422

423423
foreach (var entry in operation.Result.Unpack<ListDirectoryResult>().Children)
@@ -461,9 +461,11 @@ await SchemaObjects(
461461

462462
return ydbSchemaObjects;
463463
}
464-
catch (Driver.TransportException e)
464+
catch (YdbException e)
465465
{
466-
throw new YdbException(e);
466+
ydbConnection.OnNotSuccessStatusCode(e.Code);
467+
468+
throw;
467469
}
468470
}
469471

0 commit comments

Comments
 (0)