Skip to content

Commit 50ec58a

Browse files
Add more app lock statements (#463)
1 parent 600a3ee commit 50ec58a

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/Telemetry/Telemetry.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ public enum TelemetryErrorName
408408
{
409409
ConsumeChangesLoop,
410410
Convert,
411+
CreateGlobalStateTable,
412+
CreateLeasesTable,
411413
CreateSchema,
412414
FlushAsync,
413415
GetCaseSensitivity,

src/TriggerBinding/SqlTriggerListener.cs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ FROM sys.columns AS c
346346
private async Task<long> CreateSchemaAsync(SqlConnection connection, SqlTransaction transaction, CancellationToken cancellationToken)
347347
{
348348
string createSchemaQuery = $@"
349+
{AppLockStatements}
350+
349351
IF SCHEMA_ID(N'{SchemaName}') IS NULL
350352
EXEC ('CREATE SCHEMA {SchemaName}');
351353
";
@@ -393,6 +395,8 @@ IF SCHEMA_ID(N'{SchemaName}') IS NULL
393395
private async Task<long> CreateGlobalStateTableAsync(SqlConnection connection, SqlTransaction transaction, CancellationToken cancellationToken)
394396
{
395397
string createGlobalStateTableQuery = $@"
398+
{AppLockStatements}
399+
396400
IF OBJECT_ID(N'{GlobalStateTableName}', 'U') IS NULL
397401
CREATE TABLE {GlobalStateTableName} (
398402
UserFunctionID char(16) NOT NULL,
@@ -406,7 +410,27 @@ PRIMARY KEY (UserFunctionID, UserTableID)
406410
using (var createGlobalStateTableCommand = new SqlCommand(createGlobalStateTableQuery, connection, transaction))
407411
{
408412
var stopwatch = Stopwatch.StartNew();
409-
await createGlobalStateTableCommand.ExecuteNonQueryAsync(cancellationToken);
413+
try
414+
{
415+
await createGlobalStateTableCommand.ExecuteNonQueryAsync(cancellationToken);
416+
}
417+
catch (Exception ex)
418+
{
419+
TelemetryInstance.TrackException(TelemetryErrorName.CreateGlobalStateTable, ex, this._telemetryProps);
420+
var sqlEx = ex as SqlException;
421+
if (sqlEx?.Number == 2714)
422+
{
423+
// Error 2714 is for an object of that name already existing in the database. This generally shouldn't happen
424+
// since we check for its existence in the statement but occasionally a race condition can make it so
425+
// that multiple instances will try and create the table at once. In that case we can just ignore the
426+
// error since all we care about is that the table exists at all.
427+
this._logger.LogWarning($"Failed to create global state table '{GlobalStateTableName}'. Exception message: {ex.Message} This is informational only, function startup will continue as normal.");
428+
}
429+
else
430+
{
431+
throw;
432+
}
433+
}
410434
long durationMs = stopwatch.ElapsedMilliseconds;
411435
this._logger.LogDebugWithThreadId($"END CreateGlobalStateTable Duration={durationMs}ms");
412436
return durationMs;
@@ -446,6 +470,8 @@ private async Task<long> InsertGlobalStateTableRowAsync(SqlConnection connection
446470
this._logger.LogDebugWithThreadId($"END GetMinValidVersion MinValidVersion={minValidVersion}");
447471

448472
string insertRowGlobalStateTableQuery = $@"
473+
{AppLockStatements}
474+
449475
IF NOT EXISTS (
450476
SELECT * FROM {GlobalStateTableName}
451477
WHERE UserFunctionID = '{this._userFunctionId}' AND UserTableID = {userTableId}
@@ -486,6 +512,8 @@ private async Task<long> CreateLeasesTableAsync(
486512
string primaryKeys = string.Join(", ", primaryKeyColumns.Select(col => col.name.AsBracketQuotedString()));
487513

488514
string createLeasesTableQuery = $@"
515+
{AppLockStatements}
516+
489517
IF OBJECT_ID(N'{leasesTableName}', 'U') IS NULL
490518
CREATE TABLE {leasesTableName} (
491519
{primaryKeysWithTypes},
@@ -500,7 +528,27 @@ PRIMARY KEY ({primaryKeys})
500528
using (var createLeasesTableCommand = new SqlCommand(createLeasesTableQuery, connection, transaction))
501529
{
502530
var stopwatch = Stopwatch.StartNew();
503-
await createLeasesTableCommand.ExecuteNonQueryAsync(cancellationToken);
531+
try
532+
{
533+
await createLeasesTableCommand.ExecuteNonQueryAsync(cancellationToken);
534+
}
535+
catch (Exception ex)
536+
{
537+
TelemetryInstance.TrackException(TelemetryErrorName.CreateLeasesTable, ex, this._telemetryProps);
538+
var sqlEx = ex as SqlException;
539+
if (sqlEx?.Number == 2714)
540+
{
541+
// Error 2714 is for an object of that name already existing in the database. This generally shouldn't happen
542+
// since we check for its existence in the statement but occasionally a race condition can make it so
543+
// that multiple instances will try and create the table at once. In that case we can just ignore the
544+
// error since all we care about is that the table exists at all.
545+
this._logger.LogWarning($"Failed to create global state table '{leasesTableName}'. Exception message: {ex.Message} This is informational only, function startup will continue as normal.");
546+
}
547+
else
548+
{
549+
throw;
550+
}
551+
}
504552
long durationMs = stopwatch.ElapsedMilliseconds;
505553
this._logger.LogDebugWithThreadId($"END CreateLeasesTable Duration={durationMs}ms");
506554
return durationMs;

0 commit comments

Comments
 (0)