Skip to content

Commit 277dc01

Browse files
committed
fix #633 server side elasticsearch exceptions are now caught in a ElasticsearchServerException and a setting on ConnectionConfiguration allows you to always throw on those
1 parent 2a2dcdf commit 277dc01

34 files changed

+195
-245
lines changed

Diff for: src/Elasticsearch.Net/Connection/ConnectionConfiguration.cs

+27-1
Original file line numberDiff line numberDiff line change
@@ -51,45 +51,61 @@ public class ConnectionConfiguration<T> : IConnectionConfigurationValues, IHideO
5151

5252
private int _timeout;
5353
int IConnectionConfigurationValues.Timeout { get { return _timeout; }}
54+
5455
private int? _pingTimeout;
5556
int? IConnectionConfigurationValues.PingTimeout { get{ return _pingTimeout; } }
5657

5758
private int? _deadTimeout;
5859
int? IConnectionConfigurationValues.DeadTimeout { get{ return _deadTimeout; } }
60+
5961
private int? _maxDeadTimeout;
6062
int? IConnectionConfigurationValues.MaxDeadTimeout { get{ return _maxDeadTimeout; } }
63+
6164
private string _proxyUsername;
6265
string IConnectionConfigurationValues.ProxyUsername { get{ return _proxyUsername; } }
66+
6367
private string _proxyPassword;
6468
string IConnectionConfigurationValues.ProxyPassword { get{ return _proxyPassword; } }
69+
6570
private bool _disablePings;
6671
bool IConnectionConfigurationValues.DisablePings { get{ return _disablePings; } }
72+
6773
private string _proxyAddress;
6874
string IConnectionConfigurationValues.ProxyAddress { get{ return _proxyAddress; } }
6975

7076
private bool _usePrettyResponses;
7177
bool IConnectionConfigurationValues.UsesPrettyResponses { get{ return _usePrettyResponses; } }
78+
7279
private bool _keepRawResponse;
7380
bool IConnectionConfigurationValues.KeepRawResponse { get{ return _keepRawResponse; } }
7481

7582
private int _maximumAsyncConnections;
7683
int IConnectionConfigurationValues.MaximumAsyncConnections { get{ return _maximumAsyncConnections; } }
84+
7785
private int? _maxRetries;
7886
int? IConnectionConfigurationValues.MaxRetries { get{ return _maxRetries; } }
87+
7988
private bool _sniffOnStartup;
8089
bool IConnectionConfigurationValues.SniffsOnStartup { get{ return _sniffOnStartup; } }
90+
8191
private bool _sniffOnConectionFault;
8292
bool IConnectionConfigurationValues.SniffsOnConnectionFault { get{ return _sniffOnConectionFault; } }
93+
8394
private TimeSpan? _sniffLifeSpan;
8495
TimeSpan? IConnectionConfigurationValues.SniffInformationLifeSpan { get{ return _sniffLifeSpan; } }
96+
8597
private bool _traceEnabled;
8698
bool IConnectionConfigurationValues.TraceEnabled { get{ return _traceEnabled; } }
99+
100+
private bool _throwOnServerExceptions;
101+
bool IConnectionConfigurationValues.ThrowOnElasticsearchServerExceptions { get{ return _throwOnServerExceptions; } }
102+
87103
private Action<IElasticsearchResponse> _connectionStatusHandler;
88104
Action<IElasticsearchResponse> IConnectionConfigurationValues.ConnectionStatusHandler { get{ return _connectionStatusHandler; } }
105+
89106
private NameValueCollection _queryString;
90107
NameValueCollection IConnectionConfigurationValues.QueryStringParameters { get{ return _queryString; } }
91108

92-
93109
IElasticsearchSerializer IConnectionConfigurationValues.Serializer { get; set; }
94110

95111
public ConnectionConfiguration(IConnectionPool connectionPool)
@@ -140,6 +156,16 @@ public T EnableTrace(bool enabled = true)
140156
return (T) this;
141157
}
142158

159+
/// <summary>
160+
/// Instead of following a c/go like error checking on response.IsValid always throw an ElasticsearchServerException
161+
/// on the client when a call resulted in an exception on the elasticsearch server.
162+
/// <para>Reasons for such exceptions could be search parser errors, index missing exceptions</para>
163+
/// </summary>
164+
public T ThrowOnElasticsearchServerExceptions(bool alwaysThrow = true)
165+
{
166+
this._throwOnServerExceptions = alwaysThrow;
167+
return (T) this;
168+
}
143169
/// <summary>
144170
/// When a node is used for the very first time or when it's used for the first time after it has been marked dead
145171
/// a ping with a very low timeout is send to the node to make sure that when it's still dead it reports it as fast as possible.

Diff for: src/Elasticsearch.Net/Connection/ElasticsearchServerException.cs

+23
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,36 @@
44
using System.Linq;
55
using System.Net;
66
using System.Text;
7+
using System.Text.RegularExpressions;
78

89
namespace Elasticsearch.Net.Connection
910
{
11+
public class ElasticsearchServerError
12+
{
13+
public int Status { get; set; }
14+
public string Error { get; set; }
15+
16+
}
17+
1018
public class ElasticsearchServerException : Exception
1119
{
20+
private static Regex ExceptionSplitter = new Regex(@"^([^\[]*?)\[(.*)\]", RegexOptions.Singleline);
21+
1222
public int Status { get; set; }
1323
public string Error { get; set; }
1424
public string ExceptionType { get; set; }
25+
public ElasticsearchServerException(ElasticsearchServerError error)
26+
{
27+
if (error == null) return;
28+
this.Status = error.Status;
29+
if (error.Error.IsNullOrEmpty()) return;
30+
var matches = ExceptionSplitter.Match(error.Error);
31+
if (matches.Groups.Count == 3)
32+
{
33+
this.Error = matches.Groups[2].Value;
34+
this.ExceptionType = matches.Groups[1].Value;
35+
}
36+
else this.Error = error.Error;
37+
}
1538
}
1639
}

Diff for: src/Elasticsearch.Net/Connection/IConnectionConfigurationValues.cs

+9-4
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@ namespace Elasticsearch.Net.Connection
88
public interface IConnectionConfigurationValues
99
{
1010
IConnectionPool ConnectionPool { get; }
11-
//Uri Uri { get; }
11+
1212
int MaximumAsyncConnections { get; }
13-
//string Host { get; }
14-
//int Port { get; }
1513
int Timeout { get; }
1614
int? PingTimeout { get; }
1715
int? DeadTimeout { get; }
1816
int? MaxDeadTimeout { get; }
1917
int? MaxRetries { get; }
2018
bool DisablePings { get; }
19+
2120
string ProxyAddress { get; }
2221
string ProxyUsername { get; }
2322
string ProxyPassword { get; }
@@ -26,6 +25,13 @@ public interface IConnectionConfigurationValues
2625
bool UsesPrettyResponses { get; }
2726
bool KeepRawResponse { get; }
2827

28+
/// <summary>
29+
/// Instead of following a c/go like error checking on response.IsValid always throw an ElasticsearchServerException
30+
/// on the client when a call resulted in an exception on the elasticsearch server.
31+
/// <para>Reasons for such exceptions could be search parser errors, index missing exceptions</para>
32+
/// </summary>
33+
bool ThrowOnElasticsearchServerExceptions { get; }
34+
2935
/// <summary>
3036
/// Sniff the cluster state immediatly on startup
3137
/// </summary>
@@ -41,7 +47,6 @@ public interface IConnectionConfigurationValues
4147
/// the specified timespan
4248
/// </summary>
4349
TimeSpan? SniffInformationLifeSpan { get; }
44-
4550

4651
/// <summary>
4752
/// Append these query string parameters automatically to every request

Diff for: src/Elasticsearch.Net/Connection/Transport.cs

+11-3
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,25 @@ private ElasticsearchResponse<T> DoRequest<T>(TransportRequestState<T> requestSt
192192
var streamResponse = _doRequest(requestState.Method, uri, requestState.PostData, requestState.RequestConfiguration);
193193
if (streamResponse != null && streamResponse.SuccessOrKnownError)
194194
{
195+
ElasticsearchServerError error = null;
195196
if (!streamResponse.Success
196197
&& requestState.RequestConfiguration == null
197-
|| (requestState.RequestConfiguration != null
198+
|| (!streamResponse.Success
199+
&& requestState.RequestConfiguration != null
198200
&& requestState.RequestConfiguration.AllowedStatusCodes.All(i => i != streamResponse.HttpStatusCode)))
199201
{
200-
var deserialized = this.Serializer.Deserialize<ElasticsearchServerException>(streamResponse.Response);
201-
throw deserialized;
202+
error = this.Serializer.Deserialize<ElasticsearchServerError>(streamResponse.Response);
203+
if (this.Settings.ThrowOnElasticsearchServerExceptions)
204+
throw new ElasticsearchServerException(error);
202205
}
203206

204207
var typedResponse = this.StreamToTypedResponse<T>(streamResponse, requestState.DeserializationState);
205208
typedResponse.NumberOfRetries = retried;
209+
if (error != null)
210+
{
211+
typedResponse.Success = false;
212+
typedResponse.OriginalException = new ElasticsearchServerException(error);
213+
}
206214
response = typedResponse;
207215
return typedResponse;
208216
}

Diff for: src/Nest/DSL/AliasDescriptor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
namespace Nest
1414
{
1515
[DescriptorFor("IndicesUpdateAliases")]
16-
public partial class AliasDescriptor :
16+
public partial class AliasDescriptor : BasePathDescriptor<AliasDescriptor>,
1717
IPathInfo<AliasRequestParameters>
1818
{
1919
public AliasDescriptor()

Diff for: src/Nest/DSL/InfoDescriptor.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Nest
1313
{
1414
[DescriptorFor("Info")]
15-
public partial class InfoDescriptor :
15+
public partial class InfoDescriptor : BasePathDescriptor<InfoDescriptor>,
1616
IPathInfo<InfoRequestParameters>
1717
{
1818
ElasticsearchPathInfo<InfoRequestParameters> IPathInfo<InfoRequestParameters>.ToPathInfo(IConnectionSettingsValues settings)

Diff for: src/Nest/DSL/Paths/BasePathDescriptor.cs

+19-3
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,35 @@
44

55
namespace Nest
66
{
7-
public class BasePathDescriptor<TDescriptor>
7+
public interface IPathDescriptor
8+
{
9+
RequestConfiguration RequestConfiguration { get; set; }
10+
}
11+
12+
public class BasePathDescriptor<TDescriptor> : IPathDescriptor
813
where TDescriptor : BasePathDescriptor<TDescriptor>
914
{
10-
internal RequestConfiguration _RequestConfiguration { get; set; }
15+
RequestConfiguration IPathDescriptor.RequestConfiguration { get; set; }
1116

1217
/// <summary>
1318
/// Specify settings for this request alone, handy if you need a custom timeout or want to bypass sniffing, retries
1419
/// </summary>
1520
public TDescriptor RequestConfiguration(Func<RequestConfiguration, RequestConfiguration> configurationSelector)
1621
{
1722
configurationSelector.ThrowIfNull("configurationSelector");
18-
this._RequestConfiguration = configurationSelector(new RequestConfiguration());
23+
((IPathDescriptor)this).RequestConfiguration =
24+
configurationSelector(((IPathDescriptor)this).RequestConfiguration ?? new RequestConfiguration());
1925
return (TDescriptor)this;
2026
}
27+
internal ElasticsearchPathInfo<TParameters> ToPathInfo<TParameters>(TParameters queryString)
28+
where TParameters : FluentRequestParameters<TParameters>, new()
29+
{
30+
var pathInfo = new ElasticsearchPathInfo<TParameters>();
31+
pathInfo.RequestParameters = queryString ?? new TParameters();
32+
var config = ((IPathDescriptor)this).RequestConfiguration;
33+
if (config != null)
34+
pathInfo.RequestParameters.RequestConfiguration(r => config);
35+
return pathInfo;
36+
}
2137
}
2238
}

Diff for: src/Nest/DSL/Paths/DocumentPathDescriptor.cs

+5-8
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,11 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
8383
var index = this._Index != null ? inferrer.IndexName(this._Index) : inferrer.IndexName<T>();
8484
var type = this._Type != null ? inferrer.TypeName(this._Type) : inferrer.TypeName<T>();
8585
var id = this._Id ?? inferrer.Id(this._Object);
86-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
87-
{
88-
Index = index,
89-
Type = type,
90-
Id = id
91-
};
92-
pathInfo.RequestParameters = queryString ?? new TParameters();
93-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
86+
87+
var pathInfo = base.ToPathInfo(queryString);
88+
pathInfo.Index = index;
89+
pathInfo.Type = type;
90+
pathInfo.Id = id;
9491
return pathInfo;
9592
}
9693

Diff for: src/Nest/DSL/Paths/FixedIndexTypePathDescriptor.cs

+3-7
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,9 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
6060
var index = inferrer.IndexName(this._Index);
6161
var type = inferrer.TypeName(this._Type);
6262

63-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
64-
{
65-
Index = index,
66-
Type = type
67-
};
68-
pathInfo.RequestParameters = queryString ?? new TParameters();
69-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
63+
var pathInfo = base.ToPathInfo(queryString);
64+
pathInfo.Index = index;
65+
pathInfo.Type = type;
7066
return pathInfo;
7167
}
7268

Diff for: src/Nest/DSL/Paths/IndexNamePathDescriptor.cs

+3-7
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,9 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
5151
throw new DslException("missing Repository()");
5252
var inferrer = new ElasticInferrer(settings);
5353
var index = inferrer.IndexName(this._Index) ?? inferrer.DefaultIndex;
54-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
55-
{
56-
Index = index,
57-
Name = this._Name
58-
};
59-
pathInfo.RequestParameters = queryString ?? new TParameters();
60-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
54+
var pathInfo = base.ToPathInfo(queryString);
55+
pathInfo.Index = index;
56+
pathInfo.Name = this._Name;
6157
return pathInfo;
6258
}
6359

Diff for: src/Nest/DSL/Paths/IndexOptionalPathDescriptor.cs

+2-6
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,8 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
6060
if (!this._AllIndices.GetValueOrDefault(false))
6161
index = inferrer.IndexName(this._Index);
6262

63-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
64-
{
65-
Index = index,
66-
};
67-
pathInfo.RequestParameters = queryString ?? new TParameters();
68-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
63+
var pathInfo = base.ToPathInfo(queryString);
64+
pathInfo.Index = index;
6965
return pathInfo;
7066
}
7167

Diff for: src/Nest/DSL/Paths/IndexPathDescriptor.cs

+2-6
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,8 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
4848
throw new DslException("missing call to Index()");
4949

5050
var index = new ElasticInferrer(settings).IndexName(this._Index);
51-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
52-
{
53-
Index = index,
54-
};
55-
pathInfo.RequestParameters = queryString ?? new TParameters();
56-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
51+
var pathInfo = base.ToPathInfo(queryString);
52+
pathInfo.Index = index;
5753
return pathInfo;
5854
}
5955

Diff for: src/Nest/DSL/Paths/IndexTypePathDescriptor.cs

+4-7
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,10 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
7272

7373
var index = inferrer.IndexName(this._Index);
7474
var type = inferrer.TypeName(this._Type);
75-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
76-
{
77-
Index = index,
78-
Type = type
79-
};
80-
pathInfo.RequestParameters = queryString ?? new TParameters();
81-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
75+
76+
var pathInfo = base.ToPathInfo(queryString);
77+
pathInfo.Index = index;
78+
pathInfo.Type = type;
8279
return pathInfo;
8380
}
8481

Diff for: src/Nest/DSL/Paths/IndexTypePathTypedDescriptor.cs

+6-9
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,12 @@ internal virtual ElasticsearchPathInfo<TParameter> ToPathInfo(IConnectionSetting
6666
if (this._Type == null)
6767
this._Type = inferrer.TypeName<T>();
6868

69-
var index = new ElasticInferrer(settings).IndexName(this._Index);
70-
var type = new ElasticInferrer(settings).TypeName(this._Type);
71-
var pathInfo = new ElasticsearchPathInfo<TParameter>()
72-
{
73-
Index = index,
74-
Type = type
75-
};
76-
pathInfo.RequestParameters = queryString ?? new TParameter();
77-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
69+
var index = inferrer.IndexName(this._Index);
70+
var type = inferrer.TypeName(this._Type);
71+
72+
var pathInfo = base.ToPathInfo(queryString);
73+
pathInfo.Index = index;
74+
pathInfo.Type = type;
7875
return pathInfo;
7976
}
8077

Diff for: src/Nest/DSL/Paths/IndicesOptionalExplicitAllPathDescriptor.cs

+2-6
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,8 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
6565
if (!this._AllIndices.GetValueOrDefault(false))
6666
index = string.Join(",", this._Indices.Select(inferrer.IndexName));
6767

68-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
69-
{
70-
Index = index,
71-
};
72-
pathInfo.RequestParameters = queryString ?? new TParameters();
73-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
68+
var pathInfo = base.ToPathInfo(queryString);
69+
pathInfo.Index = index;
7470
return pathInfo;
7571
}
7672

Diff for: src/Nest/DSL/Paths/IndicesOptionalPathDescriptor.cs

+2-6
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,8 @@ internal virtual ElasticsearchPathInfo<TParameters> ToPathInfo(IConnectionSettin
5050
{
5151
var index = this._Indices == null ? null : string.Join(",", this._Indices.Select(i => new ElasticInferrer(settings).IndexName(i)));
5252

53-
var pathInfo = new ElasticsearchPathInfo<TParameters>()
54-
{
55-
Index = index,
56-
};
57-
pathInfo.RequestParameters = queryString ?? new TParameters();
58-
pathInfo.RequestParameters.RequestConfiguration(r=>this._RequestConfiguration);
53+
var pathInfo = base.ToPathInfo(queryString);
54+
pathInfo.Index = index;
5955
return pathInfo;
6056
}
6157

0 commit comments

Comments
 (0)