Skip to content

Commit 8e8f0d9

Browse files
authored
Merge pull request #119 from Drawaes/FixingLeadership
Add usings to HttpResponses
2 parents c37f571 + b43ad94 commit 8e8f0d9

11 files changed

Lines changed: 156 additions & 140 deletions

File tree

CondenserDotNet.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Release Notes", "Release No
8787
releasenotes\4.1.1.props = releasenotes\4.1.1.props
8888
releasenotes\4.1.10.props = releasenotes\4.1.10.props
8989
releasenotes\4.1.11.props = releasenotes\4.1.11.props
90+
releasenotes\4.1.13.props = releasenotes\4.1.13.props
9091
releasenotes\4.1.3.props = releasenotes\4.1.3.props
9192
releasenotes\4.1.4.props = releasenotes\4.1.4.props
9293
releasenotes\4.1.9.props = releasenotes\4.1.9.props

releasenotes/4.1.13.props

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project>
2+
<PropertyGroup>
3+
<PackageReleaseNotes>
4+
* Fix potential leaks by ensuring HttpResponses are disposed correctly
5+
</PackageReleaseNotes>
6+
</PropertyGroup>
7+
</Project>

src/CondenserDotNet.Client/Leadership/LeaderWatcher.cs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -69,33 +69,35 @@ private async Task TryForElection()
6969
for (var i = 0; i < 10; i++)
7070
{
7171
CondenserEventSource.Log.LeadershipSessionGetStatus(_keyToWatch);
72-
leaderResult = await _serviceManager.Client.GetAsync($"{KeyPath}{_keyToWatch}?index={_consulIndex}");
73-
if (!leaderResult.IsSuccessStatusCode)
72+
using (leaderResult = await _serviceManager.Client.GetAsync($"{KeyPath}{_keyToWatch}?index={_consulIndex}"))
7473
{
75-
_currentLeaderEvent.Reset();
76-
_electedLeaderEvent.Reset();
77-
//error so return to create session
78-
return;
74+
if (!leaderResult.IsSuccessStatusCode)
75+
{
76+
_currentLeaderEvent.Reset();
77+
_electedLeaderEvent.Reset();
78+
//error so return to create session
79+
return;
80+
}
81+
var kv = JsonConvert.DeserializeObject<KeyValue[]>(await leaderResult.Content.ReadAsStringAsync());
82+
if (string.IsNullOrWhiteSpace(kv[0].Session))
83+
{
84+
_currentLeaderEvent.Reset();
85+
_electedLeaderEvent.Reset();
86+
break;
87+
}
88+
var infoService = JsonConvert.DeserializeObject<InformationService>(kv[0].ValueFromBase64());
89+
_currentLeaderEvent.Set(infoService);
90+
_callback?.Invoke(infoService);
91+
if (Guid.Parse(kv[0].Session) == _sessionId)
92+
{
93+
_electedLeaderEvent.Set(true);
94+
}
95+
else
96+
{
97+
_electedLeaderEvent.Reset();
98+
}
99+
_consulIndex = leaderResult.GetConsulIndex();
79100
}
80-
var kv = JsonConvert.DeserializeObject<KeyValue[]>(await leaderResult.Content.ReadAsStringAsync());
81-
if (string.IsNullOrWhiteSpace(kv[0].Session))
82-
{
83-
_currentLeaderEvent.Reset();
84-
_electedLeaderEvent.Reset();
85-
break;
86-
}
87-
var infoService = JsonConvert.DeserializeObject<InformationService>(kv[0].ValueFromBase64());
88-
_currentLeaderEvent.Set(infoService);
89-
_callback?.Invoke(infoService);
90-
if (Guid.Parse(kv[0].Session) == _sessionId)
91-
{
92-
_electedLeaderEvent.Set(true);
93-
}
94-
else
95-
{
96-
_electedLeaderEvent.Reset();
97-
}
98-
_consulIndex = leaderResult.GetConsulIndex();
99101
}
100102
}
101103
}

src/CondenserDotNet.Client/Leadership/LeaderWatcherNew.cs

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -104,35 +104,37 @@ private async Task WaitForLeadershipChange()
104104
{
105105
while(true)
106106
{
107-
var leaderResult = await _serviceManager.Client.GetAsync($"{KeyPath}{_keyToWatch}?index={_consulIndex}");
108-
if(!leaderResult.IsSuccessStatusCode)
107+
using (var leaderResult = await _serviceManager.Client.GetAsync($"{KeyPath}{_keyToWatch}?index={_consulIndex}"))
109108
{
110-
//Lock deleted
111-
if(leaderResult.StatusCode == System.Net.HttpStatusCode.NotFound)
109+
if (!leaderResult.IsSuccessStatusCode)
112110
{
113-
_electedLeaderEvent.Reset();
111+
//Lock deleted
112+
if (leaderResult.StatusCode == System.Net.HttpStatusCode.NotFound)
113+
{
114+
_electedLeaderEvent.Reset();
115+
_currentInfoService.Reset();
116+
return;
117+
}
118+
await Task.Delay(500);
119+
continue;
120+
}
121+
var kv = JsonConvert.DeserializeObject<KeyValue[]>(await leaderResult.Content.ReadAsStringAsync());
122+
if (string.IsNullOrWhiteSpace(kv[0].Session))
123+
{
124+
//no one has leadership
114125
_currentInfoService.Reset();
126+
_electedLeaderEvent.Reset();
127+
return;
128+
}
129+
var infoService = JsonConvert.DeserializeObject<InformationService>(kv[0].ValueFromBase64());
130+
_currentInfoService.Set(infoService);
131+
_consulIndex = leaderResult.GetConsulIndex();
132+
_callback?.Invoke(infoService);
133+
if (await _sessionIdTask != new Guid(kv[0].Session))
134+
{
135+
_electedLeaderEvent.Reset();
115136
return;
116137
}
117-
await Task.Delay(500);
118-
continue;
119-
}
120-
var kv = JsonConvert.DeserializeObject<KeyValue[]>(await leaderResult.Content.ReadAsStringAsync());
121-
if(string.IsNullOrWhiteSpace(kv[0].Session))
122-
{
123-
//no one has leadership
124-
_currentInfoService.Reset();
125-
_electedLeaderEvent.Reset();
126-
return;
127-
}
128-
var infoService = JsonConvert.DeserializeObject<InformationService>(kv[0].ValueFromBase64());
129-
_currentInfoService.Set(infoService);
130-
_consulIndex = leaderResult.GetConsulIndex();
131-
_callback?.Invoke(infoService);
132-
if(await _sessionIdTask != new Guid(kv[0].Session))
133-
{
134-
_electedLeaderEvent.Reset();
135-
return;
136138
}
137139
}
138140
}

src/CondenserDotNet.Client/Services/ServiceRegistry.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ public async Task<IEnumerable<string>> GetAvailableServicesAsync()
3131

3232
public async Task<Dictionary<string, string[]>> GetAvailableServicesWithTagsAsync()
3333
{
34-
var result = await _client.GetAsync(HttpUtils.ServiceCatalogUrl);
35-
if (!result.IsSuccessStatusCode)
34+
using (var result = await _client.GetAsync(HttpUtils.ServiceCatalogUrl))
3635
{
37-
return null;
36+
if (!result.IsSuccessStatusCode)
37+
{
38+
return null;
39+
}
40+
var content = await result.Content.ReadAsStringAsync();
41+
var serviceList = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(content);
42+
return serviceList;
3843
}
39-
var content = await result.Content.ReadAsStringAsync();
40-
var serviceList = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(content);
41-
return serviceList;
4244
}
4345

4446
public Task<InformationService> GetServiceInstanceAsync(string serviceName)

