Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 1b01837

Browse files
authored
Increase statistics database command timeout (#125)
1 parent d27fbae commit 1b01837

7 files changed

Lines changed: 36 additions & 24 deletions

File tree

src/Gallery.CredentialExpiration/Job.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace Gallery.CredentialExpiration
2020
{
2121
public class Job : JobBase
2222
{
23-
private const int DefaultCommandTimeout = 1800; // 30 minutes max
23+
private readonly TimeSpan _defaultCommandTimeout = TimeSpan.FromMinutes(30);
2424

2525
private readonly ConcurrentDictionary<string, DateTimeOffset> _contactedUsers = new ConcurrentDictionary<string, DateTimeOffset>();
2626
private readonly string _cursorFile = "cursor.json";
@@ -65,7 +65,7 @@ public override bool Init(IDictionary<string, string> jobArgsDictionary)
6565
var smtpUri = new SmtpUri(new Uri(smtpConnectionString));
6666
_smtpClient = CreateSmtpClient(smtpUri);
6767

68-
_warnDaysBeforeExpiration = JobConfigurationManager.TryGetIntArgument(jobArgsDictionary, MyJobArgumentNames.WarnDaysBeforeExpiration)
68+
_warnDaysBeforeExpiration = JobConfigurationManager.TryGetIntArgument(jobArgsDictionary, MyJobArgumentNames.WarnDaysBeforeExpiration)
6969
?? _warnDaysBeforeExpiration;
7070

7171
_allowEmailResendAfterDays = JobConfigurationManager.TryGetIntArgument(jobArgsDictionary, MyJobArgumentNames.AllowEmailResendAfterDays)
@@ -113,7 +113,7 @@ public override async Task<bool> Run()
113113
expiredCredentials = (await galleryConnection.QueryWithRetryAsync<ExpiredCredentialData>(
114114
string.Format(Strings.GetExpiredCredentialsQuery, _warnDaysBeforeExpiration),
115115
maxRetries: 3,
116-
commandTimeout: DefaultCommandTimeout)).ToList();
116+
commandTimeout: _defaultCommandTimeout)).ToList();
117117

118118
_logger.LogInformation("Retrieved {ExpiredCredentials} expired credentials.",
119119
expiredCredentials.Count);
@@ -246,7 +246,7 @@ private static string BuildApiKeyExpiryMessage(string description, DateTimeOffse
246246
: string.Format(Strings.ApiKeyExpiring, description, (int)expiryInDays);
247247

248248
// \u2022 - Unicode for bullet point.
249-
return "\u2022 "+ message + Environment.NewLine;
249+
return "\u2022 " + message + Environment.NewLine;
250250
}
251251

252252
private SmtpClient CreateSmtpClient(SmtpUri smtpUri)

src/Gallery.Maintenance/DeleteExpiredVerificationKeysTask.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Data.SqlClient;
67
using System.Linq;
@@ -12,8 +13,8 @@ namespace Gallery.Maintenance
1213
{
1314
internal class DeleteExpiredVerificationKeysTask : IMaintenanceTask
1415
{
15-
private const int DefaultCommandTimeoutInSeconds = 300;
16-
16+
private readonly TimeSpan _commandTimeout = TimeSpan.FromMinutes(5);
17+
1718
private const string SelectQuery = @"
1819
SELECT s.[CredentialKey], c.[UserKey], u.[Username], c.[Expires], s.[Subject] as ScopeSubject
1920
FROM [dbo].[Credentials] c
@@ -34,7 +35,7 @@ public async Task<bool> RunAsync(Job job)
3435
{
3536
expiredKeys = await connection.QueryWithRetryAsync<PackageVerificationKey>(
3637
SelectQuery,
37-
commandTimeout: DefaultCommandTimeoutInSeconds,
38+
commandTimeout: _commandTimeout,
3839
maxRetries: 3);
3940
}
4041

@@ -58,13 +59,13 @@ public async Task<bool> RunAsync(Job job)
5859
{
5960
rowCount = await connection.ExecuteAsync(
6061
string.Format(DeleteQuery, string.Join(",", credentialKeys)),
61-
transaction, DefaultCommandTimeoutInSeconds);
62+
transaction, _commandTimeout);
6263

6364
transaction.Commit();
6465
}
6566
}
6667
}
67-
68+
6869
job.Logger.LogInformation("Deleted {0} expired verification keys and scopes. Expected={1}.", rowCount, expectedRowCount);
6970

