mirror of
https://github.com/alexhopeoconnor/bom-local-service.git
synced 2026-10-03 21:21:59 +10:00
Fix: Exclude active cache folders in GetCachedFrameAsync to prevent reading incomplete data
- Add active cache folder exclusion to GetCachedFrameAsync - Prevents TaskCanceledException when reading metadata from folders being written to - Matches pattern used in GetCachedRadarAsync for consistency
This commit is contained in:
+74
@@ -9,6 +9,74 @@ builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
// Configure CORS - MUST be added before other services
|
||||
var corsOrigins = builder.Configuration.GetValue<string>("Cors:AllowedOrigins", "*");
|
||||
var corsMethods = builder.Configuration.GetValue<string>("Cors:AllowedMethods", "GET,POST,OPTIONS");
|
||||
var corsHeaders = builder.Configuration.GetValue<string>("Cors:AllowedHeaders", "*");
|
||||
var corsAllowCredentials = builder.Configuration.GetValue<bool>("Cors:AllowCredentials", false);
|
||||
|
||||
// Support environment variable override (comma-separated for multiple origins)
|
||||
var corsOriginsEnv = Environment.GetEnvironmentVariable("CORS__ALLOWEDORIGINS");
|
||||
if (!string.IsNullOrEmpty(corsOriginsEnv))
|
||||
{
|
||||
corsOrigins = corsOriginsEnv;
|
||||
}
|
||||
|
||||
var corsMethodsEnv = Environment.GetEnvironmentVariable("CORS__ALLOWEDMETHODS");
|
||||
if (!string.IsNullOrEmpty(corsMethodsEnv))
|
||||
{
|
||||
corsMethods = corsMethodsEnv;
|
||||
}
|
||||
|
||||
var corsHeadersEnv = Environment.GetEnvironmentVariable("CORS__ALLOWEDHEADERS");
|
||||
if (!string.IsNullOrEmpty(corsHeadersEnv))
|
||||
{
|
||||
corsHeaders = corsHeadersEnv;
|
||||
}
|
||||
|
||||
var corsAllowCredentialsEnv = Environment.GetEnvironmentVariable("CORS__ALLOWCREDENTIALS");
|
||||
if (!string.IsNullOrEmpty(corsAllowCredentialsEnv) && bool.TryParse(corsAllowCredentialsEnv, out var parsedCredentials))
|
||||
{
|
||||
corsAllowCredentials = parsedCredentials;
|
||||
}
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
if (corsOrigins == "*")
|
||||
{
|
||||
policy.AllowAnyOrigin();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split comma-separated origins
|
||||
var origins = corsOrigins.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
policy.WithOrigins(origins);
|
||||
}
|
||||
|
||||
// Split comma-separated methods
|
||||
var methods = corsMethods.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
policy.WithMethods(methods);
|
||||
|
||||
// Split comma-separated headers or allow all
|
||||
if (corsHeaders == "*")
|
||||
{
|
||||
policy.AllowAnyHeader();
|
||||
}
|
||||
else
|
||||
{
|
||||
var headers = corsHeaders.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
policy.WithHeaders(headers);
|
||||
}
|
||||
|
||||
if (corsAllowCredentials)
|
||||
{
|
||||
policy.AllowCredentials();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Register core services via interfaces (order matters - dependencies must be registered first)
|
||||
builder.Services.AddSingleton<IDebugService, DebugService>();
|
||||
builder.Services.AddSingleton<ICacheService, CacheService>();
|
||||
@@ -45,6 +113,12 @@ if (enableHttpsRedirection)
|
||||
app.UseHttpsRedirection();
|
||||
}
|
||||
|
||||
// Enable routing (required for CORS to work with controllers)
|
||||
app.UseRouting();
|
||||
|
||||
// CORS middleware - MUST be after UseRouting but before MapControllers
|
||||
app.UseCors();
|
||||
|
||||
// No authorization required - service is designed to run behind a reverse proxy if auth is needed
|
||||
|
||||
// Map MVC routes first (before API routes to avoid conflicts)
|
||||
|
||||
@@ -116,7 +116,10 @@ public class CacheService : ICacheService
|
||||
return null;
|
||||
}
|
||||
|
||||
var (cacheFolderPath, _) = await GetCachedScreenshotWithMetadataAsync(suburb, state, CachedDataType.Radar, null, cancellationToken);
|
||||
// Exclude active cache folder (currently being written to) to avoid reading incomplete data
|
||||
var locationKey = LocationHelper.GetLocationKey(suburb, state);
|
||||
var excludeFolder = GetActiveCacheFolder(locationKey);
|
||||
var (cacheFolderPath, _) = await GetCachedScreenshotWithMetadataAsync(suburb, state, CachedDataType.Radar, excludeFolder, cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(cacheFolderPath))
|
||||
{
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Cors": {
|
||||
"AllowedOrigins": "*",
|
||||
"AllowedMethods": "GET,POST,OPTIONS",
|
||||
"AllowedHeaders": "*",
|
||||
"AllowCredentials": false
|
||||
},
|
||||
"CacheDirectory": "./cache",
|
||||
"CacheRetentionHours": 24,
|
||||
"CacheExpirationMinutes": 12.5,
|
||||
|
||||
@@ -17,6 +17,14 @@ services:
|
||||
# Virtual display for non-headless browser
|
||||
- DISPLAY=:99
|
||||
|
||||
# CORS Configuration (for Home Assistant integration)
|
||||
# Multiple origins can be comma-separated: "http://homeassistant.local:8123,http://192.168.1.100:8123"
|
||||
# Use "*" to allow all origins (less secure, but convenient for development)
|
||||
- CORS__ALLOWEDORIGINS=${CORS__ALLOWEDORIGINS:-*}
|
||||
- CORS__ALLOWEDMETHODS=${CORS__ALLOWEDMETHODS:-GET,POST,OPTIONS}
|
||||
- CORS__ALLOWEDHEADERS=${CORS__ALLOWEDHEADERS:-*}
|
||||
- CORS__ALLOWCREDENTIALS=${CORS__ALLOWCREDENTIALS:-false}
|
||||
|
||||
# Application configuration (override appsettings.json)
|
||||
# Use double underscore (__) for nested config keys
|
||||
- CACHEDIRECTORY=${CACHEDIRECTORY:-/app/cache}
|
||||
|
||||
Reference in New Issue
Block a user