Skip to content
This repository was archived by the owner on Sep 10, 2021. It is now read-only.

Commit fbb79cf

Browse files
committed
Added better exception details
- Moved to 0.2.1 - Added RpcException.Details which contains a full dump of the exception and inner exceptions (may be null)
1 parent d7af680 commit fbb79cf

File tree

8 files changed

+64
-44
lines changed

8 files changed

+64
-44
lines changed

samples/Example.General/Program.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Test001 : ITest001
4141
public async Task<string> Login(LoginRequestMsg login) {
4242
Console.WriteLine($"Worker ({_uuid}) - Username: {login.Username} Password: {login.Password}");
4343
RpcContext context = RpcContext.Current;
44-
44+
4545
return "Wow";
4646
}
4747

@@ -85,8 +85,12 @@ static async Task AsyncMain(string[] args) {
8585
Console.WriteLine();
8686
}
8787

88-
// detaches the service
89-
await TestNode.DetachAsync(service).ConfigureAwait(false);
88+
var proxy = TestNode.Proxy<ITest001>("auth:login");
89+
string a = await proxy.Login(new LoginRequestMsg()
90+
{
91+
Username = "wow",
92+
Password = "wow"
93+
});
9094

9195
await Task.Delay(50000);
9296
}

src/Holon/Holon.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>netstandard1.6</TargetFramework>
5-
<Version>0.2.0</Version>
5+
<Version>0.2.1</Version>
66
<Authors>Alan Doherty</Authors>
77
<Company>Alan Doherty</Company>
88
<Description>A minimal service and event bus with additional support for RPC</Description>
99
<Copyright>BattleCrate Ltd 2018</Copyright>
1010
<PackageProjectUrl>https://github.com/alandoherty/holon-net</PackageProjectUrl>
1111
<RepositoryUrl>https://github.com/alandoherty/holon-net</RepositoryUrl>
1212
<RepositoryType>git</RepositoryType>
13-
<AssemblyVersion>0.2.0.0</AssemblyVersion>
13+
<AssemblyVersion>0.2.1.0</AssemblyVersion>
1414
<PackageLicenseUrl>https://github.com/alandoherty/holon-net/blob/master/LICENSE</PackageLicenseUrl>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageIconUrl>https://s3-eu-west-1.amazonaws.com/assets.alandoherty.co.uk/github/holon-net-nuget.png</PackageIconUrl>
17-
<FileVersion>0.2.0.0</FileVersion>
17+
<FileVersion>0.2.1.0</FileVersion>
1818
</PropertyGroup>
1919

2020
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

src/Holon/Remoting/RpcBehaviour.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ private async Task ApplyAsync(RpcHeader header, Envelope envelope) {
7878
try {
7979
req = serializer.DeserializeRequest(envelope.Body, (i, o) => RpcArgument.FromMember(GetMember(i, o)));
8080
} catch (KeyNotFoundException) {
81-
res = new RpcResponse("InterfaceNotFound", "The interface or operation could not be found");
81+
res = new RpcResponse("InterfaceNotFound", "The interface or operation could not be found", null);
8282
} catch(Exception ex) {
83-
res = new RpcResponse("ArgumentInvalid", string.Format("The request format is invalid: {0}", ex.Message));
83+
res = new RpcResponse("ArgumentInvalid", string.Format("The request format is invalid: {0}", ex.Message), null);
8484
}
8585

8686
// apply single request
@@ -90,7 +90,7 @@ private async Task ApplyAsync(RpcHeader header, Envelope envelope) {
9090
if (req != null)
9191
memberInfo = GetMember(req.Interface, req.Operation);
9292
} catch (KeyNotFoundException) {
93-
res = new RpcResponse("OperationNotFound", "The interface or operation could not be found");
93+
res = new RpcResponse("OperationNotFound", "The interface or operation could not be found", null);
9494
}
9595

9696
// get operation information
@@ -107,7 +107,7 @@ private async Task ApplyAsync(RpcHeader header, Envelope envelope) {
107107

108108
// check if they have a response ID if no reply isn't enabled
109109
if (!noReply && envelope.ID == Guid.Empty)
110-
res = new RpcResponse("InvalidOperation", "The envelope does not specify a correlation ID");
110+
res = new RpcResponse("InvalidOperation", "The envelope does not specify a correlation ID", null);
111111

112112
// apply request if we don't have a response already, typically an error
113113
if (res == null) {
@@ -192,7 +192,7 @@ private MemberInfo GetMember(string @interface, string operation) {
192192
private async Task<RpcResponse> ApplyRequestAsync(RpcRequest req, MemberInfo member) {
193193
// find interface behaviour
194194
if (!_behaviours.TryGetValue(req.Interface, out Binding binding))
195-
return new RpcResponse("InterfaceNotFound", "The interface binding could not be found");
195+
return new RpcResponse("InterfaceNotFound", "The interface binding could not be found", null);
196196

197197
// get method info
198198
MethodInfo operationMethod = member as MethodInfo;
@@ -205,7 +205,7 @@ private async Task<RpcResponse> ApplyRequestAsync(RpcRequest req, MemberInfo mem
205205
for (int i = 0; i < methodArgs.Length; i++) {
206206
if (!req.Arguments.TryGetValue(methodParams[i].Name, out methodArgs[i])) {
207207
if (!methodParams[i].IsOptional)
208-
return new RpcResponse("ArgumentRequired", string.Format("The argument {0} is not optional", methodParams[i].Name));
208+
return new RpcResponse("ArgumentRequired", string.Format("The argument {0} is not optional", methodParams[i].Name), null);
209209
}
210210
}
211211

@@ -216,9 +216,9 @@ private async Task<RpcResponse> ApplyRequestAsync(RpcRequest req, MemberInfo mem
216216
methodResult = operationMethod.Invoke(binding.Behaviour, methodArgs);
217217
await ((Task)methodResult).ConfigureAwait(false);
218218
} catch (RpcException ex) {
219-
return new RpcResponse(ex.Code, ex.Message);
219+
return new RpcResponse(ex.Code, ex.Message, ex.ToString());
220220
} catch (Exception ex) {
221-
return new RpcResponse("Exception", ex.ToString());
221+
return new RpcResponse("Exception", ex.Message, ex.ToString());
222222
}
223223

224224
// check if the operation returns anything
@@ -416,7 +416,7 @@ public Task<InterfaceInformation> GetInterfaceInfo(string @interface) {
416416

417417
lock (_behaviour._behaviours) {
418418
if (!_behaviour._behaviours.TryGetValue(@interface, out binding) || !binding.AllowIntrospection)
419-
throw new RpcException("InterfaceNotFound", "The interface does not exist");
419+
throw new RpcException("InterfaceNotFound", "The interface does not exist", null);
420420
}
421421

422422
return Task.FromResult(binding.Introspection);

src/Holon/Remoting/RpcError.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public sealed class RpcError
1212
#region Fields
1313
private string _code;
1414
private string _message;
15+
private string _details;
1516
#endregion
1617

1718
#region Properties
@@ -32,6 +33,15 @@ public string Message {
3233
return _message;
3334
}
3435
}
36+
37+
/// <summary>
38+
/// Gets the error details.
39+
/// </summary>
40+
public string Details {
41+
get {
42+
return _details ?? _message;
43+
}
44+
}
3545
#endregion
3646

3747
#region Constructors
@@ -40,9 +50,11 @@ public string Message {
4050
/// </summary>
4151
/// <param name="code">The code.</param>
4252
/// <param name="message">The message.</param>
43-
internal RpcError(string code, string message) {
53+
/// <param name="details">The details.</param>
54+
internal RpcError(string code, string message, string details) {
4455
_code = code;
4556
_message = message;
57+
_details = details;
4658
}
4759
#endregion
4860
}

src/Holon/Remoting/RpcException.cs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class RpcException : Exception
1111
{
1212
#region Fields
1313
private string _code;
14+
private string _details;
1415
#endregion
1516

1617
#region Properties
@@ -22,45 +23,36 @@ public string Code {
2223
return _code;
2324
}
2425
}
25-
#endregion
2626

27-
#region Constructors
2827
/// <summary>
29-
/// Creates a new RPC excpetion with the provided code and message.
28+
/// Gets the details.
3029
/// </summary>
31-
/// <param name="code">The code.</param>
32-
/// <param name="message">The message.</param>
33-
public RpcException(string code, string message)
34-
: base(message) {
35-
_code = code;
30+
public string Details {
31+
get {
32+
return _details;
33+
}
3634
}
35+
#endregion
3736

37+
#region Constructors
3838
/// <summary>
39-
/// Creates a new RPC exception with the provided code, message and inner exception.
39+
/// Creates a new RPC excpetion with the provided code and message.
4040
/// </summary>
4141
/// <param name="code">The code.</param>
4242
/// <param name="message">The message.</param>
43-
/// <param name="innerException">The inner exception.</param>
44-
public RpcException(string code, string message, Exception innerException)
45-
: base(message, innerException) {
43+
/// <param name="details">The details.</param>
44+
public RpcException(string code, string message, string details)
45+
: base(message) {
4646
_code = code;
47+
_details = details;
4748
}
4849

4950
/// <summary>
5051
/// Creates a new RPC exception with the RPC error object.
5152
/// </summary>
5253
/// <param name="error">The error.</param>
5354
public RpcException(RpcError error)
54-
: this(error.Code, error.Message) {
55-
}
56-
57-
/// <summary>
58-
/// Creates a new RPC exception with the RPC error object and inner exception.
59-
/// </summary>
60-
/// <param name="error">The error.</param>
61-
/// <param name="innerException">The inner exception.</param>
62-
public RpcException(RpcError error, Exception innerException)
63-
: this(error.Code, error.Message, innerException) {
55+
: this(error.Code, error.Message, error.Details) {
6456
}
6557
#endregion
6658
}

src/Holon/Remoting/RpcResponse.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ internal RpcResponse(object data, Type type) {
7070
/// </summary>
7171
/// <param name="code">The code.</param>
7272
/// <param name="message">The message.</param>
73-
internal RpcResponse(string code, string message) {
74-
_error = new RpcError(code, message);
73+
/// <param name="details">The details.</param>
74+
internal RpcResponse(string code, string message, string details) {
75+
_error = new RpcError(code, message, details);
7576
_data = null;
7677
}
7778

src/Holon/Remoting/Serializers/ProtobufRpcSerializer.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public RpcResponse DeserializeResponse(byte[] body, Type responseType) {
6363
if (msg.IsSuccess)
6464
return new RpcResponse(msg.Data.GetData(responseType), responseType);
6565
else
66-
return new RpcResponse(msg.Error.Code, msg.Error.Message);
66+
return new RpcResponse(msg.Error.Code, msg.Error.Message, msg.Error.Details);
6767
}
6868
}
6969

@@ -106,7 +106,8 @@ public byte[] SerializeResponse(RpcResponse response) {
106106
} else {
107107
res.Error = new ErrorMsg() {
108108
Code = response.Error.Code,
109-
Message = response.Error.Message
109+
Message = response.Error.Message,
110+
Details = response.Error.Details
110111
};
111112
}
112113

@@ -281,5 +282,8 @@ class ErrorMsg
281282

282283
[ProtoMember(2, IsRequired = true)]
283284
public string Message { get; set; }
285+
286+
[ProtoMember(3)]
287+
public string Details { get; set; }
284288
}
285289
}

src/Holon/Remoting/Serializers/XmlRpcSerializer.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,13 @@ public RpcResponse DeserializeResponse(byte[] body, Type dataType) {
141141
// find the code and message
142142
XElement errCode = err.Element(XName.Get("Code"));
143143
XElement errMsg = err.Element(XName.Get("Message"));
144+
XElement errDetails = err.Element(XName.Get("Details"));
144145

145146
if (errCode == null || errMsg == null)
146147
throw new InvalidDataException("Invalid XML document, error missing Code and Message elements");
147148

148149
// get data
149-
return new RpcResponse(errCode.Value, errMsg.Value);
150+
return new RpcResponse(errCode.Value, errMsg.Value, errDetails == null ? null : errDetails.Value);
150151
}
151152
}
152153
}
@@ -223,6 +224,12 @@ public byte[] SerializeResponse(RpcResponse response) {
223224
writer.WriteEndElement();
224225
writer.WriteStartElement("Message");
225226
writer.WriteValue(response.Error.Message);
227+
228+
if (response.Error.Details != null)
229+
{
230+
writer.WriteStartElement("Details");
231+
writer.WriteValue(response.Error.Details);
232+
}
226233
}
227234

228235
// finish document

0 commit comments

Comments
 (0)