7071
return rowCount == expectedRowCount;

src/NuGet.Jobs.Common/Extensions/DapperExtensions.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,22 @@ namespace System.Data.SqlClient
1010
{
1111
public static class DapperExtensions
1212
{
13-
public static Task<int> ExecuteAsync(this SqlConnection connection, string sql, SqlTransaction transaction = null, int timeout = 30)
13+
public static Task<int> ExecuteAsync(this SqlConnection connection, string sql, SqlTransaction transaction = null, TimeSpan? commandTimeout = null)
1414
{
1515
SqlCommand cmd = connection.CreateCommand();
1616
cmd.CommandText = sql;
1717
cmd.CommandType = CommandType.Text;
18-
cmd.CommandTimeout = timeout;
18+
19+
if (commandTimeout.HasValue)
20+
{
21+
cmd.CommandTimeout = (int)commandTimeout.Value.TotalSeconds;
22+
}
23+
1924
if (transaction != null)
2025
{
2126
cmd.Transaction = transaction;
2227
}
28+
2329
return cmd.ExecuteNonQueryAsync();
2430
}
2531

@@ -28,7 +34,7 @@ public static async Task<IEnumerable<T>> QueryWithRetryAsync<T>(
2834
string sql,
2935
object param = null,
3036
IDbTransaction transaction = null,
31-
int? commandTimeout = null,
37+
TimeSpan? commandTimeout = null,
3238
CommandType? commandType = null,
3339
int maxRetries = 10,
3440
Action onRetry = null)
@@ -37,7 +43,7 @@ public static async Task<IEnumerable<T>> QueryWithRetryAsync<T>(
3743
{
3844
try
3945
{
40-
return await connection.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType);
46+
return await connection.QueryAsync<T>(sql, param, transaction, (int?)commandTimeout?.TotalSeconds, commandType);
4147
}
4248
catch (SqlException ex)
4349
{
@@ -68,15 +74,16 @@ public static async Task<IEnumerable<T>> QueryWithRetryAsync<T>(
6874
}
6975
}
7076
}
77+
7178
throw new Exception("Unknown error! Should have thrown the final timeout!");
7279
}
73-
80+
7481
public static async Task<T> ExecuteScalarWithRetryAsync<T>(
7582
this SqlConnection connection,
7683
string sql,
7784
object param = null,
7885
IDbTransaction transaction = null,
79-
int? commandTimeout = null,
86+
TimeSpan? commandTimeout = null,
8087
CommandType? commandType = null,
8188
int maxRetries = 10,
8289
Action onRetry = null)
@@ -85,7 +92,7 @@ public static async Task<T> ExecuteScalarWithRetryAsync<T>(
8592
{
8693
try
8794
{
88-
return await connection.ExecuteScalarAsync<T>(sql, param, transaction, commandTimeout, commandType);
95+
return await connection.ExecuteScalarAsync<T>(sql, param, transaction, (int?)commandTimeout?.TotalSeconds, commandType);
8996
}
9097
catch (SqlException ex)
9198
{
@@ -116,7 +123,8 @@ public static async Task<T> ExecuteScalarWithRetryAsync<T>(
116123
}
117124
}
118125
}
126+
119127
throw new Exception("Unknown error! Should have thrown the final timeout!");
120128
}
121129
}
122-
}
130+
}

src/Stats.AggregateCdnDownloadsInGallery/Job.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ await statisticsDatabase.QueryWithRetryAsync<DownloadCountData>(
9696
_storedProcedureName,
9797
transaction: statisticsDatabaseTransaction,
9898
commandType: CommandType.StoredProcedure,
99-
commandTimeout: (int)TimeSpan.FromMinutes(15).TotalSeconds,
99+
commandTimeout: TimeSpan.FromMinutes(15),
100100
maxRetries: 3))
101101
.ToList();
102102
}
@@ -174,7 +174,7 @@ await statisticsDatabase.QueryWithRetryAsync<DownloadCountData>(
174174
_logger.LogDebug("Updating destination database Download Counts... ({RecordCount} package registrations to process).", packageRegistrationGroups.Count());
175175

176176
await destinationDatabase.ExecuteAsync(_updateFromTempTable,
177-
timeout: (int)TimeSpan.FromMinutes(30).TotalSeconds);
177+
commandTimeout: TimeSpan.FromMinutes(30));
178178

179179
_logger.LogInformation("Updated destination database Download Counts.");
180180
}
@@ -199,7 +199,7 @@ private async Task<IDictionary<string, string>> GetPackageRegistrations(SqlConne
199199
// Ensure results are sorted deterministically.
200200
var packageRegistrationData = (await sqlConnection.QueryWithRetryAsync<PackageRegistrationData>(
201201
"SELECT [Key], LOWER([Id]) AS LowercasedId, [Id] AS OriginalId FROM [dbo].[PackageRegistrations] (NOLOCK) ORDER BY [Id] ASC",
202-
commandTimeout: (int)TimeSpan.FromMinutes(10).TotalSeconds,
202+
commandTimeout: TimeSpan.FromMinutes(10),
203203
maxRetries: 5)).ToList();
204204

205205
// We are not using .ToDictionary() and instead explicitly looping through these items to be able to detect

src/Stats.CreateAzureCdnWarehouseReports/DownloadCountReport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class DownloadCountReport
1818
: ReportBase
1919
{
2020
private const string _storedProcedureName = "[dbo].[SelectTotalDownloadCountsPerPackageVersion]";
21-
private const int _defaultCommandTimeout = 1800; // 30 minutes max
21+
private readonly TimeSpan _defaultCommandTimeout = TimeSpan.FromMinutes(30);
2222
internal const string ReportName = "downloads.v1.json";
2323

2424
public DownloadCountReport(IEnumerable<StorageContainerTarget> targets, SqlConnectionStringBuilder statisticsDatabase, SqlConnectionStringBuilder galleryDatabase)

src/Stats.CreateAzureCdnWarehouseReports/DownloadsPerToolVersionReport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class DownloadsPerToolVersionReport
1818
: ReportBase
1919
{
2020
private const string _storedProcedureName = "[dbo].[SelectTotalDownloadCountsPerToolVersion]";
21-
private const int _defaultCommandTimeout = 1800; // 30 minutes max
21+
private readonly TimeSpan _defaultCommandTimeout = TimeSpan.FromMinutes(30);
2222
internal const string ReportName = "tools.v1.json";
2323

2424
public DownloadsPerToolVersionReport(CloudStorageAccount cloudStorageAccount, string statisticsContainerName, SqlConnectionStringBuilder statisticsDatabase, SqlConnectionStringBuilder galleryDatabase)

src/Stats.CreateAzureCdnWarehouseReports/GalleryTotalsReport.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class GalleryTotalsReport
2323
internal const string ReportName = "stats-totals.json";
2424

2525
public GalleryTotalsReport(CloudStorageAccount cloudStorageAccount, string statisticsContainerName, SqlConnectionStringBuilder statisticsDatabase, SqlConnectionStringBuilder galleryDatabase)
26-
: base(new [] { new StorageContainerTarget(cloudStorageAccount, statisticsContainerName) }, statisticsDatabase, galleryDatabase)
26+
: base(new[] { new StorageContainerTarget(cloudStorageAccount, statisticsContainerName) }, statisticsDatabase, galleryDatabase)
2727
{
2828
}
2929

@@ -47,7 +47,10 @@ public async Task Run()
4747
using (var transaction = connection.BeginTransaction(IsolationLevel.Snapshot))
4848
{
4949
totalsData.Downloads = (await connection.ExecuteScalarWithRetryAsync<long>(
50-
WarehouseStoredProcedureName, commandType: CommandType.StoredProcedure, transaction: transaction));
50+
WarehouseStoredProcedureName,
51+
commandType: CommandType.StoredProcedure,
52+
commandTimeout: TimeSpan.FromMinutes(5),
53+
transaction: transaction));
5154
}
5255
Trace.TraceInformation("Total downloads: {0}", totalsData.Downloads);
5356

0 commit comments

Comments
 (0)