General Node/Async/Lambda Question We are switchi...
# random
a
General Node/Async/Lambda Question We are switching from storing ssm parameter store variables in process.env to accessing them via API at runtime (this is more secure and avoids the 4kb max env variable size on lambda functions) Currently we have a developer friendly set up like the following, where the environment variables are resolved at deployment by serverless environment variables
Copy code
// Node.js file
const {a,b,c} = process.env

module.exports.lambdaHandler1 = async () => {
  console.log(a)
  helperFunction1()
}

function helperFunction1() {
  console.log(b)
}

module.exports.lambdaHandler2 = async () => {
  console.log(c)
}
We want to switch to using the AWS Node SDK getParameters function to get the parameters at run time. Does anyone have any suggestions for calling the get parameters function at the top of the lambda handler file to simplify variable declaration for these variables that will be shared across many functions? This is an async function, so i cant await the function call at the top level, since it is outside any async functions. My immediate first idea was a simple change to something like below, but this does not work due to the getParameters call being async.
Copy code
// Node.js file

// This wont work because you can not use await outside an async function
const {a,b,c} = await AWS.SSM().getParameters(['/path/to/a', '/path/to/b', '/path/to/c'])


module.exports.lambdaHandler1 = async () => {
  console.log(a)
  helperFunction1()
}

function helperFunction1() {
  console.log(b)
}

module.exports.lambdaHandler2 = async () => {
  console.log(c)
}
What I really want to avoid is calling the “getParameters” function inside each lambda handler. That results in a lot of duplicate code and means that any helper function where we want to use an environment variable (like a database name) must be asynchronous or updated to take the env var as a parameter, which is unnecessary for many of these helper functions
s
a
Middy has a middleware for this. @sailplane/state-storage can be used too - particularly useful in combination with ExpiringValue to cache & refresh configuration that may change during a long running warm Lambda.
a
Hi Seth, Thanks for that link, I found that earlier today and found it very insightful. However it solves a different issue than what I am looking for here. That solution would still require calling the getParameters (cached or not) helper function at the top level of every lambda handler in the file, which is what i am looking to avoid
a
With the sailplane approach I usually put it in a service layer, so the parameters are lazy loaded where needed. Otherwise, I suggest the Middy middleware as a means of consolidating common initialization.
s
Ahh, I see what you're saying Alex. Sounds like Adams solution may be what you're looking for
t
@Alex Ketchum so.....there is a solution
There's 2 solutions
The solution I'm using right now is horrific, I would advise against it which is using
deasync
to pause the nodejs event loop so that it fetches synchronously. It works but is terrible
The second solution is node14 + aws lambda supports top level await which would allow you to await to load parameters in a module and others could just import it like they were normal exports
I have some work with SST left to do to make that possible - will get to it in the coming weeks
Without this solution, I don't think SSM is a real replacement for
process.env
because it forces you to add another dependency injection layer outside the base module system
a
wow @thdxr the node14 top level await support is a huge game changer. updating to node14 has been on the “nice to have” list for a while but there has always been something more important. This is a great excuse to finally make the upgrade @Adam Fanello thanks for the link to sailplane! It was very interesting to check out and looks like a great resource. Really appreciate everyones advice! Thanks!
a
Alternative to top level await is to initiate the request at the top level and store the Promise value. By the time you actually want the SSM value, it'll probably be fetched. Doing an await on an already resolved Promise doesn't cause any delay (I believe).