Skip to content

Commit 2dc23b1

Browse files
author
JoshuaMiller
committed
async cancellationToken support
1 parent 6e5ab7b commit 2dc23b1

20 files changed

Lines changed: 173 additions & 77 deletions

Jenkins.NET/Internal/Commands/BuildGetCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public BuildGetCommand(IJenkinsContext context, string jobName, string buildNumb
2828
request.Method = "POST";
2929
};
3030

31-
OnReadAsync = async response => {
31+
OnReadAsync = async (response, token) => {
3232
var document = await ReadXmlAsync(response);
3333

3434
var args = new object[] {document.Root};

Jenkins.NET/Internal/Commands/BuildOutputCommand.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System;
2-
using System.IO;
2+
using System.Text;
33

44
namespace JenkinsNET.Internal.Commands
55
{
@@ -24,13 +24,12 @@ public BuildOutputCommand(IJenkinsContext context, string jobName, string buildN
2424
Password = context.Password;
2525
Crumb = context.Crumb;
2626

27-
OnReadAsync = async response => {
27+
OnReadAsync = async (response, token) => {
2828
using (var stream = response.GetResponseStream()) {
2929
if (stream == null) return;
3030

31-
using (var reader = new StreamReader(stream)) {
32-
Result = await reader.ReadToEndAsync();
33-
}
31+
var encoding = TryGetEncoding(response.ContentEncoding, Encoding.UTF8);
32+
Result = await stream.ReadToEndAsync(encoding, token);
3433
}
3534
};
3635
}

Jenkins.NET/Internal/Commands/BuildProgressiveHtmlCommand.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using JenkinsNET.Models;
22
using System;
33
using System.IO;
4+
using System.Text;
45

56
namespace JenkinsNET.Internal.Commands
67
{
@@ -25,7 +26,7 @@ public BuildProgressiveHtmlCommand(IJenkinsContext context, string jobName, stri
2526
Password = context.Password;
2627
Crumb = context.Crumb;
2728

28-
OnWriteAsync = async (request) => {
29+
OnWriteAsync = async (request, token) => {
2930
request.Method = "POST";
3031
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
3132

@@ -35,7 +36,7 @@ public BuildProgressiveHtmlCommand(IJenkinsContext context, string jobName, stri
3536
}
3637
};
3738

38-
OnReadAsync = async response => {
39+
OnReadAsync = async (response, token) => {
3940
var hSize = response.Headers["X-Text-Size"];
4041
var hMoreData = response.Headers["X-More-Data"];
4142

@@ -52,9 +53,8 @@ public BuildProgressiveHtmlCommand(IJenkinsContext context, string jobName, stri
5253
using (var stream = response.GetResponseStream()) {
5354
if (stream == null) return;
5455

55-
using (var reader = new StreamReader(stream)) {
56-
Result.Html = await reader.ReadToEndAsync();
57-
}
56+
var encoding = TryGetEncoding(response.ContentEncoding, Encoding.UTF8);
57+
Result.Html = await stream.ReadToEndAsync(encoding, token);
5858
}
5959
};
6060
}

Jenkins.NET/Internal/Commands/BuildProgressiveTextCommand.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using JenkinsNET.Models;
22
using System;
33
using System.IO;
4+
using System.Text;
45

56
namespace JenkinsNET.Internal.Commands
67
{
@@ -25,7 +26,7 @@ public BuildProgressiveTextCommand(IJenkinsContext context, string jobName, stri
2526
Password = context.Password;
2627
Crumb = context.Crumb;
2728

28-
OnWriteAsync = async (request) => {
29+
OnWriteAsync = async (request, token) => {
2930
request.Method = "POST";
3031
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
3132

@@ -35,7 +36,7 @@ public BuildProgressiveTextCommand(IJenkinsContext context, string jobName, stri
3536
}
3637
};
3738

38-
OnReadAsync = async response => {
39+
OnReadAsync = async (response, token) => {
3940
var hSize = response.Headers["X-Text-Size"];
4041
var hMoreData = response.Headers["X-More-Data"];
4142

@@ -52,9 +53,8 @@ public BuildProgressiveTextCommand(IJenkinsContext context, string jobName, stri
5253
using (var stream = response.GetResponseStream()) {
5354
if (stream == null) return;
5455

55-
using (var reader = new StreamReader(stream)) {
56-
Result.Text = await reader.ReadToEndAsync();
57-
}
56+
var encoding = TryGetEncoding(response.ContentEncoding, Encoding.UTF8);
57+
Result.Text = await stream.ReadToEndAsync(encoding, token);
5858
}
5959
};
6060
}

Jenkins.NET/Internal/Commands/JenkinsGetCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public JenkinsGetCommand(IJenkinsContext context)
2323
request.Method = "GET";
2424
};
2525

26-
OnReadAsync = async response => {
26+
OnReadAsync = async (response, token) => {
2727
var document = await ReadXmlAsync(response);
2828
Result = new Jenkins(document.Root);
2929
};

Jenkins.NET/Internal/Commands/JobCreateCommand.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using JenkinsNET.Models;
22
using System;
3-
using System.Xml;
43

54
namespace JenkinsNET.Internal.Commands
65
{
@@ -24,10 +23,10 @@ public JobCreateCommand(IJenkinsContext context, string jobName, JenkinsProject
2423
Password = context.Password;
2524
Crumb = context.Crumb;
2625

27-
OnWriteAsync = async request => {
26+
OnWriteAsync = async (request, token) => {
2827
request.Method = "POST";
2928
request.ContentType = "application/xml";
30-
await WriteXmlAsync(request, job.Node);
29+
await WriteXmlAsync(request, job.Node, token);
3130
};
3231
}
3332
}

Jenkins.NET/Internal/Commands/JobGetCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ public JobGetCommand(IJenkinsContext context, string jobName)
2626
request.Method = "GET";
2727
};
2828

29-
OnReadAsync = async response => {
29+
OnReadAsync = async (response, token) => {
3030
var document = await ReadXmlAsync(response);
3131

32-
Result = Activator.CreateInstance(typeof(T), new[] {document.Root}) as T;
32+
Result = Activator.CreateInstance(typeof(T), document.Root) as T;
3333
};
3434
}
3535
}

Jenkins.NET/Internal/Commands/JobGetConfigCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public JobGetConfigCommand(IJenkinsContext context, string jobName)
2626
request.Method = "GET";
2727
};
2828

29-
OnReadAsync = async response => {
29+
OnReadAsync = async (response, token) => {
3030
var document = await ReadXmlAsync(response);
3131
Result = new JenkinsProject(document.Root);
3232
};

Jenkins.NET/Internal/Commands/JobUpdateConfigurationCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ public JobUpdateConfigurationCommand(IJenkinsContext context, string jobName, Je
2323
Password = context.Password;
2424
Crumb = context.Crumb;
2525

26-
OnWriteAsync = async request => {
26+
OnWriteAsync = async (request, token) => {
2727
request.Method = "POST";
2828
request.ContentType = "application/xml";
29-
await WriteXmlAsync(request, job.Node);
29+
await WriteXmlAsync(request, job.Node, token);
3030
};
3131
}
3232
}

Jenkins.NET/Internal/JenkinsHttpCommand.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Net;
55
using System.Text;
66
using System.Text.RegularExpressions;
7+
using System.Threading;
78
using System.Threading.Tasks;
89
using System.Xml;
910
using System.Xml.Linq;
@@ -18,33 +19,36 @@ internal class JenkinsHttpCommand
1819
public JenkinsCrumb Crumb {get; set;}
1920
public Action<HttpWebRequest> OnWrite {get; set;}
2021
public Action<HttpWebResponse> OnRead {get; set;}
21-
public Func<HttpWebRequest, Task> OnWriteAsync {get; set;}
22-
public Func<HttpWebResponse, Task> OnReadAsync {get; set;}
22+
public Func<HttpWebRequest, CancellationToken, Task> OnWriteAsync {get; set;}
23+
public Func<HttpWebResponse, CancellationToken, Task> OnReadAsync {get; set;}
2324

2425

2526
public void Run()
2627
{
2728
var request = CreateRequest();
2829

2930
if (OnWrite != null) OnWrite.Invoke(request);
30-
else if (OnWriteAsync != null) OnWriteAsync.Invoke(request).GetAwaiter().GetResult();
31+
else OnWriteAsync?.Invoke(request, CancellationToken.None).GetAwaiter().GetResult();
3132

3233
using (var response = (HttpWebResponse)request.GetResponse()) {
3334
if (OnRead != null) OnRead?.Invoke(response);
34-
else if (OnReadAsync != null) OnReadAsync.Invoke(response).GetAwaiter().GetResult();
35+
else OnReadAsync?.Invoke(response, CancellationToken.None).GetAwaiter().GetResult();
3536
}
3637
}
3738

38-
public async Task RunAsync()
39+
public async Task RunAsync(CancellationToken token = default(CancellationToken))
3940
{
4041
var request = CreateRequest();
4142

42-
if (OnWriteAsync != null) await OnWriteAsync.Invoke(request);
43-
else if (OnWrite != null) OnWrite.Invoke(request);
43+
if (OnWriteAsync != null) await OnWriteAsync.Invoke(request, token);
44+
else OnWrite?.Invoke(request);
4445

46+
using (token.Register(() => request.Abort(), false))
4547
using (var response = (HttpWebResponse)await request.GetResponseAsync()) {
46-
if (OnReadAsync != null) await OnReadAsync.Invoke(response);
47-
else if (OnRead != null) OnRead?.Invoke(response);
48+
token.ThrowIfCancellationRequested();
49+
50+
if (OnReadAsync != null) await OnReadAsync.Invoke(response, token);
51+
else OnRead?.Invoke(response);
4852
}
4953
}
5054

@@ -77,9 +81,12 @@ private HttpWebRequest CreateRequest()
7781
protected async Task<XDocument> ReadXmlAsync(HttpWebResponse response)
7882
{
7983
string xml;
80-
using (var stream = response.GetResponseStream())
81-
using (var reader = new StreamReader(stream)) {
82-
xml = await reader.ReadToEndAsync();
84+
using (var stream = response.GetResponseStream()) {
85+
if (stream == null) return null;
86+
87+
using (var reader = new StreamReader(stream)) {
88+
xml = await reader.ReadToEndAsync();
89+
}
8390
}
8491

8592
// Remove Decleration
@@ -89,17 +96,30 @@ protected async Task<XDocument> ReadXmlAsync(HttpWebResponse response)
8996
return XDocument.Parse(xml);
9097
}
9198

92-
protected async Task WriteXmlAsync(HttpWebRequest request, XNode node)
99+
protected async Task WriteXmlAsync(HttpWebRequest request, XNode node, CancellationToken token = default(CancellationToken))
93100
{
94101
var xmlSettings = new XmlWriterSettings {
95102
ConformanceLevel = ConformanceLevel.Fragment,
96103
Indent = false,
97104
};
98105

106+
using (token.Register(request.Abort, false))
99107
using (var stream = await request.GetRequestStreamAsync())
100108
using (var writer = XmlWriter.Create(stream, xmlSettings)) {
109+
token.ThrowIfCancellationRequested();
110+
101111
node.WriteTo(writer);
102112
}
103113
}
114+
115+
protected static Encoding TryGetEncoding(string name, Encoding fallback)
116+
{
117+
try {
118+
return Encoding.GetEncoding(name);
119+
}
120+
catch {
121+
return fallback;
122+
}
123+
}
104124
}
105125
}

0 commit comments

Comments
 (0)