-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
150 lines (128 loc) · 5.7 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Azure;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Polly;
namespace DicomLoader
{
class Program
{
static void Main(
Uri blobContainerUrl,
Uri dicomServerUrl,
string blobPrefix = null,
int maxDegreeOfParallelism = 8,
int refreshInterval = 5)
{
HttpClient httpClient = new HttpClient();
var metrics = new MetricsCollector();
var randomGenerator = new Random();
var pollyDelays =
new[]
{
TimeSpan.FromMilliseconds(2000 + randomGenerator.Next(50)),
TimeSpan.FromMilliseconds(3000 + randomGenerator.Next(50)),
TimeSpan.FromMilliseconds(5000 + randomGenerator.Next(50)),
TimeSpan.FromMilliseconds(8000 + randomGenerator.Next(50)),
TimeSpan.FromMilliseconds(12000 + randomGenerator.Next(50)),
TimeSpan.FromMilliseconds(16000 + randomGenerator.Next(50)),
};
BlobContainerClient containerClient = new BlobContainerClient(blobContainerUrl, new AzureCliCredential());
var actionBlock = new ActionBlock<string>(async blobName =>
{
Thread.Sleep(TimeSpan.FromMilliseconds(randomGenerator.Next(50)));
var blobClient = containerClient.GetBlobClient(blobName);
BlobDownloadInfo download = await blobClient.DownloadAsync();
byte[] fileContents;
using (var br = new BinaryReader(download.Content))
{
fileContents = br.ReadBytes((int)download.ContentLength);
}
HttpResponseMessage uploadResult = await Policy
.HandleResult<HttpResponseMessage>(response => !response.IsSuccessStatusCode)
.WaitAndRetryAsync(pollyDelays, (result, timeSpan, retryCount, context) =>
{
if (retryCount > 3)
{
Console.WriteLine($"Request failed with {result.Result.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}");
}
})
.ExecuteAsync(async () =>
{
var message = new HttpRequestMessage(HttpMethod.Post, new Uri(dicomServerUrl, "/studies"));
message.Headers.Add("Accept", "application/dicom+json");
message.Content = new ByteArrayContent(fileContents);
message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/dicom");
var res = await httpClient.SendAsync(message);
// We are ignoring conflicts...file already on server
if (res.StatusCode == System.Net.HttpStatusCode.Conflict)
{
Console.WriteLine($"Ignoring conflict for file: {blobName}");
return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}
else
{
return res;
}
});
if (!IsSuccessStatusCode(uploadResult.StatusCode))
{
string resultContent = await uploadResult.Content.ReadAsStringAsync();
Console.WriteLine(resultContent);
throw new Exception($"Unable to upload to server. Error code {uploadResult.StatusCode}");
}
metrics.Collect(DateTime.Now);
},
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = maxDegreeOfParallelism
}
);
// Start output on timer
var t = new Task(() =>
{
while (true)
{
Thread.Sleep(1000 * refreshInterval);
Console.WriteLine($"Images per second: {metrics.EventsPerSecond}");
}
});
t.Start();
string continuationToken = null;
try
{
do
{
var resultSegment = containerClient.GetBlobs(prefix: blobPrefix).AsPages(continuationToken);
foreach (Azure.Page<BlobItem> blobPage in resultSegment)
{
foreach (BlobItem blobItem in blobPage.Values)
{
actionBlock.Post(blobItem.Name);
}
continuationToken = blobPage.ContinuationToken;
}
} while (continuationToken != "");
}
catch (RequestFailedException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
actionBlock.Complete();
actionBlock.Completion.Wait();
}
static bool IsSuccessStatusCode(System.Net.HttpStatusCode statusCode)
{
return ((int)statusCode >= 200) && ((int)statusCode <= 299);
}
}
}