src/CondenserDotNet.Client/Services/ServiceWatcher.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,31 @@ private async Task WatcherLoop(HttpClient client)
8989
var consulIndex = "0";
9090
while (!_cancelationToken.Token.IsCancellationRequested)
9191
{
92-
var result = await client.GetAsync(_url + consulIndex, _cancelationToken.Token);
93-
if (!result.IsSuccessStatusCode)
92+
using (var result = await client.GetAsync(_url + consulIndex, _cancelationToken.Token))
9493
{
95-
if (_state == WatcherState.UsingLiveValues)
94+
if (!result.IsSuccessStatusCode)
9695
{
97-
_state = WatcherState.UsingCachedValues;
96+
if (_state == WatcherState.UsingLiveValues)
97+
{
98+
_state = WatcherState.UsingCachedValues;
99+
}
100+
await Task.Delay(1000);
101+
continue;
98102
}
99-
await Task.Delay(1000);
100-
continue;
101-
}
102-
var newConsulIndex = result.GetConsulIndex();
103-
if (newConsulIndex == consulIndex)
104-
{
103+
var newConsulIndex = result.GetConsulIndex();
104+
if (newConsulIndex == consulIndex)
105+
{
106+
continue;
107+
}
108+
consulIndex = newConsulIndex;
109+
var content = await result.Content.ReadAsStringAsync();
110+
var instance = JsonConvert.DeserializeObject<List<InformationServiceSet>>(content);
111+
Volatile.Write(ref _instances, instance);
112+
_listCallback?.Invoke(instance);
113+
_state = WatcherState.UsingLiveValues;
114+
_completionSource.TrySetResult(true);
105115
continue;
106116
}
107-
consulIndex = newConsulIndex;
108-
var content = await result.Content.ReadAsStringAsync();
109-
var instance = JsonConvert.DeserializeObject<List<InformationServiceSet>>(content);
110-
Volatile.Write(ref _instances, instance);
111-
_listCallback?.Invoke(instance);
112-
_state = WatcherState.UsingLiveValues;
113-
_completionSource.TrySetResult(true);
114-
continue;
115117
}
116118
}
117119
catch (Exception ex)

src/CondenserDotNet.Configuration/Consul/ConsulConfigSource.cs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,17 @@ public async Task<KeyOperationResult> GetKeysAsync(string keyPath)
6363
try
6464
{
6565
CondenserEventSource.Log.ConfigurationGetKeysRecursive(keyPath);
66-
var response = await _httpClient.GetAsync($"{ConsulKeyPath}{keyPath}?recurse");
67-
if (!response.IsSuccessStatusCode)
66+
using (var response = await _httpClient.GetAsync($"{ConsulKeyPath}{keyPath}?recurse"))
6867
{
69-
_logger?.LogWarning("We didn't get a succesful response from consul code was {code}", response.StatusCode);
70-
return new KeyOperationResult() { Success = false, Dictionary = null };
68+
if (!response.IsSuccessStatusCode)
69+
{
70+
_logger?.LogWarning("We didn't get a succesful response from consul code was {code}", response.StatusCode);
71+
return new KeyOperationResult() { Success = false, Dictionary = null };
72+
}
73+
74+
var dictionary = await BuildDictionaryAsync(keyPath, response);
75+
return new KeyOperationResult() { Success = true, Dictionary = dictionary };
7176
}
72-
73-
var dictionary = await BuildDictionaryAsync(keyPath, response);
74-
return new KeyOperationResult() { Success = true, Dictionary = dictionary };
7577
}
7678
catch (Exception ex)
7779
{
@@ -86,17 +88,19 @@ public async Task<KeyOperationResult> GetKeysAsync(string keyPath)
8688
try
8789
{
8890
CondenserEventSource.Log.ConfigurationGetKey(keyPath);
89-
var response = await _httpClient.GetAsync($"{ConsulKeyPath}{keyPath}");
90-
if (!response.IsSuccessStatusCode)
91+
using (var response = await _httpClient.GetAsync($"{ConsulKeyPath}{keyPath}"))
9192
{
92-
_logger?.LogWarning("We didn't get a successful response from consul code was {code}", response.StatusCode);
93-
return (false, null);
93+
if (!response.IsSuccessStatusCode)
94+
{
95+
_logger?.LogWarning("We didn't get a successful response from consul code was {code}", response.StatusCode);
96+
return (false, null);
97+
}
98+
99+
var content = await response.Content.ReadAsStringAsync();
100+
var keys = JsonConvert.DeserializeObject<KeyValue[]>(content);
101+
if (keys.Length != 1) return (false, null);
102+
return (true, keys[0].Value);
94103
}
95-
96-
var content = await response.Content.ReadAsStringAsync();
97-
var keys = JsonConvert.DeserializeObject<KeyValue[]>(content);
98-
if (keys.Length != 1) return (false, null);
99-
return (true, keys[0].Value);
100104
}
101105
catch (Exception exception)
102106
{
@@ -113,23 +117,25 @@ public async Task<KeyOperationResult> TryWatchKeysAsync(string keyPath, object s
113117
try
114118
{
115119
CondenserEventSource.Log.ConfigurationWatchKey(keyPath);
116-
var response = await _httpClient.GetAsync(url + consulState.ConsulIndex, _disposed.Token);
117-
var newConsulIndex = response.GetConsulIndex();
118-
119-
if (!response.IsSuccessStatusCode)
120-
{
121-
consulState.ConsulIndex = newConsulIndex;
122-
return default;
123-
}
124-
125-
if (newConsulIndex == consulState.ConsulIndex)
120+
using (var response = await _httpClient.GetAsync(url + consulState.ConsulIndex, _disposed.Token))
126121
{
122+
var newConsulIndex = response.GetConsulIndex();
123+
124+
if (!response.IsSuccessStatusCode)
125+
{
126+
consulState.ConsulIndex = newConsulIndex;
127+
return default;
128+
}
129+
130+
if (newConsulIndex == consulState.ConsulIndex)
131+
{
132+
consulState.ConsulIndex = newConsulIndex;
133+
return default;
134+
}
127135
consulState.ConsulIndex = newConsulIndex;
128-
return default;
136+
var dictionary = await BuildDictionaryAsync(keyPath, response);
137+
return new KeyOperationResult() { Success = true, Dictionary = dictionary };
129138
}
130-
consulState.ConsulIndex = newConsulIndex;
131-
var dictionary = await BuildDictionaryAsync(keyPath, response);
132-
return new KeyOperationResult() { Success = true, Dictionary = dictionary };
133139
}
134140
catch (Exception ex)
135141
{

src/CondenserDotNet.Core/HttpUtils.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,11 @@ public static HttpClient CreateClient(IConsulAclProvider aclProvider, string age
3939
var port = agentPort ?? DefaultPort;
4040

4141
var uri = new UriBuilder("http", host, port);
42-
HttpClient client;
43-
#if NET452
44-
System.Net.ServicePointManager.DefaultConnectionLimit = 50;
45-
client = new HttpClient()
42+
var client = new HttpClient(new HttpClientHandler() { MaxConnectionsPerServer = 50 })
4643
{
4744
BaseAddress = uri.Uri,
4845
Timeout = DefaultTimeout
4946
};
50-
#else
51-
client = new HttpClient(new HttpClientHandler() { MaxConnectionsPerServer = 50 })
52-
{
53-
BaseAddress = uri.Uri,
54-
Timeout = DefaultTimeout
55-
};
56-
#endif
5747
var token = aclProvider?.GetAclToken();
5848
if(!string.IsNullOrEmpty(token))
5949
{
@@ -62,17 +52,17 @@ public static HttpClient CreateClient(IConsulAclProvider aclProvider, string age
6252
return client;
6353
}
6454

65-
public static Task<T> GetObject<T>(this HttpContent content) =>
66-
content.ReadAsStringAsync().ContinueWith(sTask =>
55+
public static async Task<T> GetObject<T>(this HttpContent content)
6756
{
68-
return JsonConvert.DeserializeObject<T>(sTask.Result);
69-
});
57+
var result = await content.ReadAsStringAsync();
58+
return JsonConvert.DeserializeObject<T>(result);
59+
}
7060

71-
public static Task<T> GetAsync<T>(this HttpClient client, string uri) =>
72-
client.GetStringAsync(uri).ContinueWith(resultTask =>
61+
public static async Task<T> GetAsync<T>(this HttpClient client, string uri)
7362
{
74-
return JsonConvert.DeserializeObject<T>(resultTask.Result);
75-
});
63+
var result = await client.GetStringAsync(uri);
64+
return JsonConvert.DeserializeObject<T>(result);
65+
}
7666

7767
public static StringContent GetStringContent(string stringForContent)
7868
{

0 commit comments

Comments
 (0)