@@ -18,6 +18,12 @@ namespace Microsoft.DurableTask.Converters;
1818public sealed class BlobPayloadStore : IPayloadStore
1919{
2020 const string TokenPrefix = "blob:v1:" ;
21+ const string ContentEncodingGzip = "gzip" ;
22+ const int DefaultCopyBufferSize = 81920 ;
23+ const int MaxRetryAttempts = 8 ;
24+ const int BaseDelayMs = 250 ;
25+ const int MaxDelayMs = 10_000 ;
26+ const int MaxJitterMs = 100 ;
2127
2228 // Jitter RNG for retry backoff
2329 static readonly object RandomLock = new object ( ) ;
@@ -43,8 +49,8 @@ public BlobPayloadStore(LargePayloadStorageOptions options)
4349 Retry =
4450 {
4551 Mode = RetryMode . Exponential ,
46- MaxRetries = 8 ,
47- Delay = TimeSpan . FromMilliseconds ( 250 ) ,
52+ MaxRetries = MaxRetryAttempts ,
53+ Delay = TimeSpan . FromMilliseconds ( BaseDelayMs ) ,
4854 MaxDelay = TimeSpan . FromSeconds ( 10 ) ,
4955 NetworkTimeout = TimeSpan . FromMinutes ( 2 ) ,
5056 } ,
@@ -73,21 +79,21 @@ public async Task<string> UploadAsync(ReadOnlyMemory<byte> payloadBytes, Cancell
7379 {
7480 BlobOpenWriteOptions writeOptions = new ( )
7581 {
76- HttpHeaders = new BlobHttpHeaders { ContentEncoding = "gzip" } ,
82+ HttpHeaders = new BlobHttpHeaders { ContentEncoding = ContentEncodingGzip } ,
7783 } ;
7884 using Stream blobStream = await blob . OpenWriteAsync ( true , writeOptions , ct ) ;
7985 using GZipStream compressedBlobStream = new ( blobStream , CompressionLevel . Optimal , leaveOpen : true ) ;
8086 using MemoryStream payloadStream = new ( payloadBuffer , writable : false ) ;
8187
82- await payloadStream . CopyToAsync ( compressedBlobStream , bufferSize : 81920 , ct ) ;
88+ await payloadStream . CopyToAsync ( compressedBlobStream , bufferSize : DefaultCopyBufferSize , ct ) ;
8389 await compressedBlobStream . FlushAsync ( ct ) ;
8490 await blobStream . FlushAsync ( ct ) ;
8591 }
8692 else
8793 {
8894 using Stream blobStream = await blob . OpenWriteAsync ( true , default , ct ) ;
8995 using MemoryStream payloadStream = new ( payloadBuffer , writable : false ) ;
90- await payloadStream . CopyToAsync ( blobStream , bufferSize : 81920 , ct ) ;
96+ await payloadStream . CopyToAsync ( blobStream , bufferSize : DefaultCopyBufferSize , ct ) ;
9197 await blobStream . FlushAsync ( ct ) ;
9298 }
9399
@@ -115,7 +121,7 @@ public async Task<string> DownloadAsync(string token, CancellationToken cancella
115121 using BlobDownloadStreamingResult result = await blob . DownloadStreamingAsync ( cancellationToken : ct ) ;
116122 Stream contentStream = result . Content ;
117123 bool isGzip = string . Equals (
118- result . Details . ContentEncoding , "gzip" , StringComparison . OrdinalIgnoreCase ) ;
124+ result . Details . ContentEncoding , ContentEncodingGzip , StringComparison . OrdinalIgnoreCase ) ;
119125
120126 if ( isGzip )
121127 {
@@ -162,8 +168,8 @@ public bool IsKnownPayloadToken(string value)
162168
163169 static async Task < T > WithTransientRetryAsync < T > ( Func < CancellationToken , Task < T > > operation , CancellationToken cancellationToken )
164170 {
165- const int maxAttempts = 8 ;
166- TimeSpan baseDelay = TimeSpan . FromMilliseconds ( 250 ) ;
171+ const int maxAttempts = MaxRetryAttempts ;
172+ TimeSpan baseDelay = TimeSpan . FromMilliseconds ( BaseDelayMs ) ;
167173 int attempt = 0 ;
168174
169175 while ( true )
@@ -201,9 +207,9 @@ static TimeSpan ComputeBackoff(TimeSpan baseDelay, int attempt)
201207 int jitterMs ;
202208 lock ( RandomLock )
203209 {
204- jitterMs = SharedRandom . Next ( 0 , 100 ) ;
210+ jitterMs = SharedRandom . Next ( 0 , MaxJitterMs ) ;
205211 }
206- return TimeSpan . FromMilliseconds ( Math . Min ( ( baseDelay . TotalMilliseconds * factor ) + jitterMs , 10_000 ) ) ;
207- }
208212
213+ return TimeSpan . FromMilliseconds ( Math . Min ( ( baseDelay . TotalMilliseconds * factor ) + jitterMs , MaxDelayMs ) ) ;
214+ }
209215}
0 commit comments