Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="azure_app_service" value="https://www.myget.org/F/azure-appservice/api/v2" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json"/>
<add key="sdk" value="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" />
</packageSources>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

using Microsoft.Azure.Functions.Worker.Extensions.Abstractions;

[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.ServiceBus", "5.7.0")]
[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.ServiceBus", "5.10.0")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Core;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

[assembly: WorkerExtensionStartup(typeof(ServiceBusExtensionStartup))]

namespace Microsoft.Azure.Functions.Worker
{
public class ServiceBusExtensionStartup : WorkerExtensionStartup
{
public override void Configure(IFunctionsWorkerApplicationBuilder applicationBuilder)
{
if (applicationBuilder == null)
{
throw new ArgumentNullException(nameof(applicationBuilder));
}

applicationBuilder.Services.AddAzureClientsCore(); // Adds AzureComponentFactory

applicationBuilder.Services.Configure<WorkerOptions>((workerOption) =>
{
workerOption.InputConverters.RegisterAt<ServiceBusReceivedMessageConverter>(0);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Azure.Core.Amqp;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Primitives;
using Microsoft.Azure.Functions.Worker.Converters;
using Microsoft.Azure.Functions.Worker.Core;
using Microsoft.Azure.Functions.Worker.Extensions.Abstractions;

namespace Microsoft.Azure.Functions.Worker;

[SupportsDeferredBinding]
[SupportedConverterType(typeof(ServiceBusReceivedMessage))]
[SupportedConverterType(typeof(IList<ServiceBusReceivedMessage>))]
internal class ServiceBusReceivedMessageConverter : IInputConverter
{
public ValueTask<ConversionResult> ConvertAsync(ConverterContext context)
{
ConversionResult result = context?.Source switch
{
ModelBindingData binding => ConversionResult.Success(ConvertToServiceBusReceivedMessage(binding)),
CollectionModelBindingData collection when context.TargetType.IsArray => ConversionResult.Success(collection.ModelBindingDataArray.Select(ConvertToServiceBusReceivedMessage).ToArray()),
CollectionModelBindingData collection => ConversionResult.Success(collection.ModelBindingDataArray.Select(ConvertToServiceBusReceivedMessage).ToList()),
_ => ConversionResult.Unhandled()
};
return new ValueTask<ConversionResult>(result);
}

private ServiceBusReceivedMessage ConvertToServiceBusReceivedMessage(ModelBindingData binding)
{
// The lock token is a 16 byte GUID
const int lockTokenLength = 16;

if (binding.ContentType != "application/octet-stream")
{
throw new InvalidOperationException("Only binary data is supported.");
}

ReadOnlyMemory<byte> bytes = binding.Content.ToMemory();
ReadOnlyMemory<byte> lockTokenBytes = bytes.Slice(0, lockTokenLength);
ReadOnlyMemory<byte> messageBytes = bytes.Slice(lockTokenLength, bytes.Length - lockTokenLength);
return ServiceBusReceivedMessage.FromAmqpMessage(AmqpAnnotatedMessage.FromBytes(BinaryData.FromBytes(messageBytes)), BinaryData.FromBytes(lockTokenBytes));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.Azure.Functions.Worker.Extensions.Abstractions;
using System.Collections.Generic;
using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Functions.Worker.Converters;
using Microsoft.Azure.Functions.Worker.Extensions.Abstractions;

namespace Microsoft.Azure.Functions.Worker
{
[AllowConverterFallback(true)]
[InputConverter(typeof(ServiceBusReceivedMessageConverter))]
public sealed class ServiceBusTriggerAttribute : TriggerBindingAttribute, ISupportCardinality
{
private bool _isBatched = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,26 @@
<Description>Azure Service Bus extensions for .NET isolated functions</Description>

<!--Version information-->
<VersionPrefix>5.7.0</VersionPrefix>
<VersionPrefix>5.9.0</VersionPrefix>

<!--Temporarily opting out of documentation. Pending documentation-->
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>

<Import Project="..\..\..\build\Extensions.props" />


<ItemGroup>
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.14.0" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Worker.Extensions.Abstractions\src\Worker.Extensions.Abstractions.csproj" />
<ProjectReference Include="..\..\..\src\DotNetWorker.Core\DotNetWorker.Core.csproj" />
</ItemGroup>

<ItemGroup>
<SharedReference Include="..\..\Worker.Extensions.Shared/Worker.Extensions.Shared.csproj" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions test/E2ETests/E2EApps/E2EApp/Blob/BlobTestFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 2 additions & 0 deletions test/E2ETests/E2EApps/E2EApp/E2EApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.ServiceBus\src\Worker.Extensions.ServiceBus.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.Storage\src\Worker.Extensions.Storage.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.Abstractions\src\Worker.Extensions.Abstractions.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.CosmosDB\src\Worker.Extensions.CosmosDB.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.EventHubs\src\Worker.Extensions.EventHubs.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.Http\src\Worker.Extensions.Http.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.Tables\src\Worker.Extensions.Tables.csproj" />
<ProjectReference Include="..\..\..\..\extensions\Worker.Extensions.Timer\src\Worker.Extensions.Timer.csproj" />
<ProjectReference Condition="$(TestBuild) != 'true'" Include="..\..\..\..\src\DotNetWorker\DotNetWorker.csproj" />
</ItemGroup>
Expand Down
9 changes: 9 additions & 0 deletions test/E2ETests/E2ETests/HttpEndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public async Task HttpTriggerTests(string functionName, string queryString, Http
}
}

[Fact]
public async Task TablesOutputTest()
{
HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger("TablesOutputBinding");
string actualMessage = await response.Content.ReadAsStringAsync();
await HttpHelpers.InvokeHttpTrigger("TablesInputBinding");

}

[Theory]
[InlineData("HelloFromJsonBody", "{\"Name\": \"Whitney\"}", "application/json", HttpStatusCode.OK, "Hello Whitney")]
[InlineData("HelloFromJsonBody", "{\"Name\": \"麵🍜\"}", "application/json", HttpStatusCode.OK, "Hello 麵🍜")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
using Azure.Storage.Blobs;
using Microsoft.Azure.Functions.Tests;
using Microsoft.Azure.Functions.Worker;
Expand Down Expand Up @@ -1034,6 +1035,16 @@ public object BlobStringToBlobPocoArray(
}
}

private class ServiceBusSDKBindings
{
[Function("ServiceBusTriggerFunction")]
public object ServiceBusFunction(
[ServiceBusTrigger("queue")] ServiceBusReceivedMessage message)
{
throw new NotImplementedException();
}
}

private class ExternalType_Return
{
public const string FunctionName = "BasicHttpWithExternalTypeReturn";
Expand Down
1 change: 1 addition & 0 deletions test/FunctionMetadataGeneratorTests/SdkTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<ProjectReference Include="..\..\extensions\Worker.Extensions.Storage\src\Worker.Extensions.Storage.csproj" />
<ProjectReference Include="..\..\extensions\Worker.Extensions.Timer\src\Worker.Extensions.Timer.csproj" />
<ProjectReference Include="..\..\extensions\Worker.Extensions.EventHubs\src\Worker.Extensions.EventHubs.csproj" />
<ProjectReference Include="..\..\extensions\Worker.Extensions.ServiceBus\src\Worker.Extensions.ServiceBus.csproj" />
<ProjectReference Include="..\..\sdk\FunctionMetadataLoaderExtension\FunctionMetadataLoaderExtension.csproj" />
<ProjectReference Include="..\..\sdk\Sdk\Sdk.csproj" />
<ProjectReference Include="..\..\src\DotNetWorker\DotNetWorker.csproj" />
Expand Down