CrestApps.Queues 1.10.0-preview-0023

This is a prerelease version of CrestApps.Queues.
dotnet add package CrestApps.Queues --version 1.10.0-preview-0023                
NuGet\Install-Package CrestApps.Queues -Version 1.10.0-preview-0023                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CrestApps.Queues" Version="1.10.0-preview-0023" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CrestApps.Queues --version 1.10.0-preview-0023                
#r "nuget: CrestApps.Queues, 1.10.0-preview-0023"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install CrestApps.Queues as a Cake Addin
#addin nuget:?package=CrestApps.Queues&version=1.10.0-preview-0023&prerelease

// Install CrestApps.Queues as a Cake Tool
#tool nuget:?package=CrestApps.Queues&version=1.10.0-preview-0023&prerelease                

Queues

This module offers essential services for queuing elements and processing them in the background. It proves particularly useful when there is a need to queue tasks such as notifications or emails for background processing.

Since this module focuses solely on providing core services, it is marked with the EnabledByDependencyOnly flag, making it available on demand.

To utilize this module, you can create an OrchardCore module and add a dependency on CrestApps.Queues feature. Additionally, to handle your queue items, you need to implement the IQueueElementProcessor, which is responsible for processing the queued elements.

For queuing elements, utilize the IQueueStore interface.

Notification Processor

If both the OrchardCore.Notifications feature and the CrestApps.Queues modules are activated simultaneously, a default processor for handling notifications is automatically registered.

To customize the recipient of the notification based on the provided content-item, all you need to do is implement the INotificationQueueUserProvider provider.

!! Note Please note that in the absence of an implementation for INotificationQueueUserProvider, the notifications will be disregarded and not sent.

Example of implementing an Email Queue Processor

In this example, we employ a retry logic of 5 attempts in this instance to enable the processing of the queue element before considering it abandoned.

public sealed class EmailQueueProcessor : IQueueElementProcessor
{
    /// <summary>
    /// Sets the max attempts to send the email before abandon the element.
    /// </summary>
    private const int _maxAttempts = 5;

    private readonly IEmailService _emailService;

    private IEnumerable<User> _users;

    public EmailQueueProcessor(IEmailService emailService)
    {
        _emailService = emailService;
    }

    public bool CanHandle(string queueName)
    {
        return queueName == "Email";
    }

    public Task<bool> IsProcessableAsync(QueueElement element)
    {
        return Task.FromResult(element.FailedCounter < _maxAttempts);
    }

    public async Task ProcessAsync(QueueElementProcessingContext context)
    {
        foreach (var item in context.Elements)
        {
            var message = item.As<MailMessage>();

            if(message == null)
            {
                // No message was found on the queue element.
                item.IsRemovable = true;

                continue;
            }

            var result = await _emailService.SendAsync(message);

            item.IsProcessed = result.Succeeded;
        }
    }
}

Example of creating Email Queue elements using a Content Type Handler.

In this particular scenario, we make the assumption that there exists a content type called ContactFormEntry which is completed by a site visitor. Our objective is to enqueue an email for sending it to the site owner.

public sealed class ContactFormContentType : ContentHandlerBase
{
    private const string _contentType = "ContactFormEntry";

    private readonly IQueueStore _queueStore;

    public ContactFormContentType(IQueueStore queueStore)
    {
        _queueStore = queueStore;
    }

    public override Task PublishedAsync(PublishContentContext context)
    {
        if(context.PublishingItem.ContentType != _contentType)
        {
            return Task.CompletedTask;
        }

        return AddOrUpdateNotificationQueueAsync(context.PublishingItem);
    }

    public override Task UnpublishedAsync(PublishContentContext context)
    {
        if (context.PublishingItem.ContentType != _contentType)
        {
            return Task.CompletedTask;
        }

        return RemoveNotificationQueueAsync(context.PublishingItem);
    }

    public override Task RemovedAsync(RemoveContentContext context)
    {
        if (context.ContentItem.ContentType != _contentType)
        {
            return Task.CompletedTask;
        }

        return RemoveNotificationQueueAsync(context.ContentItem);
    }

    private async Task AddOrUpdateNotificationQueueAsync(ContentItem contentItem)
    {
        var queueItems = await _queueStore.GetCorrelationAsync(contentItem.ContentItemId);

        // Get event date and add minuts to it.
        var queueItem = queueItems.FirstOrDefault(x => x.QueueName == "Email")
            ?? new QueueElement()
        {
            CorrelationId = contentItem.ContentItemId,
            QueueName = "Email",
        };

        // The Mail info will come from the contact form entry or other sources.
        var message = new MailMessage()
        {
            Subject = contentItem.Content.ContactFormEntry.Subject.Text,
            Body = contentItem.Content.ContactFormEntry.Message.Text,
            To = "owner@example.com",
        };

        queueItem.Put(message);

        await _queueStore.SaveAsync(queueItem);

        await _queueStore.SaveChangesAsync();
    }

    private async Task RemoveNotificationQueueAsync(ContentItem contentItem)
    {
        var queueItems = await _queueStore.GetCorrelationAsync(contentItem.ContentItemId);

        foreach (var queueItem in queueItems)
        {
            if (queueItem.QueueName != "Email")
            {
                continue;
            }

            await _queueStore.DeleteAsync(queueItem);
        }

        await _queueStore.SaveChangesAsync();
    }
}
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.10.0-preview-0023 500 9/9/2024
1.10.0-preview-0022 138 8/26/2024
1.10.0-preview-0021 82 8/26/2024
1.10.0-preview-0020 123 8/7/2024
1.10.0-preview-0007 114 7/22/2024
1.10.0-preview-0006 147 6/10/2024
1.10.0-preview-0005 113 6/6/2024
1.10.0-preview-0004 98 6/5/2024
1.10.0-preview-0003 217 5/7/2024
1.10.0-preview-0002 145 3/8/2024
1.10.0-preview-0001 99 3/7/2024
1.9.0 521 1/17/2024
1.1.0 122 1/17/2024
1.0.8 376 9/19/2023
1.0.7 296 8/16/2023
1.0.6 181 8/14/2023
1.0.5 192 8/4/2023
1.0.4 192 8/1/2023
1.0.3 165 8/1/2023
1.0.2 151 8/1/2023
1.0.1 232 7/12/2023
1.0.0 186 7/12/2023