feat: Enhance software platform retrieval with includeUnused parameter and caching improvements

This commit is contained in:
2026-06-12 22:12:03 +01:00
parent 38145319ea
commit 4b3a8f630a
7 changed files with 59 additions and 27 deletions

View File

@@ -2,7 +2,11 @@
"permissions": {
"allow": [
"Bash(dotnet build *)",
"Bash(grep -E \"\\\\.\\(cs|xaml|razor|ts|tsx|jsx|js\\)$\")"
"Bash(grep -E \"\\\\.\\(cs|xaml|razor|ts|tsx|jsx|js\\)$\")",
"Bash(awk '/modelBuilder.Entity<SoftwareRelease>/,/^ \\\\}\\\\\\);/' /home/claunia/Development/marechai/Marechai.Database/Models/MarechaiContext.cs)",
"Bash(kiota generate *)",
"Bash(grep -A 50 '\"/software/platforms\"' /tmp/openapi.json | grep -A 20 '\"parameters\"')",
"Read(//tmp/**)"
]
}
}

View File

@@ -48,7 +48,7 @@ namespace Marechai.ApiClient.Software.Platforms
/// </summary>
/// <param name="pathParameters">Path parameters for the request</param>
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
public PlatformsRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/software/platforms", pathParameters)
public PlatformsRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/software/platforms{?includeUnused*}", pathParameters)
{
}
/// <summary>
@@ -56,7 +56,7 @@ namespace Marechai.ApiClient.Software.Platforms
/// </summary>
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
public PlatformsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/software/platforms", rawUrl)
public PlatformsRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/software/platforms{?includeUnused*}", rawUrl)
{
}
/// <returns>A List&lt;global::Marechai.ApiClient.Models.SoftwarePlatformDto&gt;</returns>
@@ -65,11 +65,11 @@ namespace Marechai.ApiClient.Software.Platforms
/// <exception cref="global::Marechai.ApiClient.Models.ProblemDetails">When receiving a 400 status code</exception>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
public async Task<List<global::Marechai.ApiClient.Models.SoftwarePlatformDto>?> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
public async Task<List<global::Marechai.ApiClient.Models.SoftwarePlatformDto>?> GetAsync(Action<RequestConfiguration<global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder.PlatformsRequestBuilderGetQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
{
#nullable restore
#else
public async Task<List<global::Marechai.ApiClient.Models.SoftwarePlatformDto>> GetAsync(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
public async Task<List<global::Marechai.ApiClient.Models.SoftwarePlatformDto>> GetAsync(Action<RequestConfiguration<global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder.PlatformsRequestBuilderGetQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
{
#endif
var requestInfo = ToGetRequestInformation(requestConfiguration);
@@ -108,11 +108,11 @@ namespace Marechai.ApiClient.Software.Platforms
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder.PlatformsRequestBuilderGetQueryParameters>>? requestConfiguration = default)
{
#nullable restore
#else
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
public RequestInformation ToGetRequestInformation(Action<RequestConfiguration<global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder.PlatformsRequestBuilderGetQueryParameters>> requestConfiguration = default)
{
#endif
var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
@@ -148,12 +148,20 @@ namespace Marechai.ApiClient.Software.Platforms
{
return new global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder(rawUrl, RequestAdapter);
}
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
#pragma warning disable CS1591
public partial class PlatformsRequestBuilderGetQueryParameters
#pragma warning restore CS1591
{
[QueryParameter("includeUnused")]
public bool? IncludeUnused { get; set; }
}
/// <summary>
/// Configuration for the request such as headers, query parameters, and middleware options.
/// </summary>
[Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
public partial class PlatformsRequestBuilderGetRequestConfiguration : RequestConfiguration<DefaultQueryParameters>
public partial class PlatformsRequestBuilderGetRequestConfiguration : RequestConfiguration<global::Marechai.ApiClient.Software.Platforms.PlatformsRequestBuilder.PlatformsRequestBuilderGetQueryParameters>
{
}
/// <summary>

View File

@@ -1,6 +1,6 @@
{
"descriptionHash": "455E51D4863B8C11F675552B6A5F7C622A7D015227812EBE046AFFC874B887574D31E89D03E429C6E52860415A01265FBA1C9923AAA507208B9806C5927C683C",
"descriptionLocation": "../openapi.yaml",
"descriptionHash": "A5DC922A77CBAB9AF21234BFCD822D499C339E346E1FB6378A53F47B5BBC53C2BEC270B3BE84DB0D0619BFE48C50C2893D80AC29639867C8D8DF795585CEBE2A",
"descriptionLocation": "../../../../../tmp/openapi.json",
"lockFileVersion": "1.0.0",
"kiotaVersion": "1.31.1",
"clientClassName": "Client",

View File

@@ -416,9 +416,12 @@ public class SoftwareBrowsingService
{
try
{
_logger.LogInformation("Fetching all software platforms from API");
_logger.LogInformation("Fetching software platforms with software from API");
List<SoftwarePlatformDto> platforms = await _apiClient.Software.Platforms.GetAsync();
List<SoftwarePlatformDto> platforms = await _apiClient.Software.Platforms.GetAsync(config =>
{
config.QueryParameters.IncludeUnused = false;
});
if(platforms == null) return [];

View File

@@ -33,6 +33,7 @@ using Marechai.Database.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OutputCaching;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
@@ -44,26 +45,35 @@ public class SoftwarePlatformsController(MarechaiContext context, IMemoryCache c
{
// Software platforms barely change — cache the full list briefly so the
// /software landing page doesn't re-hit the DB on every load.
const string PLATFORMS_CACHE_KEY = "software:platforms:list";
static readonly TimeSpan _platformsCacheTtl = TimeSpan.FromMinutes(5);
const string PLATFORMS_CACHE_KEY = "software:platforms:list";
const string PLATFORMS_WITH_SOFTWARE_CACHE_KEY = "software:platforms:with-software";
static readonly TimeSpan _platformsCacheTtl = TimeSpan.FromMinutes(5);
[HttpGet]
[AllowAnonymous]
[OutputCache(Duration = 300, VaryByQueryKeys = ["includeUnused"])]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<List<SoftwarePlatformDto>> GetAsync()
public async Task<List<SoftwarePlatformDto>> GetAsync([FromQuery] bool includeUnused = true)
{
if(cache.TryGetValue(PLATFORMS_CACHE_KEY, out List<SoftwarePlatformDto> cached) && cached is not null)
string cacheKey = includeUnused ? PLATFORMS_CACHE_KEY : PLATFORMS_WITH_SOFTWARE_CACHE_KEY;
if(cache.TryGetValue(cacheKey, out List<SoftwarePlatformDto> cached) && cached is not null)
return cached;
List<SoftwarePlatformDto> platforms = await context.SoftwarePlatforms.OrderBy(p => p.Name)
.Select(p => new SoftwarePlatformDto
{
Id = p.Id,
Name = p.Name
})
.ToListAsync();
IQueryable<SoftwarePlatform> query = context.SoftwarePlatforms;
if(!includeUnused)
query = query.Where(p => p.SoftwareReleases.Any());
cache.Set(PLATFORMS_CACHE_KEY, platforms, _platformsCacheTtl);
List<SoftwarePlatformDto> platforms = await query.OrderBy(p => p.Name)
.Select(p => new SoftwarePlatformDto
{
Id = p.Id,
Name = p.Name
})
.ToListAsync();
cache.Set(cacheKey, platforms, _platformsCacheTtl);
return platforms;
}
@@ -99,6 +109,7 @@ public class SoftwarePlatformsController(MarechaiContext context, IMemoryCache c
await context.SaveChangesWithUserAsync(userId);
cache.Remove(PLATFORMS_CACHE_KEY);
cache.Remove(PLATFORMS_WITH_SOFTWARE_CACHE_KEY);
return Ok();
}
@@ -123,6 +134,7 @@ public class SoftwarePlatformsController(MarechaiContext context, IMemoryCache c
await context.SaveChangesWithUserAsync(userId);
cache.Remove(PLATFORMS_CACHE_KEY);
cache.Remove(PLATFORMS_WITH_SOFTWARE_CACHE_KEY);
return model.Id;
}
@@ -147,6 +159,7 @@ public class SoftwarePlatformsController(MarechaiContext context, IMemoryCache c
await context.SaveChangesWithUserAsync(userId);
cache.Remove(PLATFORMS_CACHE_KEY);
cache.Remove(PLATFORMS_WITH_SOFTWARE_CACHE_KEY);
return Ok();
}
@@ -209,6 +222,7 @@ public class SoftwarePlatformsController(MarechaiContext context, IMemoryCache c
await context.SaveChangesWithUserAsync(userId);
cache.Remove(PLATFORMS_CACHE_KEY);
cache.Remove(PLATFORMS_WITH_SOFTWARE_CACHE_KEY);
return Ok();
}

View File

@@ -92,7 +92,7 @@ public partial class Index
Task<int> countTask = Service.GetSoftwareCountAsync();
Task<int> minYearTask = Service.GetMinimumYearAsync();
Task<int> maxYearTask = Service.GetMaximumYearAsync();
Task<List<SoftwarePlatformDto>> platformsTask = Service.GetPlatformsAsync();
Task<List<SoftwarePlatformDto>> platformsTask = Service.GetPlatformsAsync(includeUnused: false);
Task<List<SoftwareGenreDto>> genresTask = Service.GetAllGenresAsync();
Task<List<SoftwareSpecKeyDto>> specsTask = Service.GetSpecificationsAsync();

View File

@@ -458,11 +458,14 @@ public class SoftwareService(Marechai.ApiClient.Client client, IRequestAdapter r
}
}
public async Task<List<SoftwarePlatformDto>> GetPlatformsAsync()
public async Task<List<SoftwarePlatformDto>> GetPlatformsAsync(bool includeUnused = true)
{
try
{
List<SoftwarePlatformDto> platforms = await client.Software.Platforms.GetAsync();
List<SoftwarePlatformDto> platforms = await client.Software.Platforms.GetAsync(config =>
{
if(!includeUnused) config.QueryParameters.IncludeUnused = false;
});
return platforms ?? [];
}