Saasli / saasli-backend

Documentation
https://saasli.github.io/docs/
0 stars 0 forks source link

Establish microservice "Contracts" #33

Open godd9170 opened 7 years ago

godd9170 commented 7 years ago

We can't unfortunately throw error classes out of lambdas b/c it needs to be in the form of JSON payloads. So I am proposing the notion of a 'Contract'. Every lambda function will return as part of their response, an 'Error' component that holds an integer error code. We'll open the discussion for what these codes might stand for, but essentially one will mean success.

Then, we'll have some slick Response class that nicely abstracts the job of the taking the error code and formatting a detailed message of what f***ed up.

I envision something like this when for example a salesforce 'get' is performed.

record = functions.request('salesforce-rest', 'get', credentials.__dict__)

if record['error'] != 200:
    return Response(record['error'])
godd9170 commented 7 years ago

First proposal of a numbering scheme which is (hopefully) extensible as we grow this API.

3 Digit Codes:

First value is indicative of Success (4 for errors, 2 for successes) Second value is the 'app' or library responsible for it (e.g. Salesforce (3), AWS (2) or our own (1)) Third is the error number, we'll build a dictionary of these as we grow.

so for example.

4 -> Error 3 -> Salesforce 1 -> Required field missing

godd9170 commented 7 years ago

An argument against the error codes:

AWS Lambda is smart enough to return raised exceptions as nicely formatted json. We can extend the Exception class and actually be able to raise meaningful custom errors, from any depth of abstraction.

see https://aws.amazon.com/blogs/compute/error-handling-patterns-in-amazon-api-gateway-and-aws-lambda/

godd9170 commented 7 years ago

See http://docs.aws.amazon.com/lambda/latest/dg/python-exceptions.html for the official exception docs

godd9170 commented 7 years ago

https://github.com/serverless/serverless/pull/2014 looks like Serverless has built this in! Also, this thread is way off topic. I've been discussing how errors are propagated back out to the user. And this was supposed to be about the relationship internally between my microservices.

godd9170 commented 7 years ago

I've opened #40 to more properly address the Response discussion I've found myself in.

godd9170 commented 7 years ago

The current 'Contract' convention is as follows:

For a Success:

{ 
    'error' : False,
    'response' : ... # where this is the documented response dict
}

For an Error:

{ 
    'error' : True,
    'message' : 'Description of what went wrong' 
}

It's been around for roughly 2 days now, and I already think we should abandon it.

Here's why:

We're trying to catch every error proactively in our util functions, and then manufacturing a consistent representation of an error. But why? Lambda already returns a consistent representation of an error with a payload that looks like this:

{u'stackTrace': [[u'/var/task/handler.py', 48, u'get', u"raise Exception('Test Exception')"]], u'errorMessage': u'Test Exception', u'errorType': u'Exception'}

So if we just check every response from a microservice for the existence of errorType we'll know if it was successful or not. We can even abstract that up into our Microservice class and fire an appropriate exception.

Python has Exceptions built in for a reason... Lambda has done a good job of honouring them... so should we.

godd9170 commented 7 years ago

Every Microservice should have a README.md in it's directory with an example of the payload it anticipates, and a chart that describes it. See mysql-poll's for some inspiration.