-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DataAnnotations for azure options and use the HostBuilder setup
- Loading branch information
Lennart ten Wolde
authored and
Lennart ten Wolde
committed
May 2, 2023
1 parent
eb66559
commit cc78d71
Showing
44 changed files
with
1,153 additions
and
1,074 deletions.
There are no files selected for viewing
100 changes: 100 additions & 0 deletions
100
lib/Dequeueable.AzureQueueStorage/Configurations/HostBuilder.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,100 @@ | ||
using Dequeueable.AzureQueueStorage.Factories; | ||
using Dequeueable.AzureQueueStorage.Services.Hosts; | ||
using Dequeueable.AzureQueueStorage.Services.Queues; | ||
using Dequeueable.AzureQueueStorage.Services.Singleton; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Dequeueable.AzureQueueStorage.Configurations | ||
{ | ||
internal class HostBuilder : IDequeueableHostBuilder | ||
{ | ||
private readonly IServiceCollection _services; | ||
|
||
public HostBuilder(IServiceCollection services) | ||
{ | ||
_services = services; | ||
} | ||
|
||
public IDequeueableHostBuilder RunAsJob(Action<HostOptions>? options = null) | ||
{ | ||
_services.AddOptions<HostOptions>().BindConfiguration(HostOptions.Dequeueable) | ||
.ValidateDataAnnotations() | ||
.ValidateOnStart(); | ||
|
||
if (options is not null) | ||
{ | ||
_services.Configure(options); | ||
} | ||
|
||
_services.AddHostedService<JobHost>(); | ||
_services.AddSingleton<IHostExecutor, JobExecutor>(); | ||
|
||
_services.TryAddSingleton<IHostOptions>(provider => | ||
{ | ||
var opt = provider.GetRequiredService<IOptions<HostOptions>>(); | ||
return opt.Value; | ||
}); | ||
|
||
return this; | ||
} | ||
|
||
public IDequeueableHostBuilder RunAsListener(Action<ListenerOptions>? options = null) | ||
{ | ||
_services.AddOptions<ListenerOptions>().BindConfiguration(HostOptions.Dequeueable) | ||
.Validate(ListenerOptions.ValidatePollingInterval, $"The '{nameof(ListenerOptions.MinimumPollingIntervalInMilliseconds)}' must not be greater than the '{nameof(ListenerOptions.MaximumPollingIntervalInMilliseconds)}'.") | ||
.Validate(ListenerOptions.ValidateNewBatchThreshold, $"The '{nameof(ListenerOptions.NewBatchThreshold)}' must not be greater than the '{nameof(ListenerOptions.BatchSize)}'.") | ||
.ValidateDataAnnotations() | ||
.ValidateOnStart(); | ||
|
||
if (options is not null) | ||
{ | ||
_services.Configure(options); | ||
} | ||
|
||
_services.AddHostedService<QueueListenerHost>(); | ||
_services.AddSingleton<IHostExecutor, QueueListenerExecutor>(); | ||
|
||
_services.TryAddSingleton<IHostOptions>(provider => | ||
{ | ||
var opt = provider.GetRequiredService<IOptions<ListenerOptions>>(); | ||
return opt.Value; | ||
}); | ||
|
||
return this; | ||
} | ||
|
||
public IDequeueableHostBuilder AsSingleton(Action<SingletonOptions>? options = null) | ||
{ | ||
_services.AddOptions<SingletonOptions>().BindConfiguration(SingletonOptions.Name) | ||
.Validate(SingletonOptions.ValidatePollingInterval, $"The '{nameof(SingletonOptions.MinimumPollingIntervalInSeconds)}' must not be greater than the '{nameof(SingletonOptions.MaximumPollingIntervalInSeconds)}'.") | ||
.ValidateDataAnnotations() | ||
.ValidateOnStart(); | ||
|
||
if (options is not null) | ||
{ | ||
_services.Configure(options); | ||
} | ||
|
||
_services.AddTransient<IDistributedLockManager, DistributedLockManager>(); | ||
_services.AddTransient<IDistributedLockManagerFactory, DistributedLockManagerFactory>(); | ||
_services.AddTransient<IBlobClientProvider, BlobClientProvider>(); | ||
_services.AddTransient<ISingletonLockManager, SingletonLockManager>(); | ||
_services.AddTransient<IBlobClientFactory, BlobClientFactory>(); | ||
_services.AddTransient<QueueMessageExecutor>(); | ||
_services.AddTransient<IQueueMessageExecutor>(provider => | ||
{ | ||
var singletonManager = provider.GetRequiredService<ISingletonLockManager>(); | ||
var executor = provider.GetRequiredService<QueueMessageExecutor>(); | ||
var attribute = provider.GetRequiredService<IOptions<SingletonOptions>>(); | ||
return new SingletonQueueMessageExecutor(singletonManager, executor, attribute); | ||
}); | ||
|
||
_services.PostConfigure<ListenerOptions>(storageAccountOptions => storageAccountOptions.NewBatchThreshold = 0); | ||
|
||
return this; | ||
} | ||
} | ||
} |
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
28 changes: 28 additions & 0 deletions
28
lib/Dequeueable.AzureQueueStorage/Configurations/IDequeueableHostBuilder.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,28 @@ | ||
namespace Dequeueable.AzureQueueStorage.Configurations | ||
{ | ||
/// <summary> | ||
/// Interface to builds and setup the dequeueable host | ||
/// </summary> | ||
public interface IDequeueableHostBuilder | ||
{ | ||
/// <summary> | ||
/// This makes sure only a single instance of the function is executed at any given time (even across host instances). | ||
/// A blob lease is used behind the scenes to implement the lock./> | ||
/// </summary> | ||
/// <param name="options">Action to configure the <see cref="SingletonOptions"/></param> | ||
/// <returns><see cref="IDequeueableHostBuilder"/></returns> | ||
IDequeueableHostBuilder AsSingleton(Action<SingletonOptions>? options = null); | ||
/// <summary> | ||
/// The application will run as a job, from start to finish, and will automatically shutdown when the messages are executed. | ||
/// </summary> | ||
/// <param name="options">Action to configure the <see cref="HostOptions"/></param> | ||
/// <returns><see cref="IDequeueableHostBuilder"/></returns> | ||
IDequeueableHostBuilder RunAsJob(Action<HostOptions>? options = null); | ||
/// <summary> | ||
/// The application will run as a listener, the queue will periodically be polled for new message. | ||
/// </summary> | ||
/// <param name="options">Action to configure the <see cref="ListenerOptions"/></param> | ||
/// <returns><see cref="IDequeueableHostBuilder"/></returns> | ||
IDequeueableHostBuilder RunAsListener(Action<ListenerOptions>? options = null); | ||
} | ||
} |
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
53 changes: 53 additions & 0 deletions
53
lib/Dequeueable.AzureQueueStorage/Configurations/SingletonOptions.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,53 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace Dequeueable.AzureQueueStorage.Configurations | ||
{ | ||
/// <summary> | ||
/// SingletonOptions to configure the singleton settings of the host | ||
/// </summary> | ||
public class SingletonOptions | ||
{ | ||
internal static string Name => $"{HostOptions.Dequeueable}:Singleton"; | ||
|
||
/// <summary> | ||
/// Gets the scope indentifier of the lock. This will be the blob file name to implement the lock. | ||
/// </summary> | ||
[Required(AllowEmptyStrings = false, ErrorMessage = "{0} cannot be empty.")] | ||
public string Scope { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// The minimum polling interval to check if a new lease can be acquired. | ||
/// </summary> | ||
[Range(0, int.MaxValue, ErrorMessage = "Value for {0} must not be negative or zero.")] | ||
public int MinimumPollingIntervalInSeconds { get; set; } = 10; | ||
|
||
/// <summary> | ||
/// The maximum polling interval to check if a new lease can be acquired. | ||
/// </summary> | ||
[Range(1, int.MaxValue, ErrorMessage = "Value for {0} must not be negative or zero.")] | ||
public int MaximumPollingIntervalInSeconds { get; set; } = 120; | ||
|
||
/// <summary> | ||
/// The max retries to acquire a lease. When reached, the host will shutdown. | ||
/// </summary> | ||
[Range(0, 10, ErrorMessage = "Value for {0} must be between {1} and {2}.")] | ||
public int MaxRetries { get; set; } = 3; | ||
|
||
/// <summary> | ||
/// The name of the container used for the lock files. | ||
/// </summary> | ||
[Required(AllowEmptyStrings = false, ErrorMessage = "{0} cannot be empty.")] | ||
public string ContainerName { get; set; } = "webjobshost"; | ||
|
||
/// <summary> | ||
/// The uri format to the blob storage. Used for identity flow. Use ` {accountName}`, `{containerName}` and `{blobName}` for variable substitution. | ||
/// </summary> | ||
[Required(AllowEmptyStrings = false, ErrorMessage = "{0} cannot be empty.")] | ||
public string BlobUriFormat { get; set; } = "https://{accountName}.blob.core.windows.net/{containerName}/{blobName}"; | ||
|
||
internal static bool ValidatePollingInterval(SingletonOptions options) | ||
{ | ||
return options.MinimumPollingIntervalInSeconds < options.MaximumPollingIntervalInSeconds; | ||
} | ||
} | ||
} |
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.