-
Notifications
You must be signed in to change notification settings - Fork 158
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
Make serverless/function into a subclass of lambda/function. #202
Conversation
Note: this is not ready to go in. This is to start the discussion with @lukehoban |
let attachment = new RolePolicyAttachment(`${name}-${sha1hash(policy)}`, { | ||
role: this.role, | ||
policyArn: policy, | ||
}, { parent: this }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: parent:this was lost in my translation. the lambda-function needs the role. so it's unclear to me how to accomplish this.
@lukehoban can you take a look? |
} | ||
if (!args.role) { | ||
throw new Error("Missing 'role' in 'args'"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This argument validation is taken care of in aws.lambda.Function
constructor, soprobably not needed here since we don't use it in this context.
That said - I wonder if we do want to validate that code
, handler
and any other properties that conflict with these are not passed, since we'll be overwriting those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that's a good idea. Note: i front loaded the role check because i like early errors. it makes it clear it's the problem of the person who calls us, not a mistake on our end.
serialize = serialize || (_ => true); | ||
const finalSerialize = (o: any) => { | ||
return serialize(o) && o !== this; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate from this change - I'd still love to get rid of this serialize thing alltogether. I believe we think it is not actually needed anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been mitigated... but i think it may still be necessary. effectively, it depends on the asynchrony in user code. If we 'pump' while serializing, it's possible for us to observe loops form, which can then cause deadlocks.
I'll see about removing in a post PR.
const argsCopy = { | ||
...args, | ||
runtime: args.runtime || runtimes.NodeJS8d10Runtime, | ||
timeout: args.timeout === undefined ? 180 : args.timeout, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably remove this line here - and just provide this 180 default via the existing aws.serverless.Function
(and possibly in the future some equivalent layer in @pulumi/cloud
). Feels like we should only "change" things that we absolutely must to enable closure serialization to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good.
role: this.role.arn, | ||
timeout: options.timeout === undefined ? 180 : options.timeout, | ||
memorySize: options.memorySize, | ||
deadLetterConfig: options.deadLetterConfig, | ||
vpcConfig: options.vpcConfig, | ||
}, { parent: this }); | ||
// createFunction will actually supply the handler. This is just to satisfy typescript. | ||
handler: undefined!, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this mean that any user of createFunction
will have to do something awkward like this at it's callsite? That seems unfortunate?
I don't suppose there is any way to create a type that is another type but without a particular set of fields? :-)
Alternatively, we could force handler
to be not be marked as required in resources.go
. That somewhat weakens type checking for cases where you are calling aws.lambda.Function()
directly, but may be worth it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't suppose there is any way to create a type that is another type but without a particular set of fields? :-)
I believe so :) I think typescript added new type-operating functions for precisely thsi purpose. let me look into it.
}, { parent: this }); | ||
// createFunction will actually supply the handler. This is just to satisfy typescript. | ||
handler: undefined!, | ||
runtime: options.runtime || lambda.NodeJS6d10Runtime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we overriding this to 6.10 here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is hte logic that was already here. I'm not sure our reasoning. @swgillespie ?
overlays/nodejs/utils.ts
Outdated
[K in O]: (Record<D, never> & Record<string, K>)[K] | ||
}[O] | ||
|
||
export type Omit<O, D extends string> = Pick<O, Sub<keyof O, D>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typescript be crazy!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i had to look at this for a few minutes to wrap my head around what was going on.
@lukehoban can you takea nother look? |
overlays/nodejs/utils.ts
Outdated
|
||
export type Sub<O extends string, D extends string> = { | ||
[K in O]: (Record<D, never> & Record<string, K>)[K] | ||
}[O] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the weirdest part for me (specifically the [O]
part). I've never used the indexed access operator
in creating a type before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Longterm, I can imagine perhaps wanting to fold createFunction
into the existing new aws.lambda.Function
, with a single unified bag of args, but this seems a very pragmatic way to expose creation of a raw callback-based Lambda for now.
|
||
// User sholud not supply 'code' or 'handler' to createFunction. We will create those | ||
// out of the handler they pass in. | ||
export type CallbackFunctionArgs = utils.Omit<lambda.FunctionArgs, "code" | "handler"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is public - lets put a doc comment and phrase this as user facing documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
role: this.role.arn, | ||
timeout: options.timeout === undefined ? 180 : options.timeout, | ||
memorySize: options.memorySize, | ||
deadLetterConfig: options.deadLetterConfig, | ||
vpcConfig: options.vpcConfig, | ||
}, { parent: this }); | ||
runtime: options.runtime || lambda.NodeJS6d10Runtime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code used to use 8.10, and it seems you are changing it back to use 6.10. Any reason why?
The change to 8.10 was made a couple weeks ago in #194.
} | ||
if ((<any>args).handler) { | ||
throw new Error("'handler' property should not be provided in 'args'"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that these properties are no longer on the type, seems fine to not check for them not being passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to keep this in. People may call from JS and they may easily get confused and think they need these due to the docs for lambda.Function. This is a pretty simple check to have, and it could prevent confusion.
overlays/nodejs/utils.ts
Outdated
// Helpers to create 'subtraction' types. i.e. a type equivalent to some other object type, | ||
// just with some members removed. | ||
|
||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-| I have no idea how that works, but nice that this is possible.
Are there any downsides to this? I assume error messages are still reasonable when these types are involved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. the error messages will still be of the form "you need this property 'x'"
export type CallbackFunctionArgs = utils.Omit<lambda.FunctionArgs, "code" | "handler"> | ||
|
||
/** | ||
* Helper to create an aws lambda function out of an actual javascript callback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Capitalization of all proper nouns here, also maybe phrase a little more explicitly as a first class part of the API.
No description provided.