-
Notifications
You must be signed in to change notification settings - Fork 184
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
[Source Gen] Generate function executor code #1309
Conversation
sdk/Sdk.Generators/Targets/Microsoft.Azure.Functions.Worker.Sdk.Generators.props
Outdated
Show resolved
Hide resolved
We still need to discuss how to register this implementation to the DI container automatically during bootstrapping so that customer does not need to explicitly register it. Same for our src gen version of function metadata provider. |
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.cs
Outdated
Show resolved
Hide resolved
Wanted to add that I'm a big fan of the refactoring 😍 taking out the |
@@ -30,9 +32,6 @@ public static class Types | |||
// System types | |||
internal const string IEnumerable = "System.Collections.IEnumerable"; | |||
internal const string IEnumerableGeneric = "System.Collections.Generic.IEnumerable`1"; | |||
internal const string IEnumerableOfString = "System.Collections.Generic.IEnumerable`1<System.String>"; |
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.
Removed unused.
2529c6b
to
3969a98
Compare
3969a98
to
7bd807d
Compare
5a34157
to
5331e3a
Compare
a9cf275
to
7efa437
Compare
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs
Outdated
Show resolved
Hide resolved
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.cs
Outdated
Show resolved
Hide resolved
4c22ea8
to
748dfea
Compare
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.
Initial (partial) review
private static string GetMethodBody(IEnumerable<ExecutableFunction> functions) | ||
{ | ||
var sb = new StringBuilder(); | ||
sb.Append(@"var inputBindingFeature = context.Features.Get<IFunctionInputBindingFeature>()!; |
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: raw string literals would improve readability here
"); | ||
foreach (ExecutableFunction function in functions) | ||
{ | ||
sb.Append($@" |
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.
To improve readability, you can build the arguments then craft the entire string with those arguments injected. That will remove the number of string fragments you have 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.
I switched and I feel the readability is gone. The indentation was driving me crazy. I ended up adjusting code here to match with the expected output code in tests. I am sure there is a better way to write this. Yea, I don't like the current version.
private readonly GeneratorExecutionContext _context; | ||
private readonly KnownTypes _knownTypes; | ||
|
||
private Compilation Compilation => _context.Compilation; |
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: move below constructor.
sdk/Sdk.Generators/FunctionsUtil.cs
Outdated
/// <summary> | ||
/// Checks if a candidate method has a Function attribute on it. | ||
/// </summary> | ||
internal static bool IsValidMethodAzureFunction( |
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: naming -> IsValidFunctionMethod
or IsFunctionMethod
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.
Renamed.
@@ -22,6 +22,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and | |||
|
|||
<ItemGroup> | |||
<CompilerVisibleProperty Include="FunctionsEnableMetadataSourceGen" /> | |||
<CompilerVisibleProperty Include="FunctionsEnablePlaceholder" /> |
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 the generator is not related to placeholders, I think we need a better name here. Should also be something that clearly describes that it controls the source generation enablement. Perhaps FunctionsEnableExecutorSourceGenerator
, though, something shorter would be better.
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.
Switched to "FunctionsEnableExecutorSourceGen". We are using "FunctionsEnablePlaceholder" to control behavior such as "not generating the extension entry(of legacy json metadata generator) in function.json". Let's sync later whether to consolidate that with something else.
sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs
Show resolved
Hide resolved
if (string.Equals(context.FunctionDefinition.EntryPoint, ""{function.EntryPoint}"", StringComparison.OrdinalIgnoreCase)) | ||
{{"); | ||
|
||
int constructorParamCounter = 0; |
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.
The activation process should be consistent with what we have today. That will also handle constructor selection and type injection (i.e., continue to go through IFunctionActivator
).
Expansion to optimize activation can use the existing extensibility, but should be done separately
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.
Good point. Updated to use IFunctionActovator.
a5e1c1f
to
36421be
Compare
Fixes #1284
This source generator creates an implementation of
IFunctionExecutor
. Our current implementation ofIFunctionExecutor
relies on reflection at runtime (so it has an impact on coldstart). We have tried a hard coded version in our coldstart test environment and it proved to improve cold start numbers since no reflection code is being executed. In this PR, the source gen creates an implementation which is similar to the one linked above. We rely on IFunctionActivator in this version to create an instance of the function class.Generator needs to be enabled explicitly by using
<FunctionsEnableExecutorSourceGen>True</FunctionsEnableExecutorSourceGen>
in project file (of the function app)