Skip to content

Commit 406b273

Browse files
Merge pull request #401 from Azure/chgagnon/fixPollingSize
Fix polling size override using wrong configuration value
2 parents 373344c + 3ce378c commit 406b273

File tree

3 files changed

+76
-13
lines changed

3 files changed

+76
-13
lines changed

src/TriggerBinding/SqlTableChangeMonitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public SqlTableChangeMonitor(
124124

125125
// Check if there's config settings to override the default batch size/polling interval values
126126
int? configuredBatchSize = configuration.GetValue<int?>(SqlTriggerConstants.ConfigKey_SqlTrigger_BatchSize);
127-
int? configuredPollingInterval = configuration.GetValue<int?>(SqlTriggerConstants.ConfigKey_SqlTrigger_BatchSize);
127+
int? configuredPollingInterval = configuration.GetValue<int?>(SqlTriggerConstants.ConfigKey_SqlTrigger_PollingInterval);
128128
this._batchSize = configuredBatchSize ?? this._batchSize;
129129
this._pollingIntervalInMs = configuredPollingInterval ?? this._pollingIntervalInMs;
130130
var monitorStartProps = new Dictionary<TelemetryPropertyName, string>(telemetryProps)

test/Common/TestUtils.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Data;
77
using System.Diagnostics;
8+
using System.Text.RegularExpressions;
89
using System.Threading;
910
using System.Threading.Tasks;
1011

@@ -177,5 +178,35 @@ public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task,
177178
throw new TimeoutException(message);
178179
}
179180
}
181+
182+
/// <summary>
183+
/// Creates a DataReceievedEventHandler that will wait for the specified regex and then check that
184+
/// the matched group matches the expected value.
185+
/// </summary>
186+
/// <param name="taskCompletionSource">The task completion source to signal when the value is received</param>
187+
/// <param name="regex">The regex. This must have a single group match for the specific value being looked for</param>
188+
/// <param name="valueName">The name of the value to output if the match fails</param>
189+
/// <param name="expectedValue">The value expected to be equal to the matched group from the regex</param>
190+
/// <returns>The event handler</returns>
191+
public static DataReceivedEventHandler CreateOutputReceievedHandler(TaskCompletionSource<bool> taskCompletionSource, string regex, string valueName, string expectedValue)
192+
{
193+
return (object sender, DataReceivedEventArgs e) =>
194+
{
195+
Match match = Regex.Match(e.Data, regex);
196+
if (match.Success)
197+
{
198+
// We found the line so now check that the group matches our expected value
199+
string actualValue = match.Groups[1].Value;
200+
if (actualValue == expectedValue)
201+
{
202+
taskCompletionSource.SetResult(true);
203+
}
204+
else
205+
{
206+
taskCompletionSource.SetException(new Exception($"Expected {valueName} value of {expectedValue} but got value {actualValue}"));
207+
}
208+
}
209+
};
210+
}
180211
}
181212
}

