diff --git a/TickerQ.slnx b/TickerQ.slnx index 41a7a5ce..2441a03b 100644 --- a/TickerQ.slnx +++ b/TickerQ.slnx @@ -37,6 +37,7 @@ + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index a3526b7a..c94f1d35 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,7 @@ net10.0 - 10.2.5 + 10.2.5-beta [10.0.0,11.0.0) [10.0.0,11.0.0) https://github.com/arcenox-co/TickerQ diff --git a/src/TickerQ.Caching.StackExchangeRedis/Infrastructure/TickerRedisPersistenceProvider.cs b/src/TickerQ.Caching.StackExchangeRedis/Infrastructure/TickerRedisPersistenceProvider.cs index f713b1a5..4604ed28 100644 --- a/src/TickerQ.Caching.StackExchangeRedis/Infrastructure/TickerRedisPersistenceProvider.cs +++ b/src/TickerQ.Caching.StackExchangeRedis/Infrastructure/TickerRedisPersistenceProvider.cs @@ -1,10 +1,5 @@ #nullable disable -using System; -using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Extensions.Logging; using StackExchange.Redis; using static TickerQ.Caching.StackExchangeRedis.DependencyInjection.ServiceExtension; @@ -32,6 +27,38 @@ public TickerRedisPersistenceProvider( ILogger> logger) : base(db, clock, optionsBuilder, redisOptions, logger) { } + #region Queryable_Methods + public ITickerQueryable TimeTickersQuery() + { + return new InMemoryTickerQueryable(async ct => + { + var list = await Serializer.LoadAllFromSetAsync( + TimeTickerIdsKey, TimeTickerKey, ct).ConfigureAwait(false); + return list; + }); + } + + public ITickerQueryable CronTickersQuery() + { + return new InMemoryTickerQueryable(async ct => + { + var list = await Serializer.LoadAllFromSetAsync( + CronIdsKey, CronKey, ct).ConfigureAwait(false); + return list; + }); + } + + public ITickerQueryable> CronTickerOccurrencesQuery() + { + return new InMemoryTickerQueryable>(async ct => + { + var list = await Serializer.LoadAllFromSetAsync>( + CronOccurrenceIdsKey, CronOccurrenceKey, ct).ConfigureAwait(false); + return list; + }); + } + #endregion + #region Time_Ticker_Shared_Methods public async Task GetTimeTickerById(Guid id, CancellationToken cancellationToken = default) { diff --git a/src/TickerQ.Dashboard/Endpoints/DashboardEndpoints.cs b/src/TickerQ.Dashboard/Endpoints/DashboardEndpoints.cs index 9678e560..5cae730f 100644 --- a/src/TickerQ.Dashboard/Endpoints/DashboardEndpoints.cs +++ b/src/TickerQ.Dashboard/Endpoints/DashboardEndpoints.cs @@ -5,6 +5,7 @@ using System.Text.Json; using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; @@ -268,10 +269,11 @@ private static async Task ValidateAuth(HttpContext context) if (dashboardOptions.Auth.Mode == AuthMode.Host) { - return Results.Challenge(); + await context.ChallengeAsync(); + return; } - return Results.Unauthorized(); + context.Response.StatusCode = 401; } diff --git a/src/TickerQ.EntityFrameworkCore/TickerQ.EntityFrameworkCore.csproj b/src/TickerQ.EntityFrameworkCore/TickerQ.EntityFrameworkCore.csproj index 196751f6..5931ac1e 100644 --- a/src/TickerQ.EntityFrameworkCore/TickerQ.EntityFrameworkCore.csproj +++ b/src/TickerQ.EntityFrameworkCore/TickerQ.EntityFrameworkCore.csproj @@ -16,5 +16,4 @@ - \ No newline at end of file diff --git a/src/TickerQ.Instrumentation.OpenTelemetry/TickerQ.Instrumentation.OpenTelemetry.csproj b/src/TickerQ.Instrumentation.OpenTelemetry/TickerQ.Instrumentation.OpenTelemetry.csproj index 72092580..ff3a6e76 100644 --- a/src/TickerQ.Instrumentation.OpenTelemetry/TickerQ.Instrumentation.OpenTelemetry.csproj +++ b/src/TickerQ.Instrumentation.OpenTelemetry/TickerQ.Instrumentation.OpenTelemetry.csproj @@ -18,5 +18,4 @@ - diff --git a/src/TickerQ.SourceGenerator/TickerQ.SourceGenerator.csproj b/src/TickerQ.SourceGenerator/TickerQ.SourceGenerator.csproj index 97ff41cf..000dafdf 100644 --- a/src/TickerQ.SourceGenerator/TickerQ.SourceGenerator.csproj +++ b/src/TickerQ.SourceGenerator/TickerQ.SourceGenerator.csproj @@ -15,5 +15,4 @@ - diff --git a/tests/TickerQ.Tests/JsonExampleGeneratorTests.cs b/tests/TickerQ.Tests/JsonExampleGeneratorTests.cs index c56cb05a..ece8a110 100644 --- a/tests/TickerQ.Tests/JsonExampleGeneratorTests.cs +++ b/tests/TickerQ.Tests/JsonExampleGeneratorTests.cs @@ -8,6 +8,11 @@ namespace TickerQ.Tests; public class JsonExampleGeneratorTests { + private static readonly JsonSerializerOptions DeserializeOptions = new() + { + PropertyNameCaseInsensitive = true + }; + public JsonExampleGeneratorTests() { TickerHelper.RequestJsonSerializerOptions = new JsonSerializerOptions @@ -70,7 +75,7 @@ public void TryGenerateExampleJson_WithDecimal_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); var value = JsonSerializer.Deserialize(json); - Assert.Equal(decimal.Zero, value); + Assert.Equal(123.45m, value); } [Fact] @@ -81,7 +86,7 @@ public void TryGenerateExampleJson_WithDateTime_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); var value = JsonSerializer.Deserialize(json); - Assert.Equal(DateTime.MinValue, value); + Assert.Equal(new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc), value); } [Fact] @@ -125,7 +130,7 @@ public void TryGenerateExampleJson_WithByte_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); var value = JsonSerializer.Deserialize(json); - Assert.Equal((byte)1, value); + Assert.Equal((byte)123, value); } [Fact] @@ -136,7 +141,7 @@ public void TryGenerateExampleJson_WithShort_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); var value = JsonSerializer.Deserialize(json); - Assert.Equal((short)1, value); + Assert.Equal((short)123, value); } [Fact] @@ -191,7 +196,7 @@ public void TryGenerateExampleJson_WithNullableDateTime_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); var value = JsonSerializer.Deserialize(json); - Assert.Equal(DateTime.MinValue, value); + Assert.Equal(new DateTime(2023, 1, 1, 0, 0, 0, DateTimeKind.Utc), value); } [Fact] @@ -266,7 +271,7 @@ public void TryGenerateExampleJson_WithSimpleClass_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); Assert.Equal(123, value!.Id); Assert.Equal("string", value.Name); @@ -280,7 +285,7 @@ public void TryGenerateExampleJson_WithNestedClass_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); Assert.Equal(123, value!.Id); Assert.NotNull(value.Child); @@ -295,7 +300,7 @@ public void TryGenerateExampleJson_WithClassContainingList_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); Assert.NotNull(value!.Items); Assert.Single(value.Items); @@ -309,7 +314,7 @@ public void TryGenerateExampleJson_WithClassContainingArray_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); Assert.NotNull(value!.Numbers); Assert.Single(value.Numbers); @@ -323,7 +328,7 @@ public void TryGenerateExampleJson_WithStruct_ReturnsValidJson() Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.Equal(123, value.X); Assert.Equal(123, value.Y); } @@ -335,28 +340,27 @@ public void TryGenerateExampleJson_WithReadOnlyProperty_OnlyGeneratesWritablePro Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); Assert.Equal(123, value!.WritableProperty); } [Fact] - public void TryGenerateExampleJson_WithTypeWithoutParameterlessConstructor_ReturnsFalse() + public void TryGenerateExampleJson_WithTypeWithoutParameterlessConstructor_ReturnsValidJson() { var result = JsonExampleGenerator.TryGenerateExampleJson(typeof(ClassWithoutParameterlessConstructor), out var json); - Assert.False(result); - Assert.True(string.IsNullOrEmpty(json)); + Assert.True(result); + Assert.False(string.IsNullOrEmpty(json)); } [Fact] - public void TryGenerateExampleJson_ReturnsIndentedJson() + public void TryGenerateExampleJson_ReturnsCompactJson() { var result = JsonExampleGenerator.TryGenerateExampleJson(typeof(SimpleTestClass), out var json); Assert.True(result); - Assert.Contains("\n", json); - Assert.Contains(" ", json); + Assert.DoesNotContain("\n", json); } [Fact] @@ -365,10 +369,9 @@ public void TryGenerateExampleJson_WithClassHierarchy_ReturnsValidJson() var result = JsonExampleGenerator.TryGenerateExampleJson(typeof(ClassWithHierarchy), out var json); Assert.True(result); Assert.False(string.IsNullOrEmpty(json)); - var value = JsonSerializer.Deserialize(json); + var value = JsonSerializer.Deserialize(json, DeserializeOptions); Assert.NotNull(value); - Assert.NotNull(value!.Child); - Assert.Null(value.Child!.Child); // Ensure it doesn't go infinitely deep + Assert.Null(value.Child); // Circular reference detection returns null for self-referencing types } public class SimpleTestClass