-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbootstrap.clj
71 lines (62 loc) · 2.54 KB
/
bootstrap.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
;; AWS Lambda runtime using babashka.
;;
;; The bootstrap shell script will run this
;; and set the classpath to the $LAMBDA_TASK_ROOT.
(require '[org.httpkit.client :as http]
'[clojure.string :as str]
'[cheshire.core :as cheshire])
(def handler-name (System/getenv "_HANDLER"))
(println "Loading babashka lambda handler: " handler-name)
(def runtime-api-url (str "http://" (System/getenv "AWS_LAMBDA_RUNTIME_API") "/2018-06-01/runtime/"))
(defn throwable->error-body [t]
{:errorMessage (.getMessage t)
:errorType (-> t .getClass .getName)
:stackTrace (mapv str (.getStackTrace t))})
;; load handler
(def handler
(let [[handler-ns handler-fn] (str/split handler-name #"/")]
(try
(require (symbol handler-ns))
(resolve (symbol handler-ns handler-fn))
(catch Throwable t
(println "Unable to run initialize handler fn " handler-fn "in namespace" handler-ns
"\nthrow: " t)
(http/post (str runtime-api-url "init/error")
{:body (cheshire/encode
(throwable->error-body t))})
nil))))
(when-not handler
(http/post (str runtime-api-url "init/error")
{:headers {"Lambda-Runtime-Function-Error-Type" "Runtime.NoSuchHandler"}
:body (cheshire/encode {"error" (str handler-name " didn't resolve.")})}))
;; API says not to use timeout when getting next invocation, so make it a long one
(def timeout-ms (* 1000 60 60 24))
(defn next-invocation
"Get the next invocation, returns payload and fn to respond."
[]
(let [{:keys [headers body]}
@(http/get (str runtime-api-url "invocation/next")
{:timeout timeout-ms
:as :text})
id (:lambda-runtime-aws-request-id headers)]
{:event (cheshire/decode body keyword)
:context headers
:send-response!
(fn [response]
@(http/post (str runtime-api-url "invocation/" id "/response")
{:body (cheshire/encode response)}))
:send-error!
(fn [thrown]
@(http/post (str runtime-api-url "invocation/" id "/error")
{:body (cheshire/encode
(throwable->error-body thrown))}))}))
(when handler
(println "Starting babashka lambda event loop")
(loop [{:keys [event context send-response! send-error!]} (next-invocation)]
(try
(let [response (handler event context)]
(send-response! response))
(catch Throwable t
(println "Error in executing handler" t)
(send-error! t)))
(recur (next-invocation))))