From 1417f6f8848e91be000e5db22ae7be9ebc16ae5f Mon Sep 17 00:00:00 2001 From: RafaelJCamara Date: Sun, 22 Mar 2026 11:20:20 +0100 Subject: [PATCH] Adjust WebAPI sample with dashboard integration. --- .../20260322095429_DbContextSync.Designer.cs | 234 ++++++++++++++++++ .../20260322095429_DbContextSync.cs | 31 +++ .../TickerQDbContextModelSnapshot.cs | 5 + samples/TickerQ.Sample.WebApi/Program.cs | 3 +- .../Properties/launchSettings.json | 12 + samples/TickerQ.Sample.WebApi/README.md | 15 ++ .../TickerQ.Sample.WebApi.csproj | 10 +- 7 files changed, 304 insertions(+), 6 deletions(-) create mode 100644 samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.Designer.cs create mode 100644 samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.cs create mode 100644 samples/TickerQ.Sample.WebApi/Properties/launchSettings.json create mode 100644 samples/TickerQ.Sample.WebApi/README.md diff --git a/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.Designer.cs b/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.Designer.cs new file mode 100644 index 00000000..db13c097 --- /dev/null +++ b/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.Designer.cs @@ -0,0 +1,234 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TickerQ.EntityFrameworkCore.DbContextFactory; + +#nullable disable + +namespace TickerQ.Sample.WebApi.Migrations +{ + [DbContext(typeof(TickerQDbContext))] + [Migration("20260322095429_DbContextSync")] + partial class DbContextSync + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.0"); + + modelBuilder.Entity("TickerQ.Utilities.Entities.CronTickerEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Expression") + .HasColumnType("TEXT"); + + b.Property("Function") + .HasColumnType("TEXT"); + + b.Property("InitIdentifier") + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("1"); + + b.Property("Request") + .HasColumnType("BLOB"); + + b.Property("Retries") + .HasColumnType("INTEGER"); + + b.PrimitiveCollection("RetryIntervals") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Expression") + .HasDatabaseName("IX_CronTickers_Expression"); + + b.HasIndex("Function", "Expression") + .HasDatabaseName("IX_Function_Expression"); + + b.ToTable("CronTickers", "ticker"); + }); + + modelBuilder.Entity("TickerQ.Utilities.Entities.CronTickerOccurrenceEntity", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CronTickerId") + .HasColumnType("TEXT"); + + b.Property("ElapsedTime") + .HasColumnType("INTEGER"); + + b.Property("ExceptionMessage") + .HasColumnType("TEXT"); + + b.Property("ExecutedAt") + .HasColumnType("TEXT"); + + b.Property("ExecutionTime") + .HasColumnType("TEXT"); + + b.Property("LockHolder") + .HasColumnType("TEXT"); + + b.Property("LockedAt") + .HasColumnType("TEXT"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("SkippedReason") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CronTickerId") + .HasDatabaseName("IX_CronTickerOccurrence_CronTickerId"); + + b.HasIndex("ExecutionTime") + .HasDatabaseName("IX_CronTickerOccurrence_ExecutionTime"); + + b.HasIndex("CronTickerId", "ExecutionTime") + .IsUnique() + .HasDatabaseName("UQ_CronTickerId_ExecutionTime"); + + b.HasIndex("Status", "ExecutionTime") + .HasDatabaseName("IX_CronTickerOccurrence_Status_ExecutionTime"); + + b.ToTable("CronTickerOccurrences", "ticker"); + }); + + modelBuilder.Entity("TickerQ.Utilities.Entities.TimeTickerEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ElapsedTime") + .HasColumnType("INTEGER"); + + b.Property("ExceptionMessage") + .HasColumnType("TEXT"); + + b.Property("ExecutedAt") + .HasColumnType("TEXT"); + + b.Property("ExecutionTime") + .HasColumnType("TEXT"); + + b.Property("Function") + .HasColumnType("TEXT"); + + b.Property("InitIdentifier") + .HasColumnType("TEXT"); + + b.Property("LockHolder") + .HasColumnType("TEXT"); + + b.Property("LockedAt") + .HasColumnType("TEXT"); + + b.Property("ParentId") + .HasColumnType("TEXT"); + + b.Property("Request") + .HasColumnType("BLOB"); + + b.Property("Retries") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.PrimitiveCollection("RetryIntervals") + .HasColumnType("TEXT"); + + b.Property("RunCondition") + .HasColumnType("INTEGER"); + + b.Property("SkippedReason") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ExecutionTime") + .HasDatabaseName("IX_TimeTicker_ExecutionTime"); + + b.HasIndex("ParentId"); + + b.HasIndex("Status", "ExecutionTime") + .HasDatabaseName("IX_TimeTicker_Status_ExecutionTime"); + + b.ToTable("TimeTickers", "ticker"); + }); + + modelBuilder.Entity("TickerQ.Utilities.Entities.CronTickerOccurrenceEntity", b => + { + b.HasOne("TickerQ.Utilities.Entities.CronTickerEntity", "CronTicker") + .WithMany() + .HasForeignKey("CronTickerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CronTicker"); + }); + + modelBuilder.Entity("TickerQ.Utilities.Entities.TimeTickerEntity", b => + { + b.HasOne("TickerQ.Utilities.Entities.TimeTickerEntity", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("TickerQ.Utilities.Entities.TimeTickerEntity", b => + { + b.Navigation("Children"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.cs b/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.cs new file mode 100644 index 00000000..c1e017aa --- /dev/null +++ b/samples/TickerQ.Sample.WebApi/Migrations/20260322095429_DbContextSync.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TickerQ.Sample.WebApi.Migrations +{ + /// + public partial class DbContextSync : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsEnabled", + schema: "ticker", + table: "CronTickers", + type: "INTEGER", + nullable: false, + defaultValueSql: "1"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsEnabled", + schema: "ticker", + table: "CronTickers"); + } + } +} diff --git a/samples/TickerQ.Sample.WebApi/Migrations/TickerQDbContextModelSnapshot.cs b/samples/TickerQ.Sample.WebApi/Migrations/TickerQDbContextModelSnapshot.cs index 81c3d049..83d4782d 100644 --- a/samples/TickerQ.Sample.WebApi/Migrations/TickerQDbContextModelSnapshot.cs +++ b/samples/TickerQ.Sample.WebApi/Migrations/TickerQDbContextModelSnapshot.cs @@ -37,6 +37,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("InitIdentifier") .HasColumnType("TEXT"); + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("1"); + b.Property("Request") .HasColumnType("BLOB"); diff --git a/samples/TickerQ.Sample.WebApi/Program.cs b/samples/TickerQ.Sample.WebApi/Program.cs index 44c56e5f..3a0c25a5 100644 --- a/samples/TickerQ.Sample.WebApi/Program.cs +++ b/samples/TickerQ.Sample.WebApi/Program.cs @@ -1,5 +1,5 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; +using TickerQ.Dashboard.DependencyInjection; using TickerQ.DependencyInjection; using TickerQ.EntityFrameworkCore.DbContextFactory; using TickerQ.EntityFrameworkCore.DependencyInjection; @@ -21,6 +21,7 @@ b => b.MigrationsAssembly("TickerQ.Sample.WebApi")); }); }); + options.AddDashboard(); }); var app = builder.Build(); diff --git a/samples/TickerQ.Sample.WebApi/Properties/launchSettings.json b/samples/TickerQ.Sample.WebApi/Properties/launchSettings.json new file mode 100644 index 00000000..34f07458 --- /dev/null +++ b/samples/TickerQ.Sample.WebApi/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "TickerQ.Sample.WebApi": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:55325;http://localhost:55329" + } + } +} \ No newline at end of file diff --git a/samples/TickerQ.Sample.WebApi/README.md b/samples/TickerQ.Sample.WebApi/README.md new file mode 100644 index 00000000..377e33e6 --- /dev/null +++ b/samples/TickerQ.Sample.WebApi/README.md @@ -0,0 +1,15 @@ +### To have in consideration if something goes wrong with this sample project + +- One of the errors that you might have is that the dashboard path gives you a 404. In this case, make that you firsst build the dashboard project. + +Fixing instructions: +1. Make sure your terminal is located in the dashboard `wwwroot` path. +2. `npm install` +3. `npm run build` + + +- Another problem that you might have is related to EF migrations missing/out of date. +Fixing instructions: +1. Make sure your terminal is located in the dashboard `.WebApi` path. +2. `dotnet ef migrations add `. This makes sure that you have the latest version. +3. `dotnet ef database update`. This makes sure that the latest migration you've added is applied. \ No newline at end of file diff --git a/samples/TickerQ.Sample.WebApi/TickerQ.Sample.WebApi.csproj b/samples/TickerQ.Sample.WebApi/TickerQ.Sample.WebApi.csproj index 8ac40942..8b46b4f3 100644 --- a/samples/TickerQ.Sample.WebApi/TickerQ.Sample.WebApi.csproj +++ b/samples/TickerQ.Sample.WebApi/TickerQ.Sample.WebApi.csproj @@ -1,19 +1,19 @@ + net10.0 enable enable - - + + - + +