Skip to content

Commit f3e3a51

Browse files
mikeharderscbedd
andauthored
[test-proxy] Only remove session once body has been written (#8709)
* Only remove session once body has been written, to minimize probability client retries but test-proxy has already removed the session * remove the necessity of always locking to check if a session is sanitized * add entry remove, call it * optimize a few lock calls to happen once where possible --------- Co-authored-by: Scott Beddall <scbedd@microsoft.com>
1 parent a95fe52 commit f3e3a51

2 files changed

Lines changed: 46 additions & 25 deletions

File tree

tools/test-proxy/Azure.Sdk.Tools.TestProxy/Common/RecordSession.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

44
using System;
@@ -84,7 +84,7 @@ public void Record(RecordEntry entry)
8484

8585
public RecordEntry Lookup(RecordEntry requestEntry, RecordMatcher matcher, IEnumerable<RecordedTestSanitizer> sanitizers, bool remove = true)
8686
{
87-
foreach(RecordedTestSanitizer sanitizer in sanitizers)
87+
foreach (RecordedTestSanitizer sanitizer in sanitizers)
8888
{
8989
sanitizer.Sanitize(requestEntry);
9090
}
@@ -103,12 +103,30 @@ public RecordEntry Lookup(RecordEntry requestEntry, RecordMatcher matcher, IEnum
103103
}
104104
}
105105

106+
public void Remove(RecordEntry entry)
107+
{
108+
lock (Entries)
109+
{
110+
Entries.Remove(entry);
111+
}
112+
}
113+
106114
public void Sanitize(RecordedTestSanitizer sanitizer)
107115
{
108116
lock (Entries)
109117
{
110118
sanitizer.Sanitize(this);
111119
}
112120
}
121+
public void Sanitize(IEnumerable<RecordedTestSanitizer> sanitizers)
122+
{
123+
lock (Entries)
124+
{
125+
foreach(var sanitizer in sanitizers)
126+
{
127+
sanitizer.Sanitize(this);
128+
}
129+
}
130+
}
113131
}
114132
}

tools/test-proxy/Azure.Sdk.Tools.TestProxy/RecordingHandler.cs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,7 @@ public void StopRecording(string sessionId, IDictionary<string, string> variable
114114
}
115115

116116
var sanitizers = SanitizerRegistry.GetSanitizers(recordingSession);
117-
118-
foreach (RecordedTestSanitizer sanitizer in sanitizers)
119-
{
120-
recordingSession.Session.Sanitize(sanitizer);
121-
}
117+
recordingSession.Session.Sanitize(sanitizers);
122118

123119
if (variables != null)
124120
{
@@ -457,16 +453,15 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
457453

458454
var sanitizers = SanitizerRegistry.GetSanitizers(session);
459455

460-
// we don't need to re-sanitize with recording-applicable sanitizers every time. just the very first one
461-
lock (session)
456+
if (!session.IsSanitized)
462457
{
463-
if (!session.IsSanitized)
458+
// we don't need to re-sanitize with recording-applicable sanitizers every time. just the very first one
459+
lock (session.SanitizerLock)
464460
{
465-
session.IsSanitized = true;
466-
467-
foreach (RecordedTestSanitizer sanitizer in sanitizers)
461+
if (!session.IsSanitized)
468462
{
469-
session.Session.Sanitize(sanitizer);
463+
session.Session.Sanitize(sanitizers);
464+
session.IsSanitized = true;
470465
}
471466
}
472467
}
@@ -475,23 +470,14 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
475470

476471
var entry = (await CreateEntryAsync(incomingRequest).ConfigureAwait(false)).Item1;
477472

478-
// If request contains "x-recording-remove: false", then request is not removed from session after playback.
479-
// Used by perf tests to play back the same request multiple times.
480-
var remove = true;
481-
if (incomingRequest.Headers.TryGetValue("x-recording-remove", out var removeHeader))
482-
{
483-
remove = bool.Parse(removeHeader);
484-
}
485-
486-
var match = session.Session.Lookup(entry, session.CustomMatcher ?? Matcher, sanitizers, remove);
473+
// Session may be removed later, but only after response has been fully written
474+
var match = session.Session.Lookup(entry, session.CustomMatcher ?? Matcher, sanitizers, remove: false);
487475

488476
foreach (ResponseTransform transform in Transforms.Concat(session.AdditionalTransforms))
489477
{
490478
transform.Transform(incomingRequest, match);
491479
}
492480

493-
Interlocked.Increment(ref Startup.RequestsPlayedBack);
494-
495481
outgoingResponse.StatusCode = match.StatusCode;
496482

497483
foreach (var header in match.Response.Headers)
@@ -512,6 +498,23 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
512498

513499
await WriteBodyBytes(bodyData, session.PlaybackResponseTime, outgoingResponse);
514500
}
501+
502+
Interlocked.Increment(ref Startup.RequestsPlayedBack);
503+
504+
// Only remove session once body has been written, to minimize probability client retries but test-proxy has already removed the session
505+
var remove = true;
506+
507+
// If request contains "x-recording-remove: false", then request is not removed from session after playback.
508+
// Used by perf tests to play back the same request multiple times.
509+
if (incomingRequest.Headers.TryGetValue("x-recording-remove", out var removeHeader))
510+
{
511+
remove = bool.Parse(removeHeader);
512+
}
513+
514+
if (remove)
515+
{
516+
session.Session.Remove(match);
517+
}
515518
}
516519

517520
public byte[][] GetBatches(byte[] bodyData, int batchCount)

0 commit comments

Comments
 (0)