Skip to content

Commit 7843abe

Browse files
authored
Use Singleton Metrics Provider for Listener (#285)
* initial commit * update version * add nullable makr * udpate test * remove back to v1.5.1 * Fix typo in CHANGELOG.md entry * Update Directory.Packages.props * update scalemonitor and target scaler per functionid * update comments * update by comments: * add query metrics throttle * refactor code a little bit:
1 parent ce114d5 commit 7843abe

File tree

6 files changed

+33
-30
lines changed

6 files changed

+33
-30
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Changelog
22

3-
## v1.5.1 (Unreleased)
3+
## v1.5.1
44

55
### Updates
66

7+
* Use Singelton metrics provider instead of IScaleMonitor and ITargetScaler ([#285]https://github.com/microsoft/durabletask-mssql/pull/285)
78
* Updated repo to use central package management
89
* Resolved multiple CVEs in dependencies
910

Directory.Packages.props

-2.13 KB
Binary file not shown.

src/DurableTask.SqlServer.AzureFunctions/SqlDurabilityProvider.cs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ class SqlDurabilityProvider : DurabilityProvider
2222
readonly SqlDurabilityOptions durabilityOptions;
2323
readonly SqlOrchestrationService service;
2424

25-
SqlScaleMonitor? scaleMonitor;
26-
#if FUNCTIONS_V4
27-
SqlTargetScaler? targetScaler;
28-
#endif
25+
SqlMetricsProvider? singletonSqlMetricsProvider;
2926

3027
public SqlDurabilityProvider(
3128
SqlOrchestrationService service,
@@ -200,13 +197,12 @@ public override bool TryGetScaleMonitor(
200197
string storageConnectionString,
201198
out IScaleMonitor scaleMonitor)
202199
{
203-
if (this.scaleMonitor == null)
200+
if (this.singletonSqlMetricsProvider == null)
204201
{
205-
var sqlMetricsProvider = new SqlMetricsProvider(this.service);
206-
this.scaleMonitor = new SqlScaleMonitor(hubName, sqlMetricsProvider);
202+
this.singletonSqlMetricsProvider = new SqlMetricsProvider(this.service);
207203
}
208-
209-
scaleMonitor = this.scaleMonitor;
204+
scaleMonitor = new SqlScaleMonitor(functionId, hubName, this.singletonSqlMetricsProvider);
205+
210206
return true;
211207
}
212208

@@ -218,13 +214,12 @@ public override bool TryGetTargetScaler(
218214
string connectionName,
219215
out ITargetScaler targetScaler)
220216
{
221-
if (this.targetScaler == null)
217+
if (this.singletonSqlMetricsProvider == null)
222218
{
223-
var sqlMetricsProvider = new SqlMetricsProvider(this.service);
224-
this.targetScaler = new SqlTargetScaler(hubName, sqlMetricsProvider);
219+
this.singletonSqlMetricsProvider = new SqlMetricsProvider(this.service);
225220
}
226221

227-
targetScaler = this.targetScaler;
222+
targetScaler = new SqlTargetScaler(functionId, this.singletonSqlMetricsProvider);
228223
return true;
229224
}
230225
#endif

src/DurableTask.SqlServer.AzureFunctions/SqlMetricsProvider.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33

44
namespace DurableTask.SqlServer.AzureFunctions
55
{
6+
using System;
67
using System.Threading;
78
using System.Threading.Tasks;
89

910
public class SqlMetricsProvider
1011
{
1112
readonly SqlOrchestrationService service;
13+
DateTime metricsTimeStamp = DateTime.MinValue;
14+
SqlScaleMetric? metrics;
1215

1316
public SqlMetricsProvider(SqlOrchestrationService service)
1417
{
@@ -17,13 +20,20 @@ public SqlMetricsProvider(SqlOrchestrationService service)
1720

1821
public virtual async Task<SqlScaleMetric> GetMetricsAsync(int? previousWorkerCount = null)
1922
{
20-
// GetRecommendedReplicaCountAsync will write a trace if the recommendation results
21-
// in a worker count that is different from the worker count we pass in as an argument.
22-
int recommendedReplicaCount = await this.service.GetRecommendedReplicaCountAsync(
23-
previousWorkerCount,
24-
CancellationToken.None);
23+
// We only want to query the metrics every 5 seconds.
24+
if (this.metrics == null || DateTime.UtcNow >= this.metricsTimeStamp.AddSeconds(5))
25+
{
26+
// GetRecommendedReplicaCountAsync will write a trace if the recommendation results
27+
// in a worker count that is different from the worker count we pass in as an argument.
28+
int recommendedReplicaCount = await this.service.GetRecommendedReplicaCountAsync(
29+
previousWorkerCount,
30+
CancellationToken.None);
2531

26-
return new SqlScaleMetric { RecommendedReplicaCount = recommendedReplicaCount };
32+
this.metricsTimeStamp = DateTime.UtcNow;
33+
this.metrics = new SqlScaleMetric { RecommendedReplicaCount = recommendedReplicaCount };
34+
}
35+
36+
return this.metrics;
2737
}
2838
}
2939
}

src/DurableTask.SqlServer.AzureFunctions/SqlScaleMonitor.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@ class SqlScaleMonitor : IScaleMonitor<SqlScaleMetric>
2323

2424
int? previousWorkerCount = -1;
2525

26-
public SqlScaleMonitor(string taskHubName, SqlMetricsProvider sqlMetricsProvider)
26+
public SqlScaleMonitor(string functionId, string taskHubName, SqlMetricsProvider sqlMetricsProvider)
2727
{
28-
// Scalers in Durable Functions are shared for all functions in the same task hub.
29-
// So instead of using a function ID, we use the task hub name as the basis for the descriptor ID.
30-
string id = $"DurableTask-SqlServer:{taskHubName ?? "default"}";
28+
// Scalers in Durable Functions is per function ids. And scalers share the same sqlMetricsProvider in the same taskhub.
29+
string id = $"{functionId}-DurableTask-SqlServer:{taskHubName ?? "default"}";
3130

3231
#if FUNCTIONS_V4
33-
this.Descriptor = new ScaleMonitorDescriptor(id: id, functionId: id);
32+
this.Descriptor = new ScaleMonitorDescriptor(id: id, functionId: functionId);
3433
#else
3534
this.Descriptor = new ScaleMonitorDescriptor(id);
3635
#endif

src/DurableTask.SqlServer.AzureFunctions/SqlTargetScaler.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ public class SqlTargetScaler : ITargetScaler
1212
{
1313
readonly SqlMetricsProvider sqlMetricsProvider;
1414

15-
public SqlTargetScaler(string taskHubName, SqlMetricsProvider sqlMetricsProvider)
15+
public SqlTargetScaler(string functionId, SqlMetricsProvider sqlMetricsProvider)
1616
{
1717
this.sqlMetricsProvider = sqlMetricsProvider;
1818

19-
// Scalers in Durable Functions are shared for all functions in the same task hub.
20-
// So instead of using a function ID, we use the task hub name as the basis for the descriptor ID.
21-
string id = $"DurableTask-SqlServer:{taskHubName ?? "default"}";
22-
this.TargetScalerDescriptor = new TargetScalerDescriptor(id);
19+
// Scalers in Durable Functions is per function ids. And scalers share the same sqlMetricsProvider in the same taskhub.
20+
this.TargetScalerDescriptor = new TargetScalerDescriptor(functionId);
2321
}
2422

2523
public TargetScalerDescriptor TargetScalerDescriptor { get; }

0 commit comments

Comments
 (0)