Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.18.0 #99

Merged
merged 3 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

Represents the **NuGet** versions.

## v3.18.0
- *Fixed*: Removed `Azure.Identity` dependency as no longer required; related to `https://github.com/advisories/GHSA-wvxc-855f-jvrv`.
- *Fixed*: Removed `AspNetCore.HealthChecks.SqlServer` dependency as no longer required.
- *Fixed:* Updated all dependencies to latest versions.
- *Fixed*: `CoreEx.AutoMapper` updated to leverage latest major version (`13.0.1`); as such `netstandard` no longer supported.
- *Fixed*: The `TimerHostedServiceBase` was incorrectly resetting the `LastException` on sleep versus wake.
- *Fixed*: The `AddEventSender` dependency injection extension methods now correctly register as _Scoped_.
- *Fixed*: The `Logger.LogInformation` invocations refactored to `Logger.LogDebug` where applicable to reduce noise in the logs.
- *Fixed*: The `IPropertyRule.ValidateAsync` method removed as it was not required and could lead to incorrect usage.
- *Fixed:* The `ValueValidator` now only supports a `Configure` method to enable `IPropertyRule`-based configuration (versus directly).
- *Fixed:* The `CommonValidator.ValidateAsync` is now internal as this was not intended and could lead to incorrect usage.
- *Enhancement*: Added `AfterSend` event to `IEventSender` to enable post-send processing.
- *Enhancement*: Added `EventOutboxHostedService.OneOffTrigger` method to enable a _one-off_ trigger interval to be specified for the registered (DI) instance.

## v3.17.0
- *Enhancement*: Additional `CoreEx.Validation` usability improvements:
- `Validator.CreateFor<T>` added to enable the creation of a `CommonValidator<T>` instance for a specified type `T` (more purposeful name); synonym for existing `CommonValidator.Create<T>` (unchanged).
Expand Down
2 changes: 1 addition & 1 deletion Common.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>3.17.0</Version>
<Version>3.18.0</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
1 change: 0 additions & 1 deletion samples/My.Hr/My.Hr.Api/My.Hr.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.1.0" />
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions src/CoreEx.AutoMapper/CoreEx.AutoMapper.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>CoreEx.Mapping</RootNamespace>
<Product>CoreEx.AutoMapper</Product>
<Title>CoreEx .NET AutoMapper Extensions.</Title>
Expand All @@ -12,7 +12,7 @@
<Import Project="..\..\Common.targets" />

<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/CoreEx.Azure/CoreEx.Azure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<ItemGroup>
<PackageReference Include="Azure.Data.Tables" Version="12.8.3" />
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.17.4" />
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.17.5" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.19.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.17.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.2.0" />
Expand Down
8 changes: 7 additions & 1 deletion src/CoreEx.Azure/ServiceBus/ServiceBusSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public Task SendAsync(IEnumerable<EventSendData> events, CancellationToken cance

try
{
Logger.LogInformation("Sending {Count} message(s) to {Name}.", batch.Count, qn);
Logger.LogDebug("Sending {Count} message(s) to {Name}.", batch.Count, qn);
await sender.SendMessagesAsync(batch, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
Expand All @@ -139,12 +139,18 @@ public Task SendAsync(IEnumerable<EventSendData> events, CancellationToken cance
unsentEvents.RemoveAll(esd => sentIds.Contains(esd.Id ?? string.Empty));
}
}

// Raise the event.
AfterSend?.Invoke(this, EventArgs.Empty);
}, cancellationToken, nameof(SendAsync));
}

/// <summary>
/// Prepend the sent stats to the message.
/// </summary>
private static string PrependStats(string message, int totalCount, int unsentCount) => $"{unsentCount} of the total {totalCount} events were not successfully sent. {message}";

/// <inheritdoc/>
public event EventHandler? AfterSend;
}
}
4 changes: 2 additions & 2 deletions src/CoreEx.Azure/ServiceBus/ServiceBusSubscriber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public Task ReceiveAsync(ServiceBusReceivedMessage message, ServiceBusMessageAct

// Invoke the actual function logic.
Result.Go(await function(@event!, args, ct).ConfigureAwait(false))
.Then(() => Logger.LogInformation("{Type} executed successfully - Service Bus message '{Message}'.", GetType().Name, message.MessageId))
.Then(() => Logger.LogDebug("{Type} executed successfully - Service Bus message '{Message}'.", GetType().Name, message.MessageId))
.ThrowOnError();

// Perform the complete/success instrumentation.
Expand Down Expand Up @@ -234,7 +234,7 @@ public Task ReceiveAsync<TValue>(ServiceBusReceivedMessage message, ServiceBusMe

// Invoke the actual function logic.
Result.Go(await function(@event!, args, ct).ConfigureAwait(false))
.Then(() => Logger.LogInformation("{Type} executed successfully - Service Bus message '{Message}'.", GetType().Name, message.MessageId))
.Then(() => Logger.LogDebug("{Type} executed successfully - Service Bus message '{Message}'.", GetType().Name, message.MessageId))
.ThrowOnError();

// Perform the complete/success instrumentation.
Expand Down
2 changes: 1 addition & 1 deletion src/CoreEx.Cosmos/CoreEx.Cosmos.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<Import Project="..\..\Common.targets" />

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.38.1" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.39.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.10" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
<Import Project="..\..\Common.targets" />

<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="8.0.0" />
<PackageReference Include="Azure.Identity" Version="1.11.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ public async Task<int> DequeueAndSendAsync(int maxDequeueSize = 50, string? part
return 0;
}

Logger.LogInformation("{EventCount} event(s) were dequeued. [Elapsed={Elapsed}ms]", events.Count(), sw.Elapsed.TotalMilliseconds);
Logger.LogDebug("{EventCount} event(s) were dequeued. [Elapsed={Elapsed}ms]", events.Count(), sw.Elapsed.TotalMilliseconds);

// Send the events.
sw = Stopwatch.StartNew();
await EventSender.SendAsync(events.ToArray(), cancellationToken).ConfigureAwait(false);
sw.Stop();
Logger.LogInformation("{EventCount} event(s) were sent successfully. [Sender={Sender}, Elapsed={Elapsed}ms]", events.Count(), EventSender.GetType().Name, sw.Elapsed.TotalMilliseconds);
Logger.LogDebug("{EventCount} event(s) were sent successfully. [Sender={Sender}, Elapsed={Elapsed}ms]", events.Count(), EventSender.GetType().Name, sw.Elapsed.TotalMilliseconds);

// Commit the transaction.
txn.Complete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public abstract class EventOutboxEnqueueBase(IDatabase database, ILogger<EventOu
public string DefaultDestination { get; set; } = "$default";

/// <summary>
/// Sets the optional <see cref="IEventSender"/> to act as the primary <see cref="IEventSender"/> where <i>outbox enqueue</i> is to provide backup/audit capabilities.
/// Sets the <see cref="IEventSender"/> to act as the primary <see cref="IEventSender"/> where <i>outbox enqueue</i> is to provide backup/audit capabilities.
/// </summary>
public void SetPrimaryEventSender(IEventSender eventSender)
{
Expand Down Expand Up @@ -125,6 +125,8 @@ await Database.StoredProcedure(EnqueueStoredProcedure)
sw.Stop();
Logger.LogDebug("{EventCount} event(s) were enqueued; {SuccessCount} as sent, {ErrorCount} to be sent. [Sender={Sender}, Elapsed={Elapsed}ms]",
events.Count(), events.Count() - unsentEvents.Count, unsentEvents.Count, GetType().Name, sw.Elapsed.TotalMilliseconds);

AfterSend?.Invoke(this, EventArgs.Empty);
}

/// <summary>
Expand Down Expand Up @@ -163,5 +165,8 @@ private TableValuedParameter CreateTableValuedParameter(IEnumerable<EventSendDat

return tvp;
}

/// <inheritdoc/>
public event EventHandler? AfterSend;
}
}
18 changes: 18 additions & 0 deletions src/CoreEx.Database.SqlServer/Outbox/EventOutboxHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using CoreEx.Hosting.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -24,6 +26,22 @@ public class EventOutboxHostedService : SynchronizedTimerHostedServiceBase<Event
private int? _maxDequeueSize;
private string? _name;

/// <summary>
/// Provides an opportunity to make a one-off change to the underlying timer to trigger using the specified <paramref name="oneOffInterval"/> to the registered <see cref="EventOutboxHostedService"/>.
/// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> used to get the registered <see cref="EventOutboxHostedService"/>.</param>
/// <param name="oneOffInterval">The one-off interval before triggering; defaults to <c>null</c> which represents an immediate trigger.</param>
/// <param name="leaveWhereTimeRemainingIsLess">Indicates whether to <i>not</i> adjust the time where the time remaining is less than the one-off interval specified.</param>
/// <remarks>Where there is more than one instance registered, or none, then no action will be taken.
/// <para>This functionality is intended for low volume event publishing where there is need to bring forward the configured interval for a one-off execution. This is particularly useful where there is a need to publish
/// an event immediately versus waiting for the next scheduled execution.</para></remarks>
public static void OneOffTrigger(IServiceProvider serviceProvider, TimeSpan? oneOffInterval = null, bool leaveWhereTimeRemainingIsLess = true)
{
var services = serviceProvider.ThrowIfNull(nameof(serviceProvider)).GetServices<IHostedService>().OfType<EventOutboxHostedService>();
if (services.Count() == 1)
services.First().OneOffTrigger(oneOffInterval, leaveWhereTimeRemainingIsLess);
}

/// <summary>
/// Get or sets the configuration name for <see cref="Interval"/>. Defaults to '<c>Interval</c>'.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
<Import Project="..\..\Common.targets" />

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.28" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.29" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.18" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/CoreEx.Solace/CoreEx.Solace.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="SolaceSystems.Solclient.Messaging" Version="10.23.0" />
<PackageReference Include="SolaceSystems.Solclient.Messaging" Version="10.24.0" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 8 additions & 2 deletions src/CoreEx.Solace/PubSub/PubSubSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public Task SendAsync(IEnumerable<EventSendData> events, CancellationToken cance

try
{
Logger.LogInformation("Sending {Count} message(s) to PubSub Broker.", messageBatch.Count);
Logger.LogDebug("Sending {Count} message(s) to PubSub Broker.", messageBatch.Count);
var returnCode = session.Send([.. messageBatch], 0, messageBatch.Count, out int sentCount);

if (returnCode != ReturnCode.SOLCLIENT_OK)
Expand All @@ -174,7 +174,7 @@ public Task SendAsync(IEnumerable<EventSendData> events, CancellationToken cance
throw new InvalidOperationException("Not all messages in batch were sent; only {sentCount} of {messageBatch.Count} were sent.");
}

Logger.LogInformation("Successful send of {Count} message(s).", messageBatch.Count);
Logger.LogDebug("Successful send of {Count} message(s).", messageBatch.Count);
}
catch (Exception ex)
{
Expand All @@ -186,6 +186,9 @@ public Task SendAsync(IEnumerable<EventSendData> events, CancellationToken cance
unsentEvents.RemoveAll(esd => sentIds.Contains(esd.Id ?? string.Empty));
}
}

// Raise the event.
AfterSend?.Invoke(this, EventArgs.Empty);
}, nameof(SendAsync));

return Task.CompletedTask;
Expand All @@ -211,5 +214,8 @@ private ISession EstablishSessionToPubSubBroker()
/// Prepend the sent stats to the message.
/// </summary>
private static string PrependStats(string message, int totalCount, int unsentCount) => $"{unsentCount} of the total {totalCount} events were not successfully sent. {message}";

/// <inheritdoc/>
public event EventHandler? AfterSend;
}
}
Loading
Loading