Endpoint

Endpoint is a derivative class from the Circuit. It delegates all HTTP calls ot the session (which is one of the Endpoint’s attributes), but can also keep a state. If Endpoint was called and request failed, it’ll change its state from closed to open.

Another feature of Endpoint is callbacks. It accepts pre-, post- and exception- callbacks, which allows to do corresponding actions with request, response and exceptions handling.

class ahoyhoy.endpoints.Endpoint(host=None, pre_callback=None, post_callback=None, exception_callback=None, classify=None, retry=None, session=None, *args, **kwargs)[source]

Bases: ahoyhoy.circuit.circuit.Circuit

Accepts a duck-typed session (a “Session” in Requests terms) and allows it to work as a Circuit (open|closed state).

Endpoint simply proxies to session methods, so it’s just as easy to use as ServiceDiscoveryHttpClient.

>>> from ahoyhoy.endpoints import Endpoint
>>> from ahoyhoy.utils import Host
>>> host = Host('google.com', '443')
>>> ep = Endpoint(host)
>>> ep.get('/')
<Response [200]>
>>> ep.open()
>>> ep.get('/')
Traceback (most recent call last):
...
RuntimeError: Circuit state is open, no connections possible.

When using service discovery, this fits nicely with the way that Load Balancers work.

>>> from ahoyhoy.lb import RoundRobinLB
>>> from ahoyhoy.lb.providers import ListProvider
>>> from ahoyhoy.utils import Host
>>> lb = RoundRobinLB(ListProvider(Host('google.com', '80')))
>>> ep = lb.pick()
>>> ep.get('/')
<Response [200]>
>>> ep.open()
>>> ep.get('/')
Traceback (most recent call last):
 ...
RuntimeError: Circuit state is open, no connections possible.

Here’s an example of how circuit opens automatically:

>>> from ahoyhoy.lb import RoundRobinLB
>>> from ahoyhoy.lb.providers import ListProvider
>>> from ahoyhoy.utils import Host
>>> lb = RoundRobinLB(ListProvider(Host('google1.com1', '80')))
>>> ep = lb.pick()
>>> ep
<Endpoint/.../Host(address='google1.com1', port='80')/<class 'ahoyhoy.circuit.circuit.ClosedState'>
>>> ep.get('/')
Traceback (most recent call last):
 ...
requests.exceptions.ConnectionError: HTTPConnectionPool(host='google1.com1', port=80): Max retries exceeded with url:...
>>> ep
<Endpoint/.../Host(address='google1.com1', port='80')/<class 'ahoyhoy.circuit.circuit.OpenState'>

Before you gasp at the number of lines there, remember that Endpoint is a relatively low-level component. Higher-level components are easier to use, but Endpoints allow full flexibility.

The SimpleHttpEndpoint factory function can be used when you don’t need service discovery.

>>> from ahoyhoy.endpoints import SimpleHttpEndpoint
>>> sep = SimpleHttpEndpoint()
>>> sep.get('http://google.com')
<Response [200]>

Custom exception callback function

>>> def exc(e):
...     return 'I caught it!'
>>> ep = Endpoint(Host('google1.com1', '80'), exception_callback=exc)
>>> ep.get('/')
'I caught it!'
Parameters:
  • host – collections.namedtuple, Host(address, port)
  • pre_callback
  • post_callback
  • exception_callback
  • classify – response clissifier. By default it’s Circuit's classify.
  • retry – function for retrying HTTP calls
  • session – custom session
  • args – positional argument for ServiceDiscoveryHttpClient
  • kwargs – keyword argument for ServiceDiscoveryHttpClient
get(*args, **kwargs)[source]
post(*args, **kwargs)[source]
put(*args, **kwargs)[source]
head(*args, **kwargs)[source]
patch(*args, **kwargs)[source]
delete(*args, **kwargs)[source]
host
state
set_headers(headers)[source]
set_retry(retry_func)[source]
ahoyhoy.endpoints.SimpleHttpEndpoint(session=None, retry=None)[source]

Simple CircuitBreaking Endpoint that uses a default (non-service discoverable) client