-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
1888c9a
commit 93ceef1
Showing
23 changed files
with
798 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
extensions/Worker.Extensions.Storage.Queues/src/Constants.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
namespace Microsoft.Azure.Functions.Worker.Storage.Queues | ||
{ | ||
internal static class Constants | ||
{ | ||
internal const string QueueExtensionName = "AzureStorageQueues"; | ||
internal const string QueueMessageText = "MessageText"; | ||
|
||
// Media content types | ||
internal const string JsonContentType = "application/json"; | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
extensions/Worker.Extensions.Storage.Queues/src/JsonConverters/QueueMessageJsonConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// 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.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Azure.Storage.Queues.Models; | ||
|
||
namespace Microsoft.Azure.Functions.Worker.Storage.Queues | ||
{ | ||
internal class QueueMessageJsonConverter : JsonConverter<QueueMessage> | ||
{ | ||
public override bool CanConvert(Type objectType) => objectType == typeof(QueueMessage); | ||
|
||
public override QueueMessage? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
if (reader.TokenType is not JsonTokenType.StartObject) | ||
{ | ||
throw new JsonException("JSON payload expected to start with StartObject token."); | ||
} | ||
|
||
string messageId = String.Empty; | ||
string popReceipt = String.Empty; | ||
string messageText = String.Empty; | ||
long dequeueCount = 1; | ||
DateTime? nextVisibleOn = null; | ||
DateTime? insertedOn = null; | ||
DateTime? expiresOn = null; | ||
|
||
var startDepth = reader.CurrentDepth; | ||
|
||
while (reader.Read()) | ||
{ | ||
if (reader.TokenType is JsonTokenType.EndObject && reader.CurrentDepth == startDepth) | ||
{ | ||
return QueuesModelFactory.QueueMessage( | ||
messageId, | ||
popReceipt, | ||
messageText, | ||
dequeueCount, | ||
nextVisibleOn, | ||
insertedOn, | ||
expiresOn | ||
); | ||
} | ||
|
||
if (reader.TokenType is not JsonTokenType.PropertyName) | ||
{ | ||
continue; | ||
} | ||
|
||
var propertyName = reader.GetString(); | ||
reader.Read(); | ||
|
||
switch (propertyName?.ToLowerInvariant()) | ||
{ | ||
case "messageid": | ||
messageId = reader.GetString() ?? throw new JsonException("JSON payload must contain a MessageId."); | ||
break; | ||
case "popreceipt": | ||
popReceipt = reader.GetString() ?? throw new JsonException("JSON payload must contain a PopReceipt."); | ||
break; | ||
case "messagetext": | ||
messageText = reader.GetString() ?? throw new JsonException("JSOn payload must contain a MessageText."); | ||
break; | ||
case "dequeuecount": | ||
dequeueCount = reader.GetInt64(); | ||
break; | ||
case "nextvisibleon": | ||
nextVisibleOn = reader.GetDateTime(); | ||
break; | ||
case "insertedon": | ||
insertedOn = reader.GetDateTime(); | ||
break; | ||
case "expireson": | ||
expiresOn = reader.GetDateTime(); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
throw new JsonException("JSON payload expected to end with EndObject token."); | ||
} | ||
|
||
public override void Write(Utf8JsonWriter writer, QueueMessage value, JsonSerializerOptions options) | ||
{ | ||
throw new JsonException($"Serialization is not supported by the {nameof(QueueMessageJsonConverter)}."); | ||
} | ||
} | ||
} |
6 changes: 4 additions & 2 deletions
6
extensions/Worker.Extensions.Storage.Queues/src/Properties/AssemblyInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
// 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.Runtime.CompilerServices; | ||
using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; | ||
|
||
[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.1.2")] | ||
[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.1.3")] | ||
[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] |
6 changes: 5 additions & 1 deletion
6
extensions/Worker.Extensions.Storage.Queues/src/QueueTriggerAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueConverterBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// 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.Globalization; | ||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Functions.Worker.Converters; | ||
using Microsoft.Azure.Functions.Worker.Core; | ||
using Microsoft.Azure.Functions.Worker.Extensions; | ||
using Microsoft.Azure.Functions.Worker.Storage.Queues; | ||
|
||
namespace Microsoft.Azure.Functions.Worker | ||
{ | ||
internal abstract class QueueConverterBase<T> : IInputConverter | ||
{ | ||
public QueueConverterBase() | ||
{ | ||
} | ||
|
||
public bool CanConvert(ConverterContext context) | ||
{ | ||
if (context is null) | ||
{ | ||
throw new ArgumentNullException(nameof(context)); | ||
} | ||
|
||
if (context.TargetType != typeof(T)) | ||
{ | ||
return false; | ||
} | ||
|
||
if (context.Source is not ModelBindingData bindingData) | ||
{ | ||
return false; | ||
} | ||
|
||
if (bindingData.Source is not Constants.QueueExtensionName) | ||
{ | ||
throw new InvalidBindingSourceException(bindingData.Source, Constants.QueueExtensionName); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public async ValueTask<ConversionResult> ConvertAsync(ConverterContext context) | ||
{ | ||
try | ||
{ | ||
if (!CanConvert(context)) | ||
{ | ||
return ConversionResult.Unhandled(); | ||
} | ||
|
||
var modelBindingData = (ModelBindingData)context.Source!; | ||
var result = await ConvertCoreAsync(modelBindingData); | ||
return ConversionResult.Success(result); | ||
} | ||
catch (JsonException ex) | ||
{ | ||
string msg = String.Format(CultureInfo.CurrentCulture, | ||
@"Binding parameters to complex objects uses JSON serialization. | ||
1. Bind the parameter type as 'string' instead to get the raw values and avoid JSON deserialization, or | ||
2. Change the queue payload to be valid json."); | ||
|
||
return ConversionResult.Failed(new InvalidOperationException(msg, ex)); | ||
} | ||
catch (Exception ex) | ||
{ | ||
return ConversionResult.Failed(ex); | ||
} | ||
} | ||
|
||
protected abstract ValueTask<T> ConvertCoreAsync(ModelBindingData data); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...ns/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageBinaryDataConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// 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.Text.Json; | ||
using System.Threading.Tasks; | ||
using Microsoft.Azure.Functions.Worker.Converters; | ||
using Microsoft.Azure.Functions.Worker.Core; | ||
using Microsoft.Azure.Functions.Worker.Extensions; | ||
using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; | ||
using Microsoft.Azure.Functions.Worker.Storage.Queues; | ||
|
||
namespace Microsoft.Azure.Functions.Worker | ||
{ | ||
/// <summary> | ||
/// Converter to bind to <see cref="BinaryData" /> type parameters. | ||
/// </summary> | ||
[SupportsDeferredBinding] | ||
[SupportedTargetType(typeof(BinaryData))] | ||
internal sealed class QueueMessageBinaryDataConverter : QueueConverterBase<BinaryData> | ||
{ | ||
public QueueMessageBinaryDataConverter() : base() | ||
{ | ||
} | ||
|
||
protected override ValueTask<BinaryData> ConvertCoreAsync(ModelBindingData data) | ||
{ | ||
return new ValueTask<BinaryData>(ExtractQueueMessageContent(data)); | ||
} | ||
|
||
private BinaryData ExtractQueueMessageContent(ModelBindingData modelBindingData) | ||
{ | ||
if (modelBindingData.ContentType is not Constants.JsonContentType) | ||
{ | ||
throw new InvalidContentTypeException(modelBindingData.ContentType, Constants.JsonContentType); | ||
} | ||
|
||
var content = modelBindingData.Content.ToObjectFromJson<JsonElement>(); | ||
var messageText = content.GetProperty(Constants.QueueMessageText).ToString() | ||
?? throw new InvalidOperationException($"The '{Constants.QueueMessageText}' property is missing or null."); | ||
|
||
return new BinaryData(messageText); | ||
} | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using System.Text.Json; | ||
using System.Threading.Tasks; | ||
using Azure.Storage.Queues.Models; | ||
using Microsoft.Azure.Functions.Worker.Converters; | ||
using Microsoft.Azure.Functions.Worker.Core; | ||
using Microsoft.Azure.Functions.Worker.Extensions; | ||
using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; | ||
using Microsoft.Azure.Functions.Worker.Storage.Queues; | ||
|
||
namespace Microsoft.Azure.Functions.Worker | ||
{ | ||
/// <summary> | ||
/// Converter to bind to <see cref="QueueMessage" /> type parameters. | ||
/// </summary> | ||
[SupportsDeferredBinding] | ||
[SupportedTargetType(typeof(QueueMessage))] | ||
internal sealed class QueueMessageConverter : QueueConverterBase<QueueMessage> | ||
{ | ||
private readonly JsonSerializerOptions _jsonOptions; | ||
|
||
public QueueMessageConverter() : base() | ||
{ | ||
_jsonOptions = new() { Converters = { new QueueMessageJsonConverter() } }; | ||
} | ||
|
||
protected override ValueTask<QueueMessage> ConvertCoreAsync(ModelBindingData data) | ||
{ | ||
return new ValueTask<QueueMessage>(ExtractQueueMessage(data)); | ||
} | ||
|
||
private QueueMessage ExtractQueueMessage(ModelBindingData modelBindingData) | ||
{ | ||
if (modelBindingData.ContentType is not Constants.JsonContentType) | ||
{ | ||
throw new InvalidContentTypeException(modelBindingData.ContentType, Constants.JsonContentType); | ||
} | ||
|
||
return modelBindingData.Content.ToObjectFromJson<QueueMessage>(_jsonOptions); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using Azure.Storage.Queues.Models; | ||
using Microsoft.Azure.Functions.Worker; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace SampleApp | ||
{ | ||
/// <summary> | ||
/// Samples demonstrating binding to <see cref="QueueMessage"/> and <see cref="BinaryData"/> types. | ||
/// </summary> | ||
public class QueueSamples | ||
{ | ||
private readonly ILogger<QueueSamples> _logger; | ||
|
||
public QueueSamples(ILogger<QueueSamples> logger) | ||
{ | ||
_logger = logger; | ||
} | ||
|
||
/// <summary> | ||
/// This function demonstrates binding to a single <see cref="QueueMessage"/>. | ||
/// </summary> | ||
[Function(nameof(QueueMessageFunction))] | ||
public void QueueMessageFunction([QueueTrigger("input-queue")] QueueMessage message) | ||
{ | ||
_logger.LogInformation(message.MessageText); | ||
} | ||
|
||
/// <summary> | ||
/// This function demonstrates binding to a single <see cref="BinaryData"/>. | ||
/// </summary> | ||
[Function(nameof(QueueBinaryDataFunction))] | ||
public void QueueBinaryDataFunction([QueueTrigger("input-queue-binarydata")] BinaryData message) | ||
{ | ||
_logger.LogInformation(message.ToString()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.