Fix TimeRangeError builder and update error response docs

- Fix TimeRangeError to properly extract properties from anonymous objects
- Add suggestions field to timeseries error response examples in README
- Enhance demo app to use suggested ranges from error responses
This commit is contained in:
2025-12-17 01:24:39 +10:00
parent 92c241b26e
commit 5e31ed33c6
13 changed files with 1298 additions and 182 deletions
+23
View File
@@ -61,5 +61,28 @@ public static class CacheHelper
{
return IsCacheFolderCompleteForDataType(cacheFolderPath, CachedDataType.Radar, configuration);
}
/// <summary>
/// Calculates the estimated cache update duration in seconds.
/// This is used as a fallback when metrics-based estimation is not available yet.
/// Calculates based on frame count and configured wait times.
/// </summary>
public static int GetEstimatedUpdateDurationSeconds(IConfiguration configuration, CachedDataType dataType = CachedDataType.Radar)
{
// Calculate based on actual wait times and frame count
var frameCount = GetFrameCountForDataType(configuration, dataType);
var tileRenderWaitMs = configuration.GetValue<int>("Screenshot:TileRenderWaitMs", 5000);
var dynamicContentWaitMs = configuration.GetValue<int>("Screenshot:DynamicContentWaitMs", 2000);
// Rough calculation:
// - Initial page load and navigation: ~10-15 seconds
// - Per frame: tileRenderWaitMs (default 5s) + overhead (~1-2s for clicking, waiting, etc.)
// - Final processing and metadata saving: ~5 seconds
var perFrameSeconds = (tileRenderWaitMs + 1500) / 1000.0; // Add 1.5s overhead per frame
var baseOverheadSeconds = 15; // Initial load + final processing
var estimatedSeconds = (int)Math.Ceiling(baseOverheadSeconds + (frameCount * perFrameSeconds));
return estimatedSeconds;
}
}
+14 -4
View File
@@ -22,7 +22,8 @@ public static class LocationHelper
}
/// <summary>
/// Parses suburb and state from a cache filename (format: Suburb_State_YYYYMMDD_HHMMSS.png)
/// Parses suburb and state from a cache filename (format: Suburb_State_YYYYMMDD_HHMMSS)
/// Handles multi-word suburbs like "Gold Coast" which becomes "Gold_Coast_QLD_20251216_130831"
/// Returns null if parsing fails
/// </summary>
public static (string suburb, string state)? ParseLocationFromFilename(string fileName)
@@ -30,12 +31,21 @@ public static class LocationHelper
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
var parts = fileNameWithoutExtension.Split('_');
if (parts.Length >= 2)
// Need at least: suburb, state, date, time (4 parts minimum)
// Format: [Suburb_Parts...]_State_YYYYMMDD_HHMMSS
if (parts.Length < 4)
{
return (parts[0], parts[1]);
return null;
}
return null;
// Last two parts are always timestamp (YYYYMMDD, HHMMSS)
// Second-to-last part is the state
// Everything before that is the suburb (may contain underscores from multi-word suburbs)
var state = parts[^3]; // Third from end
var suburbParts = parts.Take(parts.Length - 3).ToArray();
var suburb = string.Join(" ", suburbParts); // Join with spaces (original format had spaces converted to underscores)
return (suburb, state);
}
/// <summary>
+6 -3
View File
@@ -34,16 +34,18 @@ public static class ResponseBuilder
/// Creates a RadarResponse from a cache folder path, frames, and metadata
/// </summary>
/// <param name="cacheManagementCheckIntervalMinutes">The interval in minutes that the background cache management service checks for updates. Used to calculate NextUpdateTime when cache is invalid.</param>
/// <param name="estimatedUpdateDurationSeconds">Estimated duration in seconds for a cache update to complete. Used to calculate NextUpdateTime when update is in progress.</param>
public static RadarResponse CreateRadarResponse(
string cacheFolderPath,
List<RadarFrame> frames,
int cacheManagementCheckIntervalMinutes,
LastUpdatedInfo? metadata = null,
string? suburb = null,
string? state = null,
bool? cacheIsValid = null,
DateTime? cacheExpiresAt = null,
bool isUpdating = false,
int cacheManagementCheckIntervalMinutes = 5)
int? estimatedUpdateDurationSeconds = null)
{
var folderInfo = new DirectoryInfo(cacheFolderPath);
var lastWriteTime = folderInfo.Exists
@@ -88,8 +90,9 @@ public static class ResponseBuilder
if (isUpdating)
{
// Update in progress - estimate completion in ~2 minutes
nextUpdateTime = now.AddMinutes(2);
// Update in progress - estimate completion based on configured/calculated duration
var durationSeconds = estimatedUpdateDurationSeconds ?? 120; // Default to 2 minutes if not provided
nextUpdateTime = now.AddSeconds(durationSeconds);
}
else if (cacheIsValid == true && cacheExpiresAt.HasValue)
{