You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@reef.apache.org by af...@apache.org on 2016/01/31 10:00:10 UTC
reef git commit: [REEF-1169] Implement REST requests using .NET
HttpClient in O.A.R.Client
Repository: reef
Updated Branches:
refs/heads/master 407041dcd -> 76adb40cf
[REEF-1169] Implement REST requests using .NET HttpClient in O.A.R.Client
This addressed the issue by
* Implementing IRestRequest, IRestResponse and IRestClient based on .NET
* httpclient
JIRA:
[REEF-1169](https://issues.apache.org/jira/browse/REEF-1169)
Pull Request:
Closes #805
Project: http://git-wip-us.apache.org/repos/asf/reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/76adb40c
Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/76adb40c
Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/76adb40c
Branch: refs/heads/master
Commit: 76adb40cf422e0d46021516ec3a9318ddf13dc3a
Parents: 407041d
Author: Anupam <an...@gmail.com>
Authored: Thu Jan 7 16:27:23 2016 -0800
Committer: Andrew Chung <af...@apache.org>
Committed: Sun Jan 31 00:58:45 2016 -0800
----------------------------------------------------------------------
lang/cs/.nuget/packages.config | 2 +-
.../Org.Apache.REEF.Client.Tests.csproj | 12 +-
.../RestClientTests.cs | 188 +++++++++++++++++++
.../YarnClientTests.cs | 35 ++--
.../packages.config | 3 +-
.../Org.Apache.REEF.Client.csproj | 25 ++-
.../YARN/RESTClient/HttpClient.cs | 59 ++++++
.../YARN/RESTClient/HttpClientRetryHandler.cs | 68 +++++++
.../YARN/RESTClient/IDeserializer.cs | 33 ++++
.../YARN/RESTClient/IHttpClient.cs | 37 ++++
.../YARN/RESTClient/IRequestFactory.cs | 43 +++++
.../YARN/RESTClient/IRestClient.cs | 43 +++++
.../YARN/RESTClient/IRestClientFactory.cs | 52 -----
.../YARN/RESTClient/IRestRequestExecutor.cs | 20 +-
.../YARN/RESTClient/ISerializer.cs | 33 ++++
.../YARN/RESTClient/Method.cs | 26 +++
.../YARN/RESTClient/RequestFactory.cs | 76 ++++++++
.../YARN/RESTClient/RestClient.cs | 141 ++++++++++++++
.../YARN/RESTClient/RestJsonDeserializer.cs | 31 +--
.../YARN/RESTClient/RestJsonSerializer.cs | 28 ++-
.../YARN/RESTClient/RestRequest.cs | 49 +++++
.../YARN/RESTClient/RestRequestExecutor.cs | 92 ++++++---
.../YARN/RESTClient/RestResponse.cs | 50 +++++
.../YARN/RESTClient/YarnClient.cs | 57 +++---
.../YARN/RESTClient/YarnRestAPIException.cs | 3 +
lang/cs/Org.Apache.REEF.Client/packages.config | 4 +-
.../AsyncUtils/VoidResult.cs | 31 +++
.../Org.Apache.Reef.Utilities.csproj | 1 +
lang/cs/Org.Apache.REEF.sln | Bin 34256 -> 34618 bytes
29 files changed, 1057 insertions(+), 185 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/.nuget/packages.config
----------------------------------------------------------------------
diff --git a/lang/cs/.nuget/packages.config b/lang/cs/.nuget/packages.config
index a4f6043..ca0774b 100644
--- a/lang/cs/.nuget/packages.config
+++ b/lang/cs/.nuget/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client.Tests/Org.Apache.REEF.Client.Tests.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client.Tests/Org.Apache.REEF.Client.Tests.csproj b/lang/cs/Org.Apache.REEF.Client.Tests/Org.Apache.REEF.Client.Tests.csproj
index 7260f07..724fe05 100644
--- a/lang/cs/Org.Apache.REEF.Client.Tests/Org.Apache.REEF.Client.Tests.csproj
+++ b/lang/cs/Org.Apache.REEF.Client.Tests/Org.Apache.REEF.Client.Tests.csproj
@@ -41,11 +41,8 @@ under the License.
<HintPath>$(PackagesDir)\NSubstitute.1.8.2.0\lib\net45\NSubstitute.dll</HintPath>
<Private>True</Private>
</Reference>
- <Reference Include="RestSharp, Version=100.0.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
- <HintPath>$(PackagesDir)\RestSharpSigned.105.2.3\lib\net45\RestSharp.dll</HintPath>
- <Private>True</Private>
- </Reference>
<Reference Include="System" />
+ <Reference Include="System.Net.Http" />
<Reference Include="System.ServiceProcess" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>$(PackagesDir)\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
@@ -68,6 +65,7 @@ under the License.
<Compile Include="JobResourceUploaderTests.cs" />
<Compile Include="LegacyJobResourceUploaderTests.cs" />
<Compile Include="MultipleRMUrlProviderTests.cs" />
+ <Compile Include="RestClientTests.cs" />
<Compile Include="WindowsHadoopEmulatorYarnClientTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="YarnClientTests.cs" />
@@ -87,6 +85,10 @@ under the License.
<Project>{97DBB573-3994-417A-9F69-FFA25F00D2A6}</Project>
<Name>Org.Apache.REEF.Tang</Name>
</ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\Org.Apache.REEF.Utilities\Org.Apache.REEF.Utilities.csproj">
+ <Project>{79E7F89A-1DFB-45E1-8D43-D71A954AEB98}</Project>
+ <Name>Org.Apache.REEF.Utilities</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@@ -109,4 +111,4 @@ under the License.
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client.Tests/RestClientTests.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client.Tests/RestClientTests.cs b/lang/cs/Org.Apache.REEF.Client.Tests/RestClientTests.cs
new file mode 100644
index 0000000..a970cf9
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client.Tests/RestClientTests.cs
@@ -0,0 +1,188 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NSubstitute;
+using Org.Apache.REEF.Client.YARN.RestClient;
+using Org.Apache.REEF.Tang.Implementations.Tang;
+using Org.Apache.REEF.Tang.Util;
+
+namespace Org.Apache.REEF.Client.Tests
+{
+ [TestClass]
+ public class RestClientTests
+ {
+ private const string AnyResource = "anyResource";
+ private const string AnyRootElement = "anyRootElement";
+ private const int AnyIntField = 42;
+ private const string AnyStringField = "AnyStringFieldValue";
+ private const string MediaType = @"application/json";
+
+ private static readonly string ExpectedReturnJson =
+ "{anyRootElement:{\"AnyStringField\":\"" + AnyStringField + "\",\"AnyIntField\":" + AnyIntField + "}}";
+
+ private static readonly string AnyPostContent =
+ "{\"AnyStringField\":\"" + AnyStringField + "\"}";
+
+ private static readonly Uri AnyRequestUri = new Uri("http://any/request/uri");
+ private static readonly Encoding Encoding = Encoding.UTF8;
+
+ [TestMethod]
+ public async Task RestClientGetRequestReturnsResponse()
+ {
+ var tc = new TestContext();
+
+ var client = tc.GetRestClient();
+
+ var anyRequest = new RestRequest
+ {
+ Method = Method.GET,
+ Resource = AnyResource,
+ RootElement = AnyRootElement
+ };
+
+ var successfulResponseMessage = CreateSuccessfulResponseMessage();
+ tc.HttpClient.GetAsync(AnyRequestUri + anyRequest.Resource, CancellationToken.None)
+ .Returns(Task.FromResult(successfulResponseMessage));
+
+ var response =
+ await client.ExecuteRequestAsync<AnyResponse>(anyRequest, AnyRequestUri, CancellationToken.None);
+
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ Assert.AreEqual(AnyStringField, response.Data.AnyStringField);
+ Assert.AreEqual(AnyIntField, response.Data.AnyIntField);
+ Assert.IsNull(response.Exception);
+ var unused = tc.HttpClient.Received(1).GetAsync(AnyRequestUri + anyRequest.Resource, CancellationToken.None);
+ }
+
+ [TestMethod]
+ public async Task RestClientPostRequestReturnsResponse()
+ {
+ var tc = new TestContext();
+
+ var client = tc.GetRestClient();
+
+ var anyRequest = new RestRequest
+ {
+ Method = Method.POST,
+ Resource = AnyResource,
+ RootElement = AnyRootElement,
+ Content = new StringContent(AnyPostContent, Encoding, MediaType)
+ };
+
+ var successfulResponseMessage = CreateSuccessfulResponseMessage();
+ tc.HttpClient.PostAsync(AnyRequestUri + anyRequest.Resource,
+ Arg.Is<StringContent>(
+ stringContent =>
+ stringContent.Headers.ContentType.MediaType == MediaType &&
+ stringContent.ReadAsStringAsync().Result == AnyPostContent),
+ CancellationToken.None)
+ .Returns(Task.FromResult(successfulResponseMessage));
+
+ var response =
+ await client.ExecuteRequestAsync<AnyResponse>(anyRequest, AnyRequestUri, CancellationToken.None);
+
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ Assert.AreEqual(AnyStringField, response.Data.AnyStringField);
+ Assert.AreEqual(AnyIntField, response.Data.AnyIntField);
+ Assert.IsNull(response.Exception);
+ var unused = tc.HttpClient.Received(1).PostAsync(AnyRequestUri + anyRequest.Resource,
+ Arg.Is<StringContent>(
+ stringContent =>
+ stringContent.Headers.ContentType.MediaType == MediaType &&
+ stringContent.ReadAsStringAsync().Result == AnyPostContent),
+ CancellationToken.None);
+ }
+
+ [TestMethod]
+ public async Task RestClientRequestReturnsFailureResponse()
+ {
+ var tc = new TestContext();
+
+ var client = tc.GetRestClient();
+
+ var anyRequest = new RestRequest
+ {
+ Method = Method.GET,
+ Resource = AnyResource,
+ RootElement = AnyRootElement
+ };
+
+ var successfulResponseMessage = CreateFailedResponseMessage();
+ tc.HttpClient.GetAsync(AnyRequestUri + anyRequest.Resource, CancellationToken.None)
+ .Returns(Task.FromResult(successfulResponseMessage));
+
+ var response =
+ await client.ExecuteRequestAsync<AnyResponse>(anyRequest, AnyRequestUri, CancellationToken.None);
+
+ Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode);
+ Assert.IsNull(response.Data);
+ Assert.IsNotNull(response.Exception);
+ Assert.IsInstanceOfType(response.Exception, typeof(HttpRequestException));
+ var unused = tc.HttpClient.Received(1).GetAsync(AnyRequestUri + anyRequest.Resource, CancellationToken.None);
+ }
+
+ private HttpResponseMessage CreateSuccessfulResponseMessage()
+ {
+ return new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(ExpectedReturnJson, Encoding, MediaType)
+ };
+ }
+
+ private HttpResponseMessage CreateFailedResponseMessage()
+ {
+ return new HttpResponseMessage(HttpStatusCode.InternalServerError)
+ {
+ Content = new StringContent("AnyFailedContent", Encoding, MediaType)
+ };
+ }
+
+ private class TestContext
+ {
+ public readonly IHttpClient HttpClient = Substitute.For<IHttpClient>();
+
+ public readonly IDeserializer Deserializer = Substitute.For<IDeserializer>();
+
+ public IRestClient GetRestClient()
+ {
+ var injector = TangFactory.GetTang().NewInjector();
+ injector.BindVolatileInstance(GenericType<IHttpClient>.Class, HttpClient);
+ ////injector.BindVolatileInstance(GenericType<IDeserializer>.Class, Deserializer);
+ return injector.GetInstance<IRestClient>();
+ }
+ }
+
+ private class AnyResponse
+ {
+ public string AnyStringField { get; set; }
+
+ public int AnyIntField { get; set; }
+ }
+
+ private class AnyRequest
+ {
+ public string AnyStringField { get; set; }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client.Tests/YarnClientTests.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client.Tests/YarnClientTests.cs b/lang/cs/Org.Apache.REEF.Client.Tests/YarnClientTests.cs
index fe07cc0..3858b12 100644
--- a/lang/cs/Org.Apache.REEF.Client.Tests/YarnClientTests.cs
+++ b/lang/cs/Org.Apache.REEF.Client.Tests/YarnClientTests.cs
@@ -27,7 +27,7 @@ using Org.Apache.REEF.Client.YARN.RestClient;
using Org.Apache.REEF.Client.YARN.RestClient.DataModel;
using Org.Apache.REEF.Tang.Implementations.Tang;
using Org.Apache.REEF.Tang.Util;
-using RestSharp;
+using Org.Apache.REEF.Utilities.AsyncUtils;
using Xunit;
namespace Org.Apache.REEF.Client.Tests
@@ -50,7 +50,7 @@ namespace Org.Apache.REEF.Client.Tests
HadoopVersionBuiltOn = "AnyVersionBuildOn",
};
restReqExecutor.ExecuteAsync<ClusterInfo>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/info" && req.RootElement == "clusterInfo" &&
req.Method == Method.GET),
@@ -82,7 +82,7 @@ namespace Org.Apache.REEF.Client.Tests
AppsCompleted = 301
};
restReqExecutor.ExecuteAsync<ClusterMetrics>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/metrics" && req.RootElement == "clusterMetrics" &&
req.Method == Method.GET),
@@ -116,7 +116,7 @@ namespace Org.Apache.REEF.Client.Tests
RunningContainers = 0
};
restReqExecutor.ExecuteAsync<Application>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/apps/" + applicationId
&& req.RootElement == "app"
@@ -152,7 +152,7 @@ namespace Org.Apache.REEF.Client.Tests
RunningContainers = 0
};
restReqExecutor.ExecuteAsync<Application>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/apps/" + applicationId
&& req.RootElement == "app"
@@ -181,7 +181,7 @@ namespace Org.Apache.REEF.Client.Tests
ApplicationId = applicationId
};
restReqExecutor.ExecuteAsync<NewApplication>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/apps/new-application"
&& req.Method == Method.POST),
@@ -298,30 +298,23 @@ namespace Org.Apache.REEF.Client.Tests
RunningContainers = 0
};
- var response = Substitute.For<IRestResponse>();
- response.Headers.Returns(new List<Parameter>
+ var response = new RestResponse<VoidResult>
{
- new Parameter
- {
- Name = "Location",
- Value = "http://somelocation"
- }
- });
- response.StatusCode.Returns(HttpStatusCode.Accepted);
+ StatusCode = HttpStatusCode.Accepted
+ };
restReqExecutor.ExecuteAsync(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/apps"
&& req.Method == Method.POST
- && req.JsonSerializer is RestJsonSerializer
- && req.Parameters.First().Name == "application/json"
+ && req.Content.Headers.ContentType.MediaType == "application/json"
&& IsExpectedJson(req, expectedJson)),
anyUri.First(),
CancellationToken.None).Returns(Task.FromResult(response));
restReqExecutor.ExecuteAsync<Application>(
- Arg.Is<IRestRequest>(
+ Arg.Is<RestRequest>(
req =>
req.Resource == "ws/v1/cluster/apps/" + applicationId
&& req.RootElement == "app"
@@ -336,9 +329,9 @@ namespace Org.Apache.REEF.Client.Tests
var unused = urlProvider.Received(2).GetUrlAsync();
}
- private static bool IsExpectedJson(IRestRequest req, string expectedJson)
+ private static bool IsExpectedJson(RestRequest req, string expectedJson)
{
- return (string)req.Parameters.First().Value == expectedJson;
+ return req.Content.ReadAsStringAsync().Result == expectedJson;
}
private class TestContext
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client.Tests/packages.config
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client.Tests/packages.config b/lang/cs/Org.Apache.REEF.Client.Tests/packages.config
index 779566d..4a71ef7 100644
--- a/lang/cs/Org.Apache.REEF.Client.Tests/packages.config
+++ b/lang/cs/Org.Apache.REEF.Client.Tests/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,7 +19,6 @@ under the License.
-->
<packages>
<package id="NSubstitute" version="1.8.2.0" targetFramework="net45" />
- <package id="RestSharpSigned" version="105.2.3" targetFramework="net45" />
<package id="StyleCop.MSBuild" version="4.7.49.1" targetFramework="net45" developmentDependency="true" />
<package id="xunit" version="2.1.0" targetFramework="net45" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net45" />
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj b/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
index df01b65..91a2114 100644
--- a/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
+++ b/lang/cs/Org.Apache.REEF.Client/Org.Apache.REEF.Client.csproj
@@ -38,12 +38,13 @@ under the License.
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
+ <Reference Include="Microsoft.Practices.TransientFaultHandling.Core, Version=5.1.1209.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>$(PackagesDir)\TransientFaultHandling.Core.5.1.1209.1\lib\NET4\Microsoft.Practices.TransientFaultHandling.Core.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(PackagesDir)\Newtonsoft.Json.$(NewtonsoftJsonVersion)\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="RestSharp, Version=100.0.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
- <HintPath>$(PackagesDir)\RestSharpSigned.105.2.3\lib\net45\RestSharp.dll</HintPath>
- </Reference>
<Reference Include="Microsoft.Hadoop.Avro">
<HintPath>$(PackagesDir)\Microsoft.Hadoop.Avro.$(AvroVersion)\lib\net45\Microsoft.Hadoop.Avro.dll</HintPath>
</Reference>
@@ -52,6 +53,7 @@ under the License.
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Runtime.Serialization" />
@@ -95,6 +97,20 @@ under the License.
<Compile Include="YARN\IJobSubmissionDirectoryProvider.cs" />
<Compile Include="YARN\Parameters\DriverMaxMemoryAllicationPoolSizeMB.cs" />
<Compile Include="YARN\Parameters\DriverMaxPermSizeMB.cs" />
+ <Compile Include="YARN\RestClient\HttpClient.cs" />
+ <Compile Include="YARN\RestClient\IDeserializer.cs" />
+ <Compile Include="YARN\RestClient\IHttpClient.cs" />
+ <Compile Include="YARN\RestClient\IRequestFactory.cs" />
+ <Compile Include="YARN\RestClient\IRestClient.cs" />
+ <Compile Include="YARN\RestClient\ISerializer.cs" />
+ <Compile Include="YARN\RestClient\Method.cs" />
+ <Compile Include="YARN\RestClient\RequestFactory.cs" />
+ <Compile Include="YARN\RestClient\RestClient.cs" />
+ <Compile Include="YARN\RestClient\RestJsonDeserializer.cs" />
+ <Compile Include="YARN\RestClient\RestJsonSerializer.cs" />
+ <Compile Include="YARN\RestClient\RestRequest.cs" />
+ <Compile Include="YARN\RestClient\RestResponse.cs" />
+ <Compile Include="YARN\RestClient\HttpClientRetryHandler.cs" />
<Compile Include="YARN\WindowsYarnJobCommandProvider.cs" />
<Compile Include="YARN\JobResource.cs" />
<Compile Include="YARN\JobSubmissionDirectoryProvider.cs" />
@@ -121,11 +137,8 @@ under the License.
<Compile Include="YARN\RestClient\IUrlProvider.cs" />
<Compile Include="YARN\RestClient\FileSystemJobResourceUploader.cs" />
<Compile Include="YARN\RestClient\MultipleRMUrlProvider.cs" />
- <Compile Include="YARN\RestClient\RestJsonDeserializer.cs" />
- <Compile Include="YARN\RestClient\RestJsonSerializer.cs" />
<Compile Include="YARN\YarnJobSubmissionResult.cs" />
<Compile Include="YARN\YARNREEFClient.cs" />
- <Compile Include="YARN\RestClient\IRestClientFactory.cs" />
<Compile Include="YARN\RestClient\RestRequestExecutor.cs" />
<Compile Include="YARN\RestClient\IYarnRMClient.cs" />
<Compile Include="YARN\RestClient\DataModel\Application.cs" />
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClient.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClient.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClient.cs
new file mode 100644
index 0000000..6d636d2
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClient.cs
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Pass through HTTP client which calls into <see cref="System.Net.Http.HttpClient"/>
+ /// </summary>
+ internal class HttpClient : IHttpClient
+ {
+ private readonly System.Net.Http.HttpClient _httpClient;
+
+ [Inject]
+ private HttpClient()
+ {
+ _httpClient = new System.Net.Http.HttpClient(
+ new HttpClientRetryHandler(new WebRequestHandler()),
+ disposeHandler: false);
+ }
+
+ public async Task<HttpResponseMessage> GetAsync(string requestResource, CancellationToken cancellationToken)
+ {
+ return await _httpClient.GetAsync(requestResource, cancellationToken);
+ }
+
+ public async Task<HttpResponseMessage> PostAsync(string requestResource,
+ StringContent content,
+ CancellationToken cancellationToken)
+ {
+ return await _httpClient.PostAsync(requestResource, content, cancellationToken);
+ }
+
+ public async Task<HttpResponseMessage> PutAsync(string requestResource,
+ StringContent content,
+ CancellationToken cancellationToken)
+ {
+ return await _httpClient.PutAsync(requestResource, content, cancellationToken);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClientRetryHandler.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClientRetryHandler.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClientRetryHandler.cs
new file mode 100644
index 0000000..ccc9052
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/HttpClientRetryHandler.cs
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Practices.TransientFaultHandling;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// DelegatingHandler for retrying requests with HTTP client
+ /// </summary>
+ internal class HttpClientRetryHandler : DelegatingHandler
+ {
+ private const int RetryCount = 3;
+ private static readonly TimeSpan MinBackoffTimeSpan = TimeSpan.FromMilliseconds(100);
+ private static readonly TimeSpan MaxBackoffTimeSpan = TimeSpan.FromSeconds(5);
+ private static readonly TimeSpan DeltaBackoffTimeSpan = TimeSpan.FromMilliseconds(500);
+
+ private readonly RetryPolicy<AllErrorsTransientStrategy> _retryPolicy;
+
+ public HttpClientRetryHandler(HttpMessageHandler innerHandler)
+ : base(innerHandler)
+ {
+ this._retryPolicy = new RetryPolicy<AllErrorsTransientStrategy>(
+ new ExponentialBackoff(
+ "YarnRESTRetryHandler",
+ RetryCount,
+ MinBackoffTimeSpan,
+ MaxBackoffTimeSpan,
+ DeltaBackoffTimeSpan,
+ firstFastRetry: true));
+ }
+
+ protected override async Task<HttpResponseMessage> SendAsync(
+ HttpRequestMessage request,
+ CancellationToken cancellationToken)
+ {
+ return await this._retryPolicy.ExecuteAsync(
+ async () => await base.SendAsync(request, cancellationToken),
+ cancellationToken);
+ }
+ }
+
+ internal class AllErrorsTransientStrategy : ITransientErrorDetectionStrategy
+ {
+ public bool IsTransient(Exception ex)
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IDeserializer.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IDeserializer.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IDeserializer.cs
new file mode 100644
index 0000000..869a157
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IDeserializer.cs
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Deserialize from string representation to corresponding data model object
+ /// </summary>
+ [DefaultImplementation(typeof(RestJsonDeserializer))]
+ internal interface IDeserializer
+ {
+ /// <summary>
+ /// Deserialize content string to <typeparam name="T"></typeparam>
+ /// </summary>
+ T Deserialize<T>(string contentString, string rootElement);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IHttpClient.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IHttpClient.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IHttpClient.cs
new file mode 100644
index 0000000..366dd29
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IHttpClient.cs
@@ -0,0 +1,37 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Wrapper interface on <see cref="System.Net.Http.HttpClient"/> for ease of unit-testing
+ /// </summary>
+ [DefaultImplementation(typeof(HttpClient))]
+ internal interface IHttpClient
+ {
+ Task<HttpResponseMessage> GetAsync(string requestResource, CancellationToken cancellationToken);
+
+ Task<HttpResponseMessage> PostAsync(string requestResource, StringContent content, CancellationToken cancellationToken);
+
+ Task<HttpResponseMessage> PutAsync(string requestResource, StringContent content, CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRequestFactory.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRequestFactory.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRequestFactory.cs
new file mode 100644
index 0000000..ecef9f5
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRequestFactory.cs
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Factory for generating REST requests
+ /// </summary>
+ [DefaultImplementation(typeof(RequestFactory))]
+ internal interface IRequestFactory
+ {
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ RestRequest CreateRestRequest(string resourcePath, Method method);
+
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ RestRequest CreateRestRequest(string resourcePath, Method method, string rootElement);
+
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ RestRequest CreateRestRequest(string resourcePath, Method method, string rootElement, object body);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClient.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClient.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClient.cs
new file mode 100644
index 0000000..4ac1654
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClient.cs
@@ -0,0 +1,43 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.AsyncUtils;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Interface for the client that executes the RestRequests and handles
+ /// errors and retries
+ /// </summary>
+ [DefaultImplementation(typeof(RestClient))]
+ internal interface IRestClient
+ {
+ /// <summary>
+ /// Execute request where the response is expected to be type T
+ /// </summary>
+ Task<RestResponse<T>> ExecuteRequestAsync<T>(RestRequest request, Uri requestBaseUri, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Execute request where no response object is expected
+ /// </summary>
+ Task<RestResponse<VoidResult>> ExecuteRequestAsync(RestRequest request, Uri requestBaseUri, CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClientFactory.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClientFactory.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClientFactory.cs
deleted file mode 100644
index 77e813d..0000000
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestClientFactory.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-using System;
-using Org.Apache.REEF.Client.YARN.RestClient;
-using Org.Apache.REEF.Tang.Annotations;
-using RestSharp;
-
-namespace Org.Apache.REEF.Client.Yarn.RestClient
-{
- [DefaultImplementation(typeof(RestClientFactory))]
- internal interface IRestClientFactory
- {
- IRestClient CreateRestClient(Uri baseUri);
- }
-
- internal class RestClientFactory : IRestClientFactory
- {
- [Inject]
- private RestClientFactory()
- {
- }
-
- public IRestClient CreateRestClient(Uri baseUri)
- {
- // TODO: We are creating a new client per request
- // as one client can contact only one baseUri.
- // This is not very bad but it might still be worth
- // it to cache clients per baseUri in the future.
- var restClient = new RestSharp.RestClient(baseUri)
- {
- FollowRedirects = true
- };
- restClient.AddHandler("application/json", new RestJsonDeserializer());
- return restClient;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestRequestExecutor.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestRequestExecutor.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestRequestExecutor.cs
index 7bb492a..ca4e2bc 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestRequestExecutor.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/IRestRequestExecutor.cs
@@ -18,21 +18,31 @@
using System;
using System.Threading;
using System.Threading.Tasks;
+using Org.Apache.REEF.Client.YARN.RestClient;
using Org.Apache.REEF.Tang.Annotations;
-using RestSharp;
+using Org.Apache.REEF.Utilities.AsyncUtils;
namespace Org.Apache.REEF.Client.Yarn.RestClient
{
+ /// <summary>
+ /// Executes a REST request
+ /// </summary>
[DefaultImplementation(typeof(RestRequestExecutor))]
internal interface IRestRequestExecutor
{
+ /// <summary>
+ /// Executes a REST request where a response is expected
+ /// </summary>
Task<T> ExecuteAsync<T>(
- IRestRequest request,
+ RestRequest request,
Uri uri,
- CancellationToken cancellationToken) where T : new();
+ CancellationToken cancellationToken);
- Task<IRestResponse> ExecuteAsync(
- IRestRequest request,
+ /// <summary>
+ /// Executes a REST request where a response is NOT expected
+ /// </summary>
+ Task<RestResponse<VoidResult>> ExecuteAsync(
+ RestRequest request,
Uri uri,
CancellationToken cancellationToken);
}
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/ISerializer.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/ISerializer.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/ISerializer.cs
new file mode 100644
index 0000000..abea5c6
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/ISerializer.cs
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Serializes a data model object to string
+ /// </summary>
+ [DefaultImplementation(typeof(RestJsonSerializer))]
+ internal interface ISerializer
+ {
+ /// <summary>
+ /// Serializes <param name="obj"></param> to <see cref="string"/>
+ /// </summary>
+ string Serialize(object obj);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/Method.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/Method.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/Method.cs
new file mode 100644
index 0000000..2b78e71
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/Method.cs
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ internal enum Method
+ {
+ INVALID,
+ GET,
+ POST,
+ PUT
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RequestFactory.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RequestFactory.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RequestFactory.cs
new file mode 100644
index 0000000..b499c55
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RequestFactory.cs
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Net.Http;
+using System.Text;
+using Org.Apache.REEF.Tang.Annotations;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Factory to generate REST requests
+ /// </summary>
+ internal class RequestFactory : IRequestFactory
+ {
+ private readonly ISerializer _serializer;
+ private readonly string _baseResourceString;
+
+ [Inject]
+ private RequestFactory(ISerializer serializer)
+ {
+ _serializer = serializer;
+ _baseResourceString = @"ws/v1/";
+ }
+
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ public RestRequest CreateRestRequest(string resourcePath, Method method)
+ {
+ return CreateRestRequest(resourcePath, method, null);
+ }
+
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ public RestRequest CreateRestRequest(string resourcePath, Method method, string rootElement)
+ {
+ return CreateRestRequest(resourcePath, method, rootElement, null);
+ }
+
+ /// <summary>
+ /// Generate REST request
+ /// </summary>
+ public RestRequest CreateRestRequest(string resourcePath, Method method, string rootElement, object body)
+ {
+ var request = new RestRequest
+ {
+ Resource = _baseResourceString + resourcePath,
+ RootElement = rootElement,
+ Method = method,
+ };
+
+ if (body != null)
+ {
+ string content = _serializer.Serialize(body);
+ request.Content = new StringContent(content, Encoding.UTF8, @"application/json");
+ }
+
+ return request;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestClient.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestClient.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestClient.cs
new file mode 100644
index 0000000..d034c73
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestClient.cs
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.AsyncUtils;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Implementation of RestClient which uses HTTPClient to
+ /// make REST requests and handles errors
+ /// </summary>
+ internal class RestClient : IRestClient
+ {
+ private readonly IDeserializer _deserializer;
+ private readonly IHttpClient _httpClient;
+
+ [Inject]
+ private RestClient(IDeserializer deserializer, IHttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ _deserializer = deserializer;
+ }
+
+ /// <summary>
+ /// Execute request where no response object is expected
+ /// </summary>
+ public async Task<RestResponse<VoidResult>> ExecuteRequestAsync(
+ RestRequest request,
+ Uri requestBaseUri,
+ CancellationToken cancellationToken)
+ {
+ var httpResponseMessage = await GetHttpResponseAsync(request, requestBaseUri, cancellationToken);
+ Exception exception = null;
+ if (!httpResponseMessage.IsSuccessStatusCode)
+ {
+ exception =
+ new HttpRequestException(string.Format("HTTP call failed with status [{0}] and content [{1}]",
+ httpResponseMessage.StatusCode,
+ await GetContentStringFromHttpResponseMessage(httpResponseMessage)));
+ }
+
+ return new RestResponse<VoidResult>
+ {
+ Data = new VoidResult(),
+ Exception = exception,
+ StatusCode = httpResponseMessage.StatusCode
+ };
+ }
+
+ /// <summary>
+ /// Execute request where the response is expected to be type T
+ /// </summary>
+ public async Task<RestResponse<T>> ExecuteRequestAsync<T>(
+ RestRequest request,
+ Uri requestBaseUri,
+ CancellationToken cancellationToken)
+ {
+ var httpResponseMessage = await GetHttpResponseAsync(request, requestBaseUri, cancellationToken);
+ string contentString = await GetContentStringFromHttpResponseMessage(httpResponseMessage);
+ Exception exception = null;
+ T returnObj = default(T);
+
+ if (!httpResponseMessage.IsSuccessStatusCode)
+ {
+ exception =
+ new HttpRequestException(string.Format("HTTP call failed with status [{0}] and content [{1}]",
+ httpResponseMessage.StatusCode,
+ contentString));
+ }
+ else
+ {
+ returnObj = _deserializer.Deserialize<T>(contentString,
+ request.RootElement);
+ }
+ return new RestResponse<T>
+ {
+ Content = contentString,
+ Data = returnObj,
+ StatusCode = httpResponseMessage.StatusCode,
+ Exception = exception
+ };
+ }
+
+ private async Task<HttpResponseMessage> GetHttpResponseAsync(
+ RestRequest request,
+ Uri requestBaseUri,
+ CancellationToken cancellationToken)
+ {
+ HttpResponseMessage httpResponseMessage;
+ var requestResource = requestBaseUri + request.Resource;
+ switch (request.Method)
+ {
+ case Method.GET:
+ httpResponseMessage = await _httpClient.GetAsync(
+ requestResource,
+ cancellationToken);
+ break;
+ case Method.PUT:
+ httpResponseMessage = await _httpClient.PutAsync(
+ requestResource,
+ request.Content,
+ cancellationToken);
+ break;
+ case Method.POST:
+ httpResponseMessage = await _httpClient.PostAsync(
+ requestResource,
+ request.Content,
+ cancellationToken);
+ break;
+ default:
+ throw new InvalidOperationException(string.Format("Unknown method type {0}", request.Method));
+ }
+
+ return httpResponseMessage;
+ }
+
+ private static async Task<string> GetContentStringFromHttpResponseMessage(HttpResponseMessage response)
+ {
+ return response.Content == null ? string.Empty : await response.Content.ReadAsStringAsync();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonDeserializer.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonDeserializer.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonDeserializer.cs
index aa6fd7b..c58f3b4 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonDeserializer.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonDeserializer.cs
@@ -18,18 +18,21 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
-using RestSharp;
-using RestSharp.Deserializers;
+using Org.Apache.REEF.Tang.Annotations;
namespace Org.Apache.REEF.Client.YARN.RestClient
{
+ /// <summary>
+ /// Simple implementation of JSON deserializer by using Newtonsoft JSON lib
+ /// </summary>
internal sealed class RestJsonDeserializer : IDeserializer
{
- public string RootElement { get; set; }
- public string Namespace { get; set; }
- public string DateFormat { get; set; }
+ [Inject]
+ private RestJsonDeserializer()
+ {
+ }
- public T Deserialize<T>(IRestResponse response)
+ public T Deserialize<T>(string contentString, string rootElement)
{
/* If root element is not empty, then we want to
* skip the top level token and parse only one level deeper
@@ -49,17 +52,17 @@ namespace Org.Apache.REEF.Client.YARN.RestClient
* }
*
* This logic helps us avoid such classes.
- */
- if (!string.IsNullOrEmpty(RootElement))
+ */
+ if (string.IsNullOrEmpty(rootElement))
{
- var jobject = JObject.Parse(response.Content);
- var jtoken = jobject[RootElement];
- var jsonSerializer = new JsonSerializer();
- jsonSerializer.Converters.Add(new StringEnumConverter());
- return jtoken.ToObject<T>(jsonSerializer);
+ return JsonConvert.DeserializeObject<T>(contentString, new StringEnumConverter());
}
- return JsonConvert.DeserializeObject<T>(response.Content, new StringEnumConverter());
+ var jobject = JObject.Parse(contentString);
+ var jtoken = jobject[rootElement];
+ var jsonSerializer = new JsonSerializer();
+ jsonSerializer.Converters.Add(new StringEnumConverter());
+ return jtoken.ToObject<T>(jsonSerializer);
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonSerializer.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonSerializer.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonSerializer.cs
index abd88b9..14eb5b8 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonSerializer.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestJsonSerializer.cs
@@ -17,34 +17,30 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
-using RestSharp.Serializers;
+using Newtonsoft.Json.Serialization;
+using Org.Apache.REEF.Tang.Annotations;
namespace Org.Apache.REEF.Client.YARN.RestClient
{
/// <summary>
- /// RestSharp by default uses SimpleJsonSerializer which
- /// does not understand property renaming. Here we create a
- /// simple ISerializer implementation that uses Newtonsoft.Json
- /// for performing serialization
+ /// Simple implementation of JSON serializer by using Newtonsoft JSON lib
/// </summary>
internal sealed class RestJsonSerializer : ISerializer
{
- public RestJsonSerializer()
+ private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
{
- ContentType = "application/json";
- }
-
- public string RootElement { get; set; }
-
- public string Namespace { get; set; }
+ ContractResolver = new CamelCasePropertyNamesContractResolver(),
+ Converters = new JsonConverter[] { new StringEnumConverter() }
+ };
- public string DateFormat { get; set; }
-
- public string ContentType { get; set; }
+ [Inject]
+ private RestJsonSerializer()
+ {
+ }
public string Serialize(object obj)
{
- return JsonConvert.SerializeObject(obj, new StringEnumConverter());
+ return JsonConvert.SerializeObject(obj, _jsonSerializerSettings);
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequest.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequest.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequest.cs
new file mode 100644
index 0000000..a70191c
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequest.cs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Net.Http;
+using System.Text;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Encapsulated data related to a REST request
+ /// </summary>
+ internal class RestRequest
+ {
+ /// <summary>
+ /// Path to the resource being accessed
+ /// This path is relative to the base path.
+ /// </summary>
+ public string Resource { get; set; }
+
+ /// <summary>
+ /// Root element (if any) in the response JSON
+ /// </summary>
+ public string RootElement { get; set; }
+
+ /// <summary>
+ /// HTTP method to be invoked for the request
+ /// </summary>
+ public Method Method { get; set; }
+
+ /// <summary>
+ /// The serialized string content for the request
+ /// </summary>
+ public StringContent Content { get; internal set; }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequestExecutor.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequestExecutor.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequestExecutor.cs
index 75187a5..538c705 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequestExecutor.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestRequestExecutor.cs
@@ -5,9 +5,9 @@
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
-//
+//
// http://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,73 +20,103 @@ using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
+using Org.Apache.REEF.Client.YARN.RestClient;
using Org.Apache.REEF.Client.YARN.RestClient.DataModel;
using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Utilities.AsyncUtils;
using Org.Apache.REEF.Utilities.Logging;
-using RestSharp;
namespace Org.Apache.REEF.Client.Yarn.RestClient
{
+ /// <summary>
+ /// Executes a REST request
+ /// </summary>
internal class RestRequestExecutor : IRestRequestExecutor
{
private static readonly Logger Log = Logger.GetLogger(typeof(RestRequestExecutor));
- private readonly IRestClientFactory _clientFactory;
+ private readonly IRestClient _client;
[Inject]
private RestRequestExecutor(
- IRestClientFactory clientFactory)
+ IRestClient client)
{
- _clientFactory = clientFactory;
+ _client = client;
}
public async Task<T> ExecuteAsync<T>(
- IRestRequest request,
+ RestRequest request,
Uri requestUri,
- CancellationToken cancellationToken) where T : new()
+ CancellationToken cancellationToken)
{
- var client = _clientFactory.CreateRestClient(requestUri);
-
- var response =
- await
- client.ExecuteTaskAsync<T>(request, cancellationToken);
-
- if (response.ErrorException != null)
+ RestResponse<T> response;
+ try
{
- throw new YarnRestAPIException("Executing REST API failed", response.ErrorException);
+ response = await _client.ExecuteRequestAsync<T>(request, requestUri, cancellationToken);
+ }
+ catch (Exception exception)
+ {
+ throw new YarnRestAPIException("Unhandled exception in executing REST request.", exception);
}
+ HandleResponse(response.Exception, response.StatusCode, response.Content);
+
+ return response.Data;
+ }
+
+ public async Task<RestResponse<VoidResult>> ExecuteAsync(RestRequest request,
+ Uri requestUri,
+ CancellationToken cancellationToken)
+ {
+ RestResponse<VoidResult> response;
try
{
- // HTTP status code greater than 300 is unexpected here.
- // See if the server sent a error response and throw suitable
- // exception to user.
- if (response.StatusCode >= HttpStatusCode.Ambiguous)
- {
- Log.Log(Level.Error, "RESTRequest failed. StatusCode: {0}; Response: {1}", response.StatusCode, response.Content);
- var errorResponse = JsonConvert.DeserializeObject<Error>(response.Content);
- throw new YarnRestAPIException { Error = errorResponse };
- }
+ response = await _client.ExecuteRequestAsync(request, requestUri, cancellationToken);
}
catch (Exception exception)
{
- throw new YarnRestAPIException("Unhandled exception in deserializing error response.", exception);
+ throw new YarnRestAPIException("Unhandled exception in executing REST request.", exception);
}
- return response.Data;
+ HandleResponse(response.Exception, response.StatusCode, response.Content);
+ return response;
}
- public async Task<IRestResponse> ExecuteAsync(IRestRequest request, Uri uri, CancellationToken cancellationToken)
+ private static void HandleResponse(Exception responseException, HttpStatusCode httpStatusCode, string content)
{
- var client = _clientFactory.CreateRestClient(uri);
+ if (responseException != null)
+ {
+ throw new YarnRestAPIException("Executing REST API failed", responseException)
+ {
+ StatusCode = httpStatusCode
+ };
+ }
+ // HTTP status code greater than 300 is unexpected here.
+ // See if the server sent a error response and throw suitable
+ // exception to user.
+ if (httpStatusCode < HttpStatusCode.Ambiguous)
+ {
+ return;
+ }
+
+ Log.Log(Level.Error,
+ "RESTRequest failed. StatusCode: {0}; Response: {1}",
+ httpStatusCode,
+ content);
+ Error errorResponse;
try
{
- return await client.ExecuteTaskAsync(request, cancellationToken);
+ errorResponse = JsonConvert.DeserializeObject<Error>(content);
}
catch (Exception exception)
{
- throw new YarnRestAPIException("Unhandled exception in executing REST request.", exception);
+ throw new YarnRestAPIException("Unhandled exception in deserializing error response.", exception)
+ {
+ StatusCode = httpStatusCode
+ };
}
+
+ throw new YarnRestAPIException { Error = errorResponse, StatusCode = httpStatusCode };
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestResponse.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestResponse.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestResponse.cs
new file mode 100644
index 0000000..87872c6
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/RestResponse.cs
@@ -0,0 +1,50 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Net;
+
+namespace Org.Apache.REEF.Client.YARN.RestClient
+{
+ /// <summary>
+ /// Represents the response of a REST request
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ internal class RestResponse<T>
+ {
+ /// <summary>
+ /// Deserialized response for REST request
+ /// </summary>
+ public T Data { get; set; }
+
+ /// <summary>
+ /// StatusCode of the REST response
+ /// </summary>
+ public HttpStatusCode StatusCode { get; set; }
+
+ /// <summary>
+ /// Exception details if a communication/protocol
+ /// error happened while processing the request
+ /// </summary>
+ public Exception Exception { get; set; }
+
+ /// <summary>
+ /// String content (serialized) of the response
+ /// </summary>
+ public string Content { get; set; }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnClient.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnClient.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnClient.cs
index 62f0c14..ec47d8b 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnClient.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnClient.cs
@@ -26,7 +26,6 @@ using Org.Apache.REEF.Client.YARN.RestClient.DataModel;
using Org.Apache.REEF.Tang.Annotations;
using Org.Apache.REEF.Utilities.AsyncUtils;
using Org.Apache.REEF.Utilities.Logging;
-using RestSharp;
namespace Org.Apache.REEF.Client.Yarn.RestClient
{
@@ -39,15 +38,18 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
internal sealed partial class YarnClient : IYarnRMClient
{
private static readonly Logger Logger = Logger.GetLogger(typeof(YarnClient));
- private readonly string _baseResourceString;
private readonly IUrlProvider _yarnRmUrlProviderUri;
private readonly IRestRequestExecutor _restRequestExecutor;
+ private readonly IRequestFactory _requestFactory;
[Inject]
- internal YarnClient(IUrlProvider yarnRmUrlProviderUri, IRestRequestExecutor restRequestExecutor)
+ private YarnClient(
+ IUrlProvider yarnRmUrlProviderUri,
+ IRestRequestExecutor restRequestExecutor,
+ IRequestFactory requestFactory)
{
+ _requestFactory = requestFactory;
_yarnRmUrlProviderUri = yarnRmUrlProviderUri;
- _baseResourceString = @"ws/v1/";
_restRequestExecutor = restRequestExecutor;
}
@@ -55,7 +57,10 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
{
await new RemoveSynchronizationContextAwaiter();
- IRestRequest request = CreateRestRequest(ClusterInfo.Resource, Method.GET, ClusterInfo.RootElement);
+ var request = _requestFactory.CreateRestRequest(
+ ClusterInfo.Resource,
+ Method.GET,
+ ClusterInfo.RootElement);
return
await GenerateUrlAndExecuteRequestAsync<ClusterInfo>(request, cancellationToken);
@@ -65,7 +70,9 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
{
await new RemoveSynchronizationContextAwaiter();
- var request = CreateRestRequest(ClusterMetrics.Resource, Method.GET, ClusterMetrics.RootElement);
+ var request = _requestFactory.CreateRestRequest(ClusterMetrics.Resource,
+ Method.GET,
+ ClusterMetrics.RootElement);
return
await
@@ -76,7 +83,9 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
{
await new RemoveSynchronizationContextAwaiter();
- var request = CreateRestRequest(Application.Resource + appId, Method.GET, Application.RootElement);
+ var request = _requestFactory.CreateRestRequest(Application.Resource + appId,
+ Method.GET,
+ Application.RootElement);
return
await GenerateUrlAndExecuteRequestAsync<Application>(request, cancellationToken);
@@ -86,7 +95,7 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
{
await new RemoveSynchronizationContextAwaiter();
- var request = CreateRestRequest(NewApplication.Resource, Method.POST);
+ var request = _requestFactory.CreateRestRequest(NewApplication.Resource, Method.POST);
return
await
@@ -99,38 +108,26 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
{
await new RemoveSynchronizationContextAwaiter();
- var request = CreateRestRequest(SubmitApplication.Resource, Method.POST);
+ var request = _requestFactory.CreateRestRequest(
+ SubmitApplication.Resource,
+ Method.POST,
+ rootElement: null,
+ body: submitApplication);
- request.AddBody(submitApplication);
var submitResponse = await GenerateUrlAndExecuteRequestAsync(request, cancellationToken);
if (submitResponse.StatusCode != HttpStatusCode.Accepted)
{
throw new YarnRestAPIException(
string.Format("Application submission failed with HTTP STATUS {0}",
- submitResponse.StatusCode));
+ submitResponse.StatusCode));
}
return await GetApplicationAsync(submitApplication.ApplicationId, cancellationToken);
}
- private RestRequest CreateRestRequest(string resourcePath, Method method, string rootElement = null)
- {
- var request = new RestRequest
- {
- Resource = _baseResourceString + resourcePath,
- RootElement = rootElement,
- Method = method,
- RequestFormat = DataFormat.Json,
- JsonSerializer = new RestJsonSerializer()
- };
-
- return request;
- }
-
- private async Task<T> GenerateUrlAndExecuteRequestAsync<T>(IRestRequest request,
+ private async Task<T> GenerateUrlAndExecuteRequestAsync<T>(RestRequest request,
CancellationToken cancellationToken)
- where T : new()
{
IEnumerable<Uri> yarnRmUris = await _yarnRmUrlProviderUri.GetUrlAsync();
var exceptions = new List<Exception>();
@@ -145,7 +142,7 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
catch (Exception e)
{
exceptions.Add(e);
- Logger.Log(Level.Verbose,
+ Logger.Log(Level.Verbose,
string.Format(CultureInfo.CurrentCulture, "Possibly transient error in rest call {0}", e.Message));
}
}
@@ -153,7 +150,7 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
throw new AggregateException("Failed Rest Request", exceptions);
}
- private async Task<IRestResponse> GenerateUrlAndExecuteRequestAsync(IRestRequest request,
+ private async Task<RestResponse<VoidResult>> GenerateUrlAndExecuteRequestAsync(RestRequest request,
CancellationToken cancellationToken)
{
IEnumerable<Uri> yarnRmUris = await _yarnRmUrlProviderUri.GetUrlAsync();
@@ -169,7 +166,7 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
catch (Exception e)
{
exceptions.Add(e);
- Logger.Log(Level.Verbose,
+ Logger.Log(Level.Verbose,
string.Format(CultureInfo.CurrentCulture, "Possibly transient error in rest call {0}", e.Message));
}
}
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnRestAPIException.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnRestAPIException.cs b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnRestAPIException.cs
index 7ee9889..b25a30c 100644
--- a/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnRestAPIException.cs
+++ b/lang/cs/Org.Apache.REEF.Client/YARN/RESTClient/YarnRestAPIException.cs
@@ -16,6 +16,7 @@
// under the License.
using System;
+using System.Net;
using Org.Apache.REEF.Client.YARN.RestClient.DataModel;
namespace Org.Apache.REEF.Client.Yarn.RestClient
@@ -38,5 +39,7 @@ namespace Org.Apache.REEF.Client.Yarn.RestClient
}
public Error Error { get; internal set; }
+
+ public HttpStatusCode StatusCode { get; internal set; }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Client/packages.config
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Client/packages.config b/lang/cs/Org.Apache.REEF.Client/packages.config
index 827a433..63005d5 100644
--- a/lang/cs/Org.Apache.REEF.Client/packages.config
+++ b/lang/cs/Org.Apache.REEF.Client/packages.config
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,6 +19,6 @@ under the License.
-->
<packages>
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
- <package id="RestSharpSigned" version="105.2.3" targetFramework="net45" />
<package id="StyleCop.MSBuild" version="4.7.49.1" targetFramework="net45" developmentDependency="true" />
+ <package id="TransientFaultHandling.Core" version="5.1.1209.1" targetFramework="net45" />
</packages>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Utilities/AsyncUtils/VoidResult.cs
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Utilities/AsyncUtils/VoidResult.cs b/lang/cs/Org.Apache.REEF.Utilities/AsyncUtils/VoidResult.cs
new file mode 100644
index 0000000..a9404a4
--- /dev/null
+++ b/lang/cs/Org.Apache.REEF.Utilities/AsyncUtils/VoidResult.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System.Threading.Tasks;
+
+namespace Org.Apache.REEF.Utilities.AsyncUtils
+{
+ /// <summary>
+ /// A type used to indicate that no meaningful value is returned.
+ /// We often use this type with <see cref="Task{TResult}"/> to indicate that an asynchronous
+ /// operation returns no meaningful value. This eliminates the need to simultaneously
+ /// support <see cref="Task"/> APIs and <see cref="Task{TResult}"/> APIs
+ /// </summary>
+ public struct VoidResult
+ {
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj b/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj
index 5065af6..4576cd6 100644
--- a/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj
+++ b/lang/cs/Org.Apache.REEF.Utilities/Org.Apache.Reef.Utilities.csproj
@@ -38,6 +38,7 @@ under the License.
</ItemGroup>
<ItemGroup>
<Compile Include="AsyncUtils\RemoveSynchronizationContextAwaiter.cs" />
+ <Compile Include="AsyncUtils\VoidResult.cs" />
<Compile Include="Attributes\ClientSideAttribute.cs" />
<Compile Include="Attributes\DriverSideAttribute.cs" />
<Compile Include="Attributes\EvaluatorSideAttribute.cs" />
http://git-wip-us.apache.org/repos/asf/reef/blob/76adb40c/lang/cs/Org.Apache.REEF.sln
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.sln b/lang/cs/Org.Apache.REEF.sln
index 3b13a5e..41932c1 100644
Binary files a/lang/cs/Org.Apache.REEF.sln and b/lang/cs/Org.Apache.REEF.sln differ