librelist archives

« back to archive

bubbling errors and flashing those errors

bubbling errors and flashing those errors

Daniele Sluijters
2013-07-12 @ 11:35
Hi everyone,

I’m using Flask to create a web frontend to visualise some data returned 
from an API.

When I render a page I need to usually grab some kind of root element from
the API. If that fails I
can short-circuit the response and just abort it. However, if getting this
root object succeeds
I then usually need to proceed to query the API for more information about
that root object
at different endpoints of the API.

To make it easier to visualise, let’s say I need to query 
/author/<author_name> on the API
to give me an author. That response contains some basic information about 
the author,
their name and a unique ID I can use to query for objects associated with 
that other.
Once that succeeds and I want more information I can for example query 
or /bio/<author_id> but there is no guarantee that those endpoints will 
reply with some
content. There might not be a biography for this author so a 404 may be 
returned instead.

This is where it gets tricky as for every of those endpoints there might 
or might no be
additional information for my object. In this case I could again 
short-circuit the request
but that would mean that if one endpoint fails me I can’t display any 
information of the
other endpoints that might have responded.

For every subsequent call I’d like to do after fetching my root object I’d like
those calls to be able to fail gracefully, bubble up an error message 
through the stack
to my view and flash them to the user instead. This means that a user 
might get a page
rendered with only the bits of information available and a friendly 
message telling the
user that some parts couldn’t be requested from the API/backend because 
they weren’t
available, the request timed out and so forth.

I’ve thought of a few ways of doing this but I’m unsure about any of them.

# the errors-go-round method
Every call to the API returns a (result,errors) tuple, append all the 
different errors
together in a list, loop over those and flash them in your view.

This is the most easy/plain/simple method but I find it quite nasty and it litters
the views and the rest of the code base with checks on the errors returned and
so forth.

# exceptions and a with_statement / context manager
My second possibility would be to wrap every request to the backend in some kind
of get_or_riase method which if the request to the backend would fail would
raise an error.

Then in the view a context manager is used around those calls that catches those
errors and flashes their associated messages.

Something along these lines
with flash_exceptions:
  second_call = get_or_roaise(backend.get, some,
  return render_template(....)

# using logging
The third possibility I considered is using a custom logger and that every
call to the
backend would log to that logger, propagating the errors to the root of 
that logger. Then
I’d need to be able to gather those messages from that logger and flash them.

I’m not even sure if this is possible to begin with but the idea just 
popped into my mind.

I’d love some feedback on the ideas, their feasibility and if anyone has 
ever tried
something like this before and how they ended up solving this.

Kind regards,

Daniele Sluijters