Skip to content

Commit 8d9e2cc

Browse files
committed
Add async connection notifications
+ fix for Sql server notification fix
1 parent 3e35a07 commit 8d9e2cc

File tree

7 files changed

+208
-68
lines changed

7 files changed

+208
-68
lines changed

Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/DriverFactory.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2011-2020 Xtensive LLC.
1+
// Copyright (C) 2011-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Csaba Beer
@@ -152,16 +152,21 @@ private async ValueTask OpenConnectionWithNotifications(FbConnection connection,
152152
}
153153
}
154154
else {
155-
SqlHelper.NotifyConnectionOpening(handlers, connection);
155+
await SqlHelper.NotifyConnectionOpeningAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
156156
try {
157-
await connection.OpenAsync();
158-
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql))
159-
SqlHelper.NotifyConnectionInitializing(handlers, connection, configuration.ConnectionInitializationSql);
160-
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken);
161-
SqlHelper.NotifyConnectionOpened(handlers, connection);
157+
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
158+
159+
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql)) {
160+
await SqlHelper.NotifyConnectionInitializingAsync(handlers,
161+
connection, configuration.ConnectionInitializationSql, false, cancellationToken)
162+
.ConfigureAwait(false);
163+
}
164+
165+
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken).ConfigureAwait(false);
166+
await SqlHelper.NotifyConnectionOpenedAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
162167
}
163168
catch (Exception ex) {
164-
SqlHelper.NotifyConnectionOpeningFailed(handlers, connection, ex);
169+
await SqlHelper.NotifyConnectionOpeningFailedAsync(handlers, connection, ex, false, cancellationToken).ConfigureAwait(false);
165170
throw;
166171
}
167172
}

Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/DriverFactory.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2011-2020 Xtensive LLC.
1+
// Copyright (C) 2011-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Malisa Ncube
@@ -172,16 +172,21 @@ private async ValueTask OpenConnectionWithNotifications(MySqlConnection connecti
172172
}
173173
}
174174
else {
175-
SqlHelper.NotifyConnectionOpening(handlers, connection);
175+
await SqlHelper.NotifyConnectionOpeningAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
176176
try {
177-
await connection.OpenAsync();
178-
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql))
179-
SqlHelper.NotifyConnectionInitializing(handlers, connection, configuration.ConnectionInitializationSql);
180-
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken);
181-
SqlHelper.NotifyConnectionOpened(handlers, connection);
177+
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
178+
179+
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql)) {
180+
await SqlHelper.NotifyConnectionInitializingAsync(handlers,
181+
connection, configuration.ConnectionInitializationSql, false, cancellationToken)
182+
.ConfigureAwait(false);
183+
}
184+
185+
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken).ConfigureAwait(false);
186+
await SqlHelper.NotifyConnectionOpenedAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
182187
}
183188
catch (Exception ex) {
184-
SqlHelper.NotifyConnectionOpeningFailed(handlers, connection, ex);
189+
await SqlHelper.NotifyConnectionOpeningFailedAsync(handlers, connection, ex, false, cancellationToken).ConfigureAwait(false);
185190
throw;
186191
}
187192
}

Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/DriverFactory.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -165,16 +165,21 @@ private async ValueTask OpenConnectionWithNotifications(OracleConnection connect
165165
}
166166
}
167167
else {
168-
SqlHelper.NotifyConnectionOpening(handlers, connection);
168+
await SqlHelper.NotifyConnectionOpeningAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
169169
try {
170-
await connection.OpenAsync();
171-
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql))
172-
SqlHelper.NotifyConnectionInitializing(handlers, connection, configuration.ConnectionInitializationSql);
173-
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken);
174-
SqlHelper.NotifyConnectionOpened(handlers, connection);
170+
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
171+
172+
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql)) {
173+
await SqlHelper.NotifyConnectionInitializingAsync(handlers,
174+
connection, configuration.ConnectionInitializationSql, false, cancellationToken)
175+
.ConfigureAwait(false);
176+
}
177+
178+
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken).ConfigureAwait(false);
179+
await SqlHelper.NotifyConnectionOpenedAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
175180
}
176181
catch (Exception ex) {
177-
SqlHelper.NotifyConnectionOpeningFailed(handlers, connection, ex);
182+
await SqlHelper.NotifyConnectionOpeningFailedAsync(handlers, connection, ex, false, cancellationToken).ConfigureAwait(false);
178183
throw;
179184
}
180185
}

Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/DriverFactory.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -160,8 +160,10 @@ private async ValueTask OpenConnectionWithNotifications(NpgsqlConnection connect
160160
SqlHelper.NotifyConnectionOpening(handlers, connection);
161161
try {
162162
connection.Open();
163-
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql))
163+
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql)) {
164164
SqlHelper.NotifyConnectionInitializing(handlers, connection, configuration.ConnectionInitializationSql);
165+
}
166+
165167
SqlHelper.ExecuteInitializationSql(connection, configuration);
166168
SqlHelper.NotifyConnectionOpened(handlers, connection);
167169
}
@@ -171,16 +173,21 @@ private async ValueTask OpenConnectionWithNotifications(NpgsqlConnection connect
171173
}
172174
}
173175
else {
174-
SqlHelper.NotifyConnectionOpening(handlers, connection);
176+
await SqlHelper.NotifyConnectionOpeningAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
175177
try {
176-
await connection.OpenAsync();
177-
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql))
178-
SqlHelper.NotifyConnectionInitializing(handlers, connection, configuration.ConnectionInitializationSql);
179-
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken);
180-
SqlHelper.NotifyConnectionOpened(handlers, connection);
178+
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
179+
180+
if (!string.IsNullOrEmpty(configuration.ConnectionInitializationSql)) {
181+
await SqlHelper.NotifyConnectionInitializingAsync(handlers,
182+
connection, configuration.ConnectionInitializationSql, false, cancellationToken)
183+
.ConfigureAwait(false);
184+
}
185+
186+
await SqlHelper.ExecuteInitializationSqlAsync(connection, configuration, cancellationToken).ConfigureAwait(false);
187+
await SqlHelper.NotifyConnectionOpenedAsync(handlers, connection, false, cancellationToken).ConfigureAwait(false);
181188
}
182189
catch (Exception ex) {
183-
SqlHelper.NotifyConnectionOpeningFailed(handlers, connection, ex);
190+
await SqlHelper.NotifyConnectionOpeningFailedAsync(handlers, connection, ex, false, cancellationToken).ConfigureAwait(false);
184191
throw;
185192
}
186193
}

Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/Connection.cs

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2021 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -39,7 +39,13 @@ public override void Open()
3939
base.Open();
4040
}
4141
else {
42-
OpenWithCheckFast(DefaultCheckConnectionQuery);
42+
var connectionHandlers = Extensions.Get<ConnectionHandlersExtension>();
43+
if (connectionHandlers == null) {
44+
OpenWithCheckFast(DefaultCheckConnectionQuery);
45+
}
46+
else {
47+
OpenWithCheckAndNotifications(DefaultCheckConnectionQuery, connectionHandlers);
48+
}
4349
}
4450
}
4551

@@ -51,7 +57,13 @@ public override Task OpenAsync(CancellationToken cancellationToken)
5157
return base.OpenAsync(cancellationToken);
5258
}
5359

54-
return OpenWithCheckAsync(DefaultCheckConnectionQuery, cancellationToken);
60+
var connectionHandlers = Extensions.Get<ConnectionHandlersExtension>();
61+
if (connectionHandlers == null) {
62+
return OpenWithCheckFastAsync(DefaultCheckConnectionQuery, cancellationToken);
63+
}
64+
else {
65+
return OpenWithCheckAndNotificationsAsync(DefaultCheckConnectionQuery, connectionHandlers, cancellationToken);
66+
}
5567
}
5668

5769
/// <inheritdoc/>
@@ -66,10 +78,12 @@ public override void OpenAndInitialize(string initializationScript)
6678
? DefaultCheckConnectionQuery
6779
: initializationScript;
6880
var connectionHandlers = Extensions.Get<ConnectionHandlersExtension>();
69-
if (connectionHandlers == null)
81+
if (connectionHandlers == null) {
7082
OpenWithCheckFast(script);
71-
else
72-
OpenWithChecksAndNotifications(script, connectionHandlers);
83+
}
84+
else {
85+
OpenWithCheckAndNotifications(script, connectionHandlers);
86+
}
7387
}
7488

7589
/// <inheritdoc/>
@@ -82,7 +96,10 @@ public override Task OpenAndInitializeAsync(string initializationScript, Cancell
8296
var script = string.IsNullOrEmpty(initializationScript.Trim())
8397
? DefaultCheckConnectionQuery
8498
: initializationScript;
85-
return OpenWithCheckAsync(script, token);
99+
var connectionHandlers = Extensions.Get<ConnectionHandlersExtension>();
100+
return connectionHandlers == null
101+
? OpenWithCheckFastAsync(script, token)
102+
: OpenWithCheckAndNotificationsAsync(script, connectionHandlers, token);
86103
}
87104

88105
/// <inheritdoc/>
@@ -203,7 +220,7 @@ private void OpenWithCheckFast(string checkQueryString)
203220
var connectionChecked = false;
204221
var restoreTriggered = false;
205222
while (!connectionChecked) {
206-
base.Open();
223+
underlyingConnection.Open();
207224
try {
208225
using (var command = underlyingConnection.CreateCommand()) {
209226
command.CommandText = checkQueryString;
@@ -234,15 +251,14 @@ private void OpenWithCheckFast(string checkQueryString)
234251
}
235252
}
236253

237-
private void OpenWithChecksAndNotifications(string checkQueryString, ConnectionHandlersExtension connectionHandlers)
254+
private void OpenWithCheckAndNotifications(string checkQueryString, ConnectionHandlersExtension connectionHandlers)
238255
{
239256
var connectionChecked = false;
240257
var restoreTriggered = false;
241258
var handlers = connectionHandlers.Handlers;
242259
while (!connectionChecked) {
243260
SqlHelper.NotifyConnectionOpening(handlers, UnderlyingConnection, (!connectionChecked && !restoreTriggered));
244261
underlyingConnection.Open();
245-
//base.Open();
246262
try {
247263
SqlHelper.NotifyConnectionInitializing(handlers, UnderlyingConnection, checkQueryString, (!connectionChecked && !restoreTriggered));
248264
using (var command = underlyingConnection.CreateCommand()) {
@@ -276,24 +292,78 @@ private void OpenWithChecksAndNotifications(string checkQueryString, ConnectionH
276292
}
277293
}
278294

295+
private async Task OpenWithCheckFastAsync(string checkQueryString, CancellationToken cancellationToken)
296+
{
297+
var connectionChecked = false;
298+
var restoreTriggered = false;
299+
300+
while (!connectionChecked) {
301+
cancellationToken.ThrowIfCancellationRequested();
302+
await underlyingConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
303+
try {
304+
var command = underlyingConnection.CreateCommand();
305+
await using (command.ConfigureAwait(false)) {
306+
command.CommandText = checkQueryString;
307+
_ = await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
308+
}
309+
connectionChecked = true;
310+
}
311+
catch (Exception exception) {
312+
if (InternalHelpers.ShouldRetryOn(exception)) {
313+
if (restoreTriggered) {
314+
throw;
315+
}
316+
var newConnection = new SqlServerConnection(underlyingConnection.ConnectionString);
317+
try {
318+
underlyingConnection.Close();
319+
underlyingConnection.Dispose();
320+
}
321+
catch { }
322+
323+
underlyingConnection = newConnection;
324+
restoreTriggered = true;
325+
continue;
326+
}
327+
328+
throw;
329+
}
330+
}
331+
}
279332

280-
private async Task OpenWithCheckAsync(string checkQueryString, CancellationToken cancellationToken)
333+
private async Task OpenWithCheckAndNotificationsAsync(string checkQueryString,
334+
ConnectionHandlersExtension connectionHandlers, CancellationToken cancellationToken)
281335
{
282336
var connectionChecked = false;
283337
var restoreTriggered = false;
338+
var handlers = connectionHandlers.Handlers;
284339

285340
while (!connectionChecked) {
286341
cancellationToken.ThrowIfCancellationRequested();
287-
await base.OpenAsync(cancellationToken).ConfigureAwait(false);
342+
343+
await SqlHelper.NotifyConnectionOpeningAsync(handlers,
344+
UnderlyingConnection, (!connectionChecked && !restoreTriggered), cancellationToken)
345+
.ConfigureAwait(false);
346+
347+
await underlyingConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
288348
try {
349+
await SqlHelper.NotifyConnectionInitializingAsync(handlers,
350+
UnderlyingConnection, checkQueryString, (!connectionChecked && !restoreTriggered), cancellationToken)
351+
.ConfigureAwait(false);
352+
289353
var command = underlyingConnection.CreateCommand();
290354
await using (command.ConfigureAwait(false)) {
291355
command.CommandText = checkQueryString;
292356
_ = await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
293357
}
294358
connectionChecked = true;
359+
await SqlHelper.NotifyConnectionOpenedAsync(handlers, UnderlyingConnection, (!connectionChecked && !restoreTriggered), cancellationToken)
360+
.ConfigureAwait(false);
295361
}
296362
catch (Exception exception) {
363+
await SqlHelper.NotifyConnectionOpeningFailedAsync(handlers,
364+
UnderlyingConnection, exception, (!connectionChecked && !restoreTriggered), cancellationToken)
365+
.ConfigureAwait(false);
366+
297367
if (InternalHelpers.ShouldRetryOn(exception)) {
298368
if (restoreTriggered) {
299369
throw;

0 commit comments

Comments
 (0)