-
Notifications
You must be signed in to change notification settings - Fork 4
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
Function handlers discussion #14
Comments
Awesome! super clear write up @mthenw 🙌 ... Another benefit for us is that we'll have some access to user's code => awesome for tracking!
why do we treat http events differently than other event sources?
Any reason why you prefer lambda definition? it seems the most complex and maybe we can simplify things a bit more. For example Azure functions look very simple with that single
LOVE how short & simple that looks ... but don't you think it looks a bit "Lambda-ish" ... I mean sure AWS dont really have copy rights over the symbol, but in the mind of many developers, we'd be referring to all provider functions as "Lambda". Also, I'm on the fence with // not sure if the keyword "function" is reserved and can't be used as key though
exports.userFunc = serverless.function((event, context, callback) => {
callback(new Error('not implemented'))
});
// or
exports.userFunc = serverless.fn((event, context, callback) => {
callback(new Error('not implemented'))
});
// or
exports.userFunc = sl.fn((event, context, callback) => {
callback(new Error('not implemented'))
});
// or ... this is <3
exports.userFunc = sl.fn((e, ctx, cb) => cb(new Error('not implemented'))); How does this look? Overall, no matter how we end up doing this, I think it'll be a great user experience! Awesome stuff! 💯 |
Two more notes:
|
UX mainly. req/res pattern is well known and it just fits better this use case. It's much easier to use
When you look at
"In mathematical logic and computer science, lambda is used to introduce anonymous functions expressed with the concepts of lambda calculus." https://en.wikipedia.org/wiki/Lambda It's commonly used in programming languages to describe anonymous functions. BTW it's only a proposition for shortcut.
Hmm, I think that's fine. Because they are actually lambdas :)
It is reserverd. Though maybe
I don't think so. It's just a word describing function that handles something. There is nothing AWS specific here. Though I'm not saying that this is the best name :) Maybe
Hmm, not exactly understand the question. I guess in every language with first-class function we can achieve something like wrapping user function with our function. Would be great if you could clarify. |
Thanks for the writeup @mthenw! 👍 I like the idea of having one function handler which covers all the different FaaS providers. I'd love the drop In the beginning I liked the way Google separated the handlers between const stdlib = require('@serverless/stdlib')();
exports.userFunc = stdlib.handler((event, callback) => {
callback(new Error('not implemented'))
}); This could be the most minimal and simple handler we can provide. The other upside is that the user has to learn only one handler concept. Not sure what the upsides are of having one for http and one for the rest... Aside:
Unfortunately this is not true as the function code which executes the logic still needs to be adapted so that the corresponding Cloud provider understands it / can use their services. |
It's optional. But I see few use cases when that might be needed. Regarding one handler. First of all, it's not mandatory, generic handler can also be uses for HTTP funcs. Also, there is few important aspects of having separate http handler:
|
@mthenw Great research/write-up. This is the right way to start the conversation. From what I understand, you are proposing a single function handler and an optional Some thoughts about
Additionally, how will this proposed handler pattern work across languages? Any language-specific quirks that we need to be aware of? In general, I'm a fan of everything being discussed here. Overall, a very good starting point IMO. |
I would like to propose using a Promise as the unit-of-response in the "universal handler signature", not callbacks. It's going to be something that ends up having to be boilerplated on to every single thing. |
Also, in terms of event vs. req-res, my library: https://github.com/dougmoscrop/serverless-http might be of use/interest which represents lambda events as req/res objects so that existing frameworks (like koa or express or connect) can be used as the http pipeline. |
@mthenw This document is a really nice read! In what sense is the HTTP handler better UX? Do I miss the obvious? I'm pretty certain we can't return the express req/res objects. They contain a lot of functions and attributes which are not exposed in any of the function providers. Even Google provides just objects which looks like express, but a lot of stuff is missing. In addition they provide a list of body parsers by default (JSON body parser, Raw body parser, Text body parser, URL-encoded form body parser) while in express that's something you can customize. I'm not sure of some bodyparser setups supported by Google are possible with Lamba. The devil is in the details here. One thing that I would love to see is the raw event/context and so on directly attached to the context. React uses the same strategy with syntactic events. So when you do |
@dougmoscrop I love your promise based proposal. @mthenw and I talked for quite a while about it. I think it would be awesome, but I'm not sure if the community is ready for it. Maybe we support two versions: a promise based one and a callback version? To me it's certainly nice to use, especially with async/await coming 🙌 |
When I first looked at the Serverless framework, I thought this kind of abstraction would be a great thing. However, now I'm not so convinced. I'm not sure that function handler is the hard part of swapping between providers. Generally, my functions look like this.
Migrating that between providers is not a difficult problem. The hard part about swapping between providers is the other services like DynamoDb, Kinesis, SNS ect. Standardising the function abstracts functionality away from the user. It could be great for very simple use cases. But, I'm not sure this is a good thing. Of course, using this is completely optional (or should be). Tracking is probably a separate issue. I do like how IOPipe provides a wrapper around the handler to monitor functions. But it doesn't abstract any of the handler from the user. |
@johncmckim Totally agree on the vendor-lock in. I believe the idea behind it is: |
@ac360
Nice idea! I like that. Totally make sense. For now we can remove that. But the issue I see is request related metadata. There is no way to pass them. Getting them from global object doesn't seems right. |
Hmm, couldn't request related metadata that is in I already wrote all of this btw: |
@johncmckim The goal of providing standard handler is to make it easier to write functions. For the most use cases the differences between handlers expected by providers are slight but they are. We just want to simplify that. |
@ac360
Could you provide some example? |
I've created separate issue for generic handler #15. |
@dougmoscrop @nikgraf Even though promises are appealing in theory, I think in practice having a It would of course be possible to then add support for promises and generators and whatnot, but the most important is definitely the callback. |
Having a "standard" function handler for serverless function provides following benefits:
Research
AWS Lambda
One type of function handler:
In case of API Gateway event specified structure and specified structure is expected in callback.
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
Google Cloud Functions
Two types of function handler, one for HTTP functions, another for background functions. HTTP function handler accepts express-like arguments (
req
&res
).https://cloud.google.com/functions/docs/writing/http
Background function handler accepts
event
andcallback
arguments.https://cloud.google.com/functions/docs/writing/background
Azure Function
One type of function handler:
context
object differes between regular functions and functions triggered by HTTP request.In case of regular functions context object has a
bindings
property withmyInput
&myOutput
which can be used for getting input args and setting result.In case of HTTP func there are
req
&res
objects undercontext
.https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node
Proposition
We should provide two handlers. One generic handler and one for HTTP triggered functions.
Generic handler
In case of generic handler I would follow AWS Lambda definition. But as we want to abstract provider specific stuff,
context
object would be different thatcontext
object from AWS Lambda. Still, raw AWS Lambda context object should be accessible under e.g.AWSContext
key in stdlib'scontext
. Ascontext
object in most case it not needed in handler logic (and it doesn't occur in GCF) it's an optional argument.handler(function(event, [context], callback){})
(orλ(...)
)Arguments:
function(event, [context], callback)
- hander function. Function accepts following arguments:object
- additional infofunction
- callback function resultcallback(err, result)
.HTTP handler
http
is a handler for HTTP triggered functions. This handler takes function that accepts two arguments (express-likereq
&res
)http(function(event, [context], callback){})
Arguments:
function(req, res)
- HTTP hander function. Function accepts following arguments:Example:
cc @nikgraf @pmuens @ac360 @eahefnawy @DavidWells
The text was updated successfully, but these errors were encountered: