Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.94k stars 441 forks source link

The extensions.json file is often blank when QueueTrigger v4 AzFunction using .NET 6. #9280

Open kfwalther opened 1 year ago

kfwalther commented 1 year ago

When building and running our Azure functions in Visual Studio 2022 locally, we usually receive these not registered errors.

[2023-05-18T16:09:18.135Z] Host started (2311ms)
[2023-05-18T16:09:18.142Z] Job host started
[2023-05-18T16:09:18.161Z] The 'Function2' function is in error: The binding type(s) 'queueTrigger' are not registered. Please ensure the type is correct and the binding extension is installed.
[2023-05-18T16:09:18.171Z] The 'Function3' function is in error: The binding type(s) 'queue' are not registered. Please ensure the type is correct and the binding extension is installed.

We're using DI for a number of services within our Azure functions (including GraphServiceClient). Per the error, we've triple checked that the Microsoft.Azure.WebJobs.Extensions.Storage package is installed. We've tried downgrading to v4.0.5 of this package, but the symptoms persist. Here is our csproj file housing the Azure functions:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="1.8.2" />
    <PackageReference Include="Azure.Storage.Queues" Version="12.14.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.37" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.1.2" />
    <PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
    <PackageReference Include="Microsoft.Extensions.Azure" Version="1.6.3" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
    <PackageReference Include="Microsoft.Graph" Version="5.9.0" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Folder Include="bin\" />
  </ItemGroup>
  <Target Name="ZipFunctions" AfterTargets="build" DependsOnTargets="_GenerateFunctionsExtensionsMetadataPostBuild;_GenerateFunctionsPostBuild">
    <Exec Command="powershell.exe Compress-Archive -Path $(ProjectDir), $(OutDir)\bin, $(ProjectDir)host.json -DestinationPath $(ProjectDir)..\output\functionApp.zip -Force" />
  </Target>
</Project>

One of our functions looks like this:

    public class Function2
    {
        private readonly ILogger logger;

        public Function2(ILogger<Function2> logger)
        {
            this.logger = logger;
        }

        [FunctionName("Function2")]
        public async Task Run([QueueTrigger("%AzureStorageQueueName%", Connection = "CONNECTIONSTRING")] string myQueueItem)
        {
            logger.LogInformation($"Received notifications: {myQueueItem}");
        }
     }

When this occasionally works, the extensions.json file in the output directory will be populated, and all of the Azure functions properly register their bindings:

{
  "extensions":[
    { "name": "AzureStorage", "typeName":"Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage, Version=5.1.2.0, Culture=neutral, PublicKeyToken=<hash>"},
    { "name": "Startup", "typeName":"T2.Functions.Startup, T2FunctionApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<hash>"}
  ]
}

However, usually the extensions.json file appears blank as:

{
  "extensions":[
  ]
}

Investigative information

satvu commented 1 year ago

@kfwalther apologies for the delayed response - are you still experiencing issues? If this is production-impacting, please engage our support team.

Since you use DI and have a startup class, I recommend checking out this official guide for DI in dotnet. Please make sure you are not overriding any host services since that will especially lead to unexpected behavior.

ghost commented 1 year ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

If you are not the original author (kfwalther) and believe this issue is not stale, please comment with /bot not-stale and I will not close it.

kfwalther commented 1 year ago

@satvu Thanks for the link to the official guide, we used that to construct our initial implementation. We did find a work-around for the issue (which had the behavior of a race condition), but we're not sure why it works. We had to remove the _GenerateFunctionsExtensionsMetadataPostBuild dependency target from our ZipFunctions target in the .csproj file to get the extensions.json file consistently populated. So, we changed this:

  <Target Name="ZipFunctions" AfterTargets="build" DependsOnTargets="_GenerateFunctionsExtensionsMetadataPostBuild;_GenerateFunctionsPostBuild">
    <Exec Command="powershell.exe Compress-Archive -Path $(ProjectDir), $(OutDir)\bin, $(ProjectDir)host.json -DestinationPath $(ProjectDir)..\output\functionApp.zip -Force" />
  </Target>

to this:

  <Target Name="ZipFunctions" AfterTargets="build" DependsOnTargets="_GenerateFunctionsPostBuild">
    <Exec Command="powershell.exe Compress-Archive -Path $(ProjectDir), $(OutDir)\bin, $(ProjectDir)host.json -DestinationPath $(ProjectDir)..\output\functionApp.zip -Force" />
  </Target>

I would have thought this might exclude the extensions.json files from our zip, but it appears to be present. We have a few more questions than answers at this point, but at least it's working...

satvu commented 1 year ago

@kfwalther thanks for the additional information! Will discuss with team.