test/Integration/SqlTriggerBindingIntegrationTests.cs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,30 @@ await this.WaitForProductChanges(
7575
[Fact]
7676
public async Task BatchSizeOverrideTriggerTest()
7777
{
78-
const int batchSize = 20;
78+
// Use enough items to require 4 batches to be processed but then
79+
// set the batch size to the same value so they can all be processed in one
80+
// batch. The test will only wait for ~1 batch worth of time so will timeout
81+
// if the batch size isn't actually changed
82+
const int batchSize = SqlTableChangeMonitor<object>.DefaultBatchSize * 4;
7983
const int firstId = 1;
80-
const int lastId = 40;
84+
const int lastId = batchSize;
8185
this.EnableChangeTrackingForTable("Products");
82-
this.StartFunctionHost(nameof(ProductsTriggerWithValidation), SupportedLanguages.CSharp, true, environmentVariables: new Dictionary<string, string>() {
83-
{ "TEST_EXPECTED_BATCH_SIZE", batchSize.ToString() },
84-
{ "Sql_Trigger_BatchSize", batchSize.ToString() }
85-
});
86+
var taskCompletionSource = new TaskCompletionSource<bool>();
87+
DataReceivedEventHandler handler = TestUtils.CreateOutputReceievedHandler(
88+
taskCompletionSource,
89+
@"Starting change consumption loop. BatchSize: (\d*) PollingIntervalMs: \d*",
90+
"BatchSize",
91+
batchSize.ToString());
92+
this.StartFunctionHost(
93+
nameof(ProductsTriggerWithValidation),
94+
SupportedLanguages.CSharp,
95+
useTestFolder: true,
96+
customOutputHandler: handler,
97+
environmentVariables: new Dictionary<string, string>() {
98+
{ "TEST_EXPECTED_BATCH_SIZE", batchSize.ToString() },
99+
{ "Sql_Trigger_BatchSize", batchSize.ToString() }
100+
}
101+
);
86102

87103
await this.WaitForProductChanges(
88104
firstId,
@@ -92,6 +108,7 @@ await this.WaitForProductChanges(
92108
id => $"Product {id}",
93109
id => id * 100,
94110
this.GetBatchProcessingTimeout(firstId, lastId, batchSize: batchSize));
111+
await taskCompletionSource.Task.TimeoutAfter(TimeSpan.FromSeconds(5000), "Timed out waiting for BatchSize configuration message");
95112
}
96113

97114
/// <summary>
@@ -100,13 +117,28 @@ await this.WaitForProductChanges(
100117
[Fact]
101118
public async Task PollingIntervalOverrideTriggerTest()
102119
{
103-
const int pollingIntervalMs = 100;
104120
const int firstId = 1;
105-
const int lastId = 50;
121+
// Use enough items to require 5 batches to be processed - the test will
122+
// only wait for the expected time and timeout if the default polling
123+
// interval isn't actually modified.
124+
const int lastId = SqlTableChangeMonitor<object>.DefaultBatchSize * 5;
125+
const int pollingIntervalMs = SqlTableChangeMonitor<object>.DefaultPollingIntervalMs / 2;
106126
this.EnableChangeTrackingForTable("Products");
107-
this.StartFunctionHost(nameof(ProductsTriggerWithValidation), SupportedLanguages.CSharp, true, environmentVariables: new Dictionary<string, string>() {
108-
{ "Sql_Trigger_PollingIntervalMs", pollingIntervalMs.ToString() }
109-
});
127+
var taskCompletionSource = new TaskCompletionSource<bool>();
128+
DataReceivedEventHandler handler = TestUtils.CreateOutputReceievedHandler(
129+
taskCompletionSource,
130+
@"Starting change consumption loop. BatchSize: \d* PollingIntervalMs: (\d*)",
131+
"PollingInterval",
132+
pollingIntervalMs.ToString());
133+
this.StartFunctionHost(
134+
nameof(ProductsTriggerWithValidation),
135+
SupportedLanguages.CSharp,
136+
useTestFolder: true,
137+
customOutputHandler: handler,
138+
environmentVariables: new Dictionary<string, string>() {
139+
{ "Sql_Trigger_PollingIntervalMs", pollingIntervalMs.ToString() }
140+
}
141+
);
110142

111143
await this.WaitForProductChanges(
112144
firstId,
@@ -116,9 +148,9 @@ await this.WaitForProductChanges(
116148
id => $"Product {id}",
117149
id => id * 100,
118150
this.GetBatchProcessingTimeout(firstId, lastId, pollingIntervalMs: pollingIntervalMs));
151+
await taskCompletionSource.Task.TimeoutAfter(TimeSpan.FromSeconds(5000), "Timed out waiting for PollingInterval configuration message");
119152
}
120153

121-
122154
/// <summary>
123155
/// Verifies that if several changes have happened to the table row since last invocation, then a single net
124156
/// change for that row is passed to the user function.

0 commit comments

Comments
 (0)