I never thought much about how Pulumi works, until...
# typescript
b
I never thought much about how Pulumi works, until now. Here's an aws lambda function I made in the console:
Copy code
console.log('Loading function');

var count = 0;

export const handler = async (event, context) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    console.log('count =', count++);
    return event.key1;
};
count
is a module scoped variable and preserves its counter between invocations, until the lambda is torn down after being idle. Try this with Pulumi:
Copy code
export const apiLambda = createLambda({
  name: 'my-lambda',
  callback: handler,
});

var count: number = 0;

async function handler(event: any, context: any) {
  console.log('EVENT: \n' + JSON.stringify(event, null, 2) + ` COUNT ${count++}`);
  return context.logStreamName;
}
and no such luck,
count
is always 0. I guess this has something to do with how Pulumi transpiles the code.
l
Not to do with transpilation. Pulumi doesn't transpile. I'd guess it's to do with when the code is run. In your first example, all that code is run in AWS, in the node instance that creates the lambda. In your second example, all that code is run on your deployment machine, at deployment time, maybe months prior to your lambda being invoked. It's not exactly an apples-to-apples comparison.
b
If I wanted a stable database connection that would last across lambda invocations, could I do this using Pulumi as the deployment tool? This is how I found the problem originally. I tried keeping a database connection in module scope, as recommended by the AWS lambda docs. But every invocation, I found the database connection had to be recreated. Always undefined. Never persisted.
l
You need to store that value in a persistent location. DynamoDB, SSM parameter, something like that.
Or hardcode it 🙂
c
In your Lambda code that is actually deployed to AWS, do you actually see the count variable as a global? It's global in your Pulumi code but not in your Lambda code.
l
Good point: if you use the normal lambda API ather than the createLambda convenience method, the entire file is runtime.. it should produce the same results as you saw via the console.
2
b
Right. Thanks.
l
Still, it's good practice to store external values... externally! 🙂 Even as a lambda envrionment variable would work.
b
In my case its a Snowflake connection.
Not a simple string value.
I was loathe to create a connection per invocation.
c
Somewhat related to what @little-cartoon-10569 is suggesting, this might be helpful for you https://aws.amazon.com/blogs/compute/caching-data-and-configuration-settings-with-aws-lambda-extensions/
1
b
thanks
As for transcompilation, or whatever you call it, I got that idea from this article: https://mark.smithson.me/pulumi-function-serialisation-by-example/
l
Ah yes, that's a thing. I was thinking of what happens to Pulumi programs, not to the lambda functions that Pulumi deploys. I don't use Pulumi for building lambda functions any more. Same for building OCI images. I don't think it's a good fit for Pulumi. I consider those to be more like node packages or jar files: products of CI. Pulumi is a deployment tool: I prefer to give it ready-to-deploy artifacts. There's a few reasons for this, and you've bumped up against one of them :)
👍 3
2
b
Thanks for confirming my suspicions.
g
Not sure if relevant, but may be interesting, I have a pulumi resource abstraction over lambdas in which I point to a file (
<path>/index.js/ts
, for example) and that resource calls esbuild to build/bundle the lambda code and all its imports and create the FileArchive. It doesn't mix runtime/deployment code and it helps me organizing my repo.
l
I have one of those too. But I'm seriously considering moving that out to a separate build, and pushing those built lambdas to a local package manager, so that Pulumi can deploy them later.
g
Would you still build them at deploy time? Or at which point/what triggers the build?
l
Build once, deploy many times. I would build them long before deploying, so that I can test them properly before they get promoted to production.