elastic / elasticsearch-rs

Official Elasticsearch Rust Client
https://www.elastic.co/guide/en/elasticsearch/client/rust-api/current/index.html
Apache License 2.0
705 stars 72 forks source link

Add ElasticsearchException to model Elasticsearch exceptions #118

Closed russcam closed 4 years ago

russcam commented 4 years ago

This commit adds an ElasticsearchException struct that models exceptions returned by Elasticsearch in the event of an error.

An exception() function is exposed on Response to deserialize the response body into ElasticsearchException when the status code is in the 400-599 range.

Consideration was made to exposing this on the Error struct, performing the deserialization inside error_for_status_code, but this introduces some awkwardness into the API:

Additional details about an exception are collected in a map and exposed through additional_details function.

Closes #112

russcam commented 4 years ago

Think we can combine Error and Cause into the same type

russcam commented 4 years ago

Decided to keep Error and Cause separate for now. They both map to ElasticsearchException on the server side, but it looks like certain properties are only ever exposed on the top level exception which is deserialized to Error e.g. root_cause, header and failed_shards (which is not currently mapped in Error).

mwilliammyers commented 4 years ago

I haven't read this in great detail, but should it be Source instead of Cause, to mirror the std::error::Error trait?

Or is it just root_cause()?

russcam commented 4 years ago

I haven't read this in great detail, but should it be Source instead of Cause, to mirror the std::error::Error trait?

I think you might be referring to the previous comment about Error and Cause https://github.com/elastic/elasticsearch-rs/pull/118#issuecomment-666071878? The Error in this case is a struct that models the error field returned on an exception, for example,

{
  "error": {
    "root_cause": [{
      "type": "index_not_found_exception",
      "reason": "no such index [test_index]",
      "resource.type": "index_or_alias",
      "resource.id": "test_index",
      "index_uuid": "_na_",
      "index": "test_index"
    }],
    "type": "index_not_found_exception",
    "reason": "no such index [test_index]",
    "resource.type": "index_or_alias",
    "resource.id": "test_index",
    "index_uuid": "_na_",
    "index": "test_index"
  },
  "status": 404
}

is a response when an index does not exist. The error field is a serialized exception from Elasticsearch and in this case, contains a root_cause field, but other types of exception responses can contain a caused_by field that is also a serialized exception from Elasticsearch. Rather than reusing the Error struct as the type for the caused_by field though, there's a Cause struct to model it because it looks like certain properties are only ever exposed on the top level exception which is deserialized to Error and never on caused_by.