-
Notifications
You must be signed in to change notification settings - Fork 13
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
Respecting _HANDLER
environment variable
#69
Comments
One option that already exists (but isn't made obvious anywhere) is to use Here's a snippet from a project where I did this (I've left the comment, because it's somewhat relevant to the convo!)
It's a bit boilerplate-y and there's no examples or recommendations towards a pattern like this, but I do think it's a pretty reasonable approach. Not sure how to improve upon this or make it "first class" rather than some random trick. And while the It's an interesting idea though. I'm still not seeing the use case jump out at me, but I'd certainly be interested to pull the thread a bit more. |
I think it's probably going to remain a niche tool in the Haskell Lambda toolbox, but I think it could be handy in niche cases. Maybe for smaller projects where you just starting to split things out, or when you're refactoring code and don't want to commit to standing up new How about this? I feel like it's simple enough match import Control.Monad.IO.Class
import Data.Map (Map)
import qualified Data.Map as M
import Data.Text (Text)
import System.Environment (getEnv)
import qualified Data.Text as T
dispatchHandler :: MonadIO m => Map Text (m ()) -> m ()
dispatchHandler handlers = do
handler <- fmap T.pack . liftIO $ getEnv "_HANDLER"
case M.lookup handler handlers of
Nothing -> error $ "No handler defined for " ++ show handler
Just h -> h If you really wanted to force the usual handlers :: [Name] -> ExpQ
handlers = _
main = $(handlers ['Foo.bar, 'baz, 'quux]) But this feels too magical to fit in with the rest of |
This does look like something that is pretty small and probably reasonably supportable in the long term. I like that the My outstanding thoughts are:
Not to say we need to work out all things above, just stuff I figure is worth discussing a bit more :) |
This isn't quite what I meant, and I think it's clearer if I show more of an example sketch: main = dispatchHandler $ Map.fromList
[ ("Foo", runReaderTLambdaContext (evalStateT (mRuntimeWithContext myHandler) 0)) -- for argument's sake
, ("Bar", liftIO $ pureRuntime someOtherHandler)
] There's not really anywhere to stick a |
Yeah, sorry, that example is what I expected, I just said it poorly :) Before the previous comment, I was thinking about having the runners on the result of Given that we'd expect the user to resolve constarints before passing to the I suppose a constraint does allow you to resolve constraints that are common to all handlers at the end. |
Yes. If you use |
I think the best thing here is for programmers to inspect |
Continuation of #66 . The AWS docs for custom runtimes say that the
_HANDLER
environment variable lets the same piece of code be deployed multiple times to handle different requests.In larger applications, I think that this can be useful to limit the proliferation of
executable
targets in cabal files for larger lambda applications. One way to do this could be to provide aHandler
GADT that can wrap up functions matching the types of those inAWS.Lambda.Runtime
, and a functionrunHandlers :: [(Text, Handler)] -> IO ()
or something.@IamfromSpace :
If you can distinguish the events without needing to branch on
_HANDLER
then you're right that you'll share your execution environments and cut down on cold starts. Example: once #52 lands, it should be possible to build a little router package on top of it for API Gateway use.But suppose you have a larger application made out of a bunch of Lambda functions responding to different events: some listening to API Gateway events, some listening to SNS topics, whatever. With the current setup, it's easy to fall into a setup where you feel like you "need" to have a separate executable for each lambda. This then slows you down because you're going to be building and uploading a bunch of different executables.
I think there's a way you can do this within the existing combinators, including branching off
_HANDLER
. It might needdependent-map
to be completely safe. Supporting_HANDLER
might be a good fit here, but going to the Nth degree of type-safety might be above the complexity appetite for this package. I'll probably need to experiment and think some more before I have something I really want to push ahead with.The text was updated successfully, but these errors were encountered: