Skip to content
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
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PackageIcon>icon.jpg</PackageIcon>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>10.0.2</Version>
<DotNetVersion>[10.0.0,11.0.0)</DotNetVersion>
<LangVersion>latest</LangVersion>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -9,10 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="[10.0.0,11.0.0)" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="$(DotNetVersion)" />
<PackageReference Include="TickerQ.Utilities" Version="$(Version)" />
</ItemGroup>
</Project>
38 changes: 38 additions & 0 deletions src/TickerQ.Dashboard/DependencyInjection/AspNetCoreExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Builder;

Check failure on line 1 in src/TickerQ.Dashboard/DependencyInjection/AspNetCoreExtensions.cs

View workflow job for this annotation

GitHub Actions / PR Build and Test

The type or namespace name 'AspNetCore' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
using TickerQ.Utilities.Enums;
using System;
using Microsoft.Extensions.DependencyInjection;
using TickerQ.DependencyInjection;

Check failure on line 5 in src/TickerQ.Dashboard/DependencyInjection/AspNetCoreExtensions.cs

View workflow job for this annotation

GitHub Actions / PR Build and Test

The type or namespace name 'DependencyInjection' does not exist in the namespace 'TickerQ' (are you missing an assembly reference?)
using TickerQ.Utilities;

namespace TickerQ.Dashboard.DependencyInjection
{
/// <summary>
/// ASP.NET Core specific extensions for TickerQ with Dashboard support
/// </summary>
public static class AspNetCoreExtensions
{
/// <summary>
/// Initializes TickerQ for ASP.NET Core applications with Dashboard support
/// </summary>
public static IApplicationBuilder UseTickerQ(this IApplicationBuilder app, TickerQStartMode qStartMode = TickerQStartMode.Immediate)
{
var serviceProvider = app.ApplicationServices;

// Initialize core TickerQ functionality using the base extension from TickerQ package
serviceProvider.UseTickerQ(qStartMode);

// Handle Dashboard-specific initialization if configured
var tickerExecutionContext = serviceProvider.GetService<TickerExecutionContext>();
if (tickerExecutionContext?.DashboardApplicationAction != null)
{
// Cast object back to IApplicationBuilder for Dashboard middleware
tickerExecutionContext.DashboardApplicationAction(app);
tickerExecutionContext.DashboardApplicationAction = null;
}

return app;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<ItemGroup>
<PackageReference Include="FlexLabs.EntityFrameworkCore.Upsert" Version="[10.0.0-beta1,11.0.0)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[10.0.0,11.0.0)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="$(DotNetVersion)" />
<PackageReference Include="TickerQ.Utilities" Version="$(Version)" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<ItemGroup>
<PackageReference Include="OpenTelemetry" Version="[1.7.0,)" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="[1.7.0,)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[10.0.0,11.0.0)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[10.0.0,11.0.0)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(DotNetVersion)" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/TickerQ.Utilities/TickerExecutionContext.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using TickerQ.Utilities.Enums;
using TickerQ.Utilities.Models;

Expand All @@ -18,7 +18,7 @@ internal class TickerExecutionContext
{
private long _nextOccurrenceTicks;
internal Action<IServiceProvider> ExternalProviderApplicationAction { get; set; }
internal Action<IApplicationBuilder> DashboardApplicationAction { get; set; }
internal Action<object> DashboardApplicationAction { get; set; }
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DashboardApplicationAction property type has been changed from Action to Action. This weakens type safety. When this action is invoked in AspNetCoreExtensions.cs, it requires an unsafe cast from object back to IApplicationBuilder. Consider using a more type-safe approach such as defining an abstraction interface or using generics.

Copilot uses AI. Check for mistakes.
public Action<object, CoreNotifyActionType> NotifyCoreAction { get; set; }
public string LastHostExceptionMessage { get; set; }
internal ITickerOptionsSeeding OptionsSeeding { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions src/TickerQ.Utilities/TickerOptionsBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TickerQ.Utilities.Entities;
using TickerQ.Utilities.Interfaces;
using TickerQ.Utilities.Interfaces.Managers;
Expand Down Expand Up @@ -171,7 +171,7 @@ public TickerOptionsBuilder<TTimeTicker, TCronTicker> SetExceptionHandler<THandl
internal void UseExternalProviderApplication(Action<IServiceProvider> action)
=> _tickerExecutionContext.ExternalProviderApplicationAction = action;

internal void UseDashboardApplication(Action<IApplicationBuilder> action)
internal void UseDashboardApplication(Action<object> action)
=> _tickerExecutionContext.DashboardApplicationAction = action;
Comment on lines +174 to 175
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DashboardApplicationAction type has been changed from Action to Action. While this makes the code more flexible, it introduces type safety issues. The consumer code in AspNetCoreExtensions.cs (line 30) casts the object back to IApplicationBuilder without any type checking. Consider using a generic type parameter or a proper abstraction interface instead of object to maintain type safety while still being framework-agnostic.

Suggested change
internal void UseDashboardApplication(Action<object> action)
=> _tickerExecutionContext.DashboardApplicationAction = action;
internal void UseDashboardApplication<TDashboardBuilder>(Action<TDashboardBuilder> action)
where TDashboardBuilder : class
{
if (action == null) throw new ArgumentNullException(nameof(action));
_tickerExecutionContext.DashboardApplicationAction = builderObj =>
{
if (builderObj is TDashboardBuilder typedBuilder)
{
action(typedBuilder);
}
else
{
throw new InvalidOperationException(
$"Dashboard application builder type mismatch. " +
$"Expected '{typeof(TDashboardBuilder).FullName}', " +
$"but received '{builderObj?.GetType().FullName ?? "null"}'.");
}
};
}

Copilot uses AI. Check for mistakes.
}

Expand Down
11 changes: 6 additions & 5 deletions src/TickerQ.Utilities/TickerQ.Utilities.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
</ItemGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="NCrontab" Version="[3.3.0,)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(DotNetVersion)" />
<PackageReference Include="NCrontab" Version="[3.3.0,)" />
</ItemGroup>

</Project>
32 changes: 22 additions & 10 deletions src/TickerQ/DependencyInjection/TickerQServiceExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TickerQ.BackgroundServices;
using TickerQ.Dispatcher;
using TickerQ.Provider;
Expand Down Expand Up @@ -90,9 +90,26 @@ public static IServiceCollection AddTickerQ<TTimeTicker, TCronTicker>(this IServ
return services;
}

public static IApplicationBuilder UseTickerQ(this IApplicationBuilder app, TickerQStartMode qStartMode = TickerQStartMode.Immediate)
/// <summary>
/// Initializes TickerQ for generic host applications (Console, MAUI, WPF, Worker Services, etc.)
/// </summary>
public static IHost UseTickerQ(this IHost host, TickerQStartMode qStartMode = TickerQStartMode.Immediate)
{
InitializeTickerQ(host.Services, qStartMode);
return host;
}

/// <summary>
/// Initializes TickerQ with a service provider directly
/// </summary>
public static IServiceProvider UseTickerQ(this IServiceProvider serviceProvider, TickerQStartMode qStartMode = TickerQStartMode.Immediate)
{
InitializeTickerQ(serviceProvider, qStartMode);
return serviceProvider;
}

private static void InitializeTickerQ(IServiceProvider serviceProvider, TickerQStartMode qStartMode)
{
var serviceProvider = app.ApplicationServices;
var tickerExecutionContext = serviceProvider.GetService<TickerExecutionContext>();
var configuration = serviceProvider.GetService<IConfiguration>();
var notificationHubSender = serviceProvider.GetService<ITickerQNotificationHubSender>();
Expand Down Expand Up @@ -149,13 +166,8 @@ public static IApplicationBuilder UseTickerQ(this IApplicationBuilder app, Ticke
tickerExecutionContext.ExternalProviderApplicationAction = null;
}

if (tickerExecutionContext?.DashboardApplicationAction != null)
{
tickerExecutionContext.DashboardApplicationAction(app);
tickerExecutionContext.DashboardApplicationAction = null;
}

return app;
// Dashboard integration is handled by TickerQ.Dashboard package via DashboardApplicationAction
// It will be invoked when UseTickerQ is called from ASP.NET Core specific extension
}

private static async Task SeedDefinedCronTickers(IServiceProvider serviceProvider)
Expand Down
1 change: 1 addition & 0 deletions src/TickerQ/TickerQ.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

<ItemGroup>
<PackageReference Include="TickerQ.Utilities" Version="$(Version)" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(DotNetVersion)" />
</ItemGroup>

<Target Name="CopyAnalyzer" AfterTargets="Build">
Expand Down
1 change: 1 addition & 0 deletions tests/TickerQ.Tests/TickerQ.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="FluentAssertions" Version="8.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="NSubstitute" Version="5.3.0" />
<PackageReference Include="xunit" Version="2.9.3" />
Expand Down
Loading