Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract error information from JSON. #7

Closed
wants to merge 1 commit into from

Conversation

mjkillough
Copy link
Contributor

When OSRM returns an error, it (often?) includes an error code/message in the returned JSON object. This change extracts this code/message and returns it to the caller of libosrmc.

This makes it easier to debug failures, but also makes it possible to react to errors such as NoRoute. An example of such a route is between 25.07165,55.402115 and 25.086226,55.385334 in the UAE, using the foot or bicycle profiles.

mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 11, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
@daniel-j-h
Copy link
Owner

Hey there, thanks for this pull request (and the other ones) :)

Quick disclaimer before we go into details: this project was sort of a prototype and is lacking large parts of the API. I also haven't compiled or tested it against libosrm in the last two'ish years, and it's not used by me right now.

That said, if you want to pick it up I'm happy to guide you along and merge your improvements in.


Now to this pull request. I think it's a very good idea in general! We already have an error type here

struct osrmc_error final {
std::string message;
};

Right now we only store a single generic message.

Here's what I think we should do instead:

  • store two strings: message, and code
  • parse message and code from the json object (like you do)
  • code should always be there (assert that)
  • message is optional, empty string is fine in this case I think
  • add another function osrmc_error_code similar to the existing osrmc_error_message (see below)

OSRMC_API const char* osrmc_error_message(osrmc_error_t error);

In theory we could also make the error code an enum we expose to the user. But even in upstream libosrm these enum values are strings only and only documentation captures all possible values. Not sure I like this to be honest, see:

https://github.com/Project-OSRM/osrm-backend/search?q=TooBig&type=Code

Let me know what you think.

@@ -29,6 +29,21 @@ struct osrmc_error final {
std::string message;
};

void osrmc_error_from_json(osrm::json::Object* json, osrmc_error_t* error) try {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only use this function in the implementation, right? Then it should be static .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point! I'd forgotten about static. :-)

@mjkillough
Copy link
Contributor Author

Quick disclaimer before we go into details: this project was sort of a prototype and is lacking large parts of the API. I also haven't compiled or tested it against libosrm in the last two'ish years, and it's not used by me right now.

That said, if you want to pick it up I'm happy to guide you along and merge your improvements in.

Thank you so much for giving such detailed feedback, so quickly! As this didn't appear to be used, I wasn't sure what to expect. :-)

I'm using this to create a Rust wrapper around libosrm, and it includes everything I think I'll need (except the durations in the Table API, hence the other PR). It seems to work great against the current libosrm, so that was a really nice surprise! I'm very happy to support it for my use-case.

Here's what I think we should do instead:

  • store two strings: message, and code
  • parse message and code from the json object (like you do)
  • code should always be there (assert that)
  • message is optional, empty string is fine in this case I think
  • add another function osrmc_error_code similar to the existing osrmc_error_message (see below)

Great idea! This makes it much easier for me to match on the error in my application. I can now match on the code.

I've done all of this, except asserting the code is always there. I've instead defaulted it to "Unknown" if it's missing (or if the JSON is never returned). This felt better, as libosrmc could become out-of-sync with libosrm, and I'd like it to still return something for the error even i

In theory we could also make the error code an enum we expose to the user. But even in upstream libosrm these enum values are strings only and only documentation captures all possible values. Not sure I like this to be honest, see:

https://github.com/Project-OSRM/osrm-backend/search?q=TooBig&type=Code

This would have been great, as it'd allow me to handle the errors without string matching (which is a bit gross). However, I don't think we could achieve this without significant changes to libosrm - I think sticking with this approach is probably good enough.

mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 12, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
Copy link
Owner

@daniel-j-h daniel-j-h left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good design decision on the "Unknown" fallback instead of assert.

I'm pretty happy with how you changed the implementation; there's a small nitpick with asserting a nullptr (I left an inline comment). If you change that I think we can merge this in.

static void osrmc_error_from_json(osrm::json::Object* json, osrmc_error_t* error) try {
if (json == nullptr) {
*error = new osrmc_error{"Unknown", ""};
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assert json != nullptr. The object itself should always be there, otherwise the user is calling this API the wrong way. Check out how we use this API on the call sites, the result json is always an (potentially empty) object but should never be a nullptr.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point! I've updated it to assert instead.

Thanks a lot for all the help! 🙂

mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 13, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 13, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 13, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
}

static void osrmc_error_from_json(osrm::json::Object* json, osrmc_error_t* error) try {
assert(json != nullptr);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had a look at the call sites and it seems like we only use this internally in the C++ impl.

Then we could change this function to taking a const osrm::json::Object& (since we only need a read-only view for accessing the json values) and don't have to care about null pointers (since refs can't be null).

Copy link
Contributor Author

@mjkillough mjkillough Mar 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Unfortunately it can't be const as, surprisingly, indexing into values adds the key to the unordered_map if it doesn't exist. (This shouldn't actually matter in practise I don't think).

When OSRM returns an error, it (often?) includes an error code/message
in the returned JSON object. This change extracts this code/message and
returns it to the caller of libosrmc. This makes it easier to debug
failures, but also makes it possible to react to errors such as
`NoRoute`.

The errors are extracted as both `code`/`message`, and a new
`osrmc_error_code` is introduced to allow the caller to extract the
code.
mjkillough added a commit to mjkillough/libosrmc that referenced this pull request Mar 17, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in daniel-j-h#7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
daniel-j-h pushed a commit that referenced this pull request Mar 17, 2019
Add the ability to specify whether the table should be annotated with
distance and/or duration, as well as a new API for returning the
distance. This is done in a way that allows us to return errors for
unrouteable routes (where `null` is returned in the JSON), as in #7.

I'm not 100% sure of the use of `stdbool` in a FFI interface - it's been
a while since I had to write C!
@daniel-j-h
Copy link
Owner

Merged with #8 (comment)

@daniel-j-h daniel-j-h closed this Mar 17, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants