feat(AppVersion): Add AppVersionService for cache invalidation on version update
Build and Deploy to Production / build-and-deploy (push) Successful in 1m37s
Build and Deploy to Production / build-and-deploy (push) Successful in 1m37s
- Add AppVersionService to check version and clear cache if needed - Update Configuration.Protobuf package to 0.0.4 with AppVersion proto - Integrate version check in App.razor on app initialization
This commit is contained in:
@@ -11,10 +11,15 @@ public partial class App
|
|||||||
{
|
{
|
||||||
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
[Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
|
||||||
[Inject] private AuthService AuthService { get; set; } = default!;
|
[Inject] private AuthService AuthService { get; set; } = default!;
|
||||||
|
[Inject] private AppVersionService AppVersionService { get; set; } = default!;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
|
|
||||||
|
// Check app version and clear cache if needed
|
||||||
|
await AppVersionService.CheckVersionAndClearCacheIfNeededAsync();
|
||||||
|
|
||||||
// Check for referral code in URL query parameters
|
// Check for referral code in URL query parameters
|
||||||
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
|
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
|
||||||
var query = QueryHelpers.ParseQuery(uri.Query);
|
var query = QueryHelpers.ParseQuery(uri.Query);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using FrontOffice.BFF.NetworkMembership.Protobuf.Protos.NetworkMembership;
|
|||||||
using FrontOffice.BFF.DiscountShop.Protobuf.Protos.DiscountShop;
|
using FrontOffice.BFF.DiscountShop.Protobuf.Protos.DiscountShop;
|
||||||
using FrontOffice.BFF.City.Protobuf;
|
using FrontOffice.BFF.City.Protobuf;
|
||||||
using FrontOffice.BFF.Configuration.Protobuf.Protos.Configuration;
|
using FrontOffice.BFF.Configuration.Protobuf.Protos.Configuration;
|
||||||
|
using FrontOffice.BFF.Configuration.Protobuf.Protos.AppVersion;
|
||||||
using FrontOffice.Main.Utilities;
|
using FrontOffice.Main.Utilities;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection;
|
namespace Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -61,6 +62,8 @@ public static class ConfigureServices
|
|||||||
services.AddScoped<ClubConfigurationService>();
|
services.AddScoped<ClubConfigurationService>();
|
||||||
services.AddScoped<NetworkMembershipService>();
|
services.AddScoped<NetworkMembershipService>();
|
||||||
services.AddScoped<CommissionService>();
|
services.AddScoped<CommissionService>();
|
||||||
|
// App Version Service for cache invalidation
|
||||||
|
services.AddScoped<AppVersionService>();
|
||||||
// Device detection: very light, dependency-free
|
// Device detection: very light, dependency-free
|
||||||
services.AddTransient<IDeviceDetector, DeviceDetector>();
|
services.AddTransient<IDeviceDetector, DeviceDetector>();
|
||||||
// PDF generation (Chromium only)
|
// PDF generation (Chromium only)
|
||||||
@@ -110,6 +113,7 @@ public static class ConfigureServices
|
|||||||
services.AddScoped(CreateAuthenticatedClient<NetworkMembershipContract.NetworkMembershipContractClient>);
|
services.AddScoped(CreateAuthenticatedClient<NetworkMembershipContract.NetworkMembershipContractClient>);
|
||||||
services.AddScoped(CreateAuthenticatedClient<DiscountShopContract.DiscountShopContractClient>);
|
services.AddScoped(CreateAuthenticatedClient<DiscountShopContract.DiscountShopContractClient>);
|
||||||
services.AddScoped(CreateAuthenticatedClient<CityContract.CityContractClient>);
|
services.AddScoped(CreateAuthenticatedClient<CityContract.CityContractClient>);
|
||||||
|
services.AddScoped(CreateAuthenticatedClient<AppVersionContract.AppVersionContractClient>);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<PackageReference Include="Foursat.FrontOffice.BFF.City.Protobuf" Version="0.0.2" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.City.Protobuf" Version="0.0.2" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.ClubMembership.Protobuf" Version="0.0.4" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.ClubMembership.Protobuf" Version="0.0.4" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.Commission.Protobuf" Version="0.0.3" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.Commission.Protobuf" Version="0.0.3" />
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.Configuration.Protobuf" Version="0.0.3" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.Configuration.Protobuf" Version="0.0.4" />
|
||||||
<!-- <PackageReference Include="Foursat.FrontOffice.BFF.ClubMembership.Protobuf" Version="0.0.3" /> -->
|
<!-- <PackageReference Include="Foursat.FrontOffice.BFF.ClubMembership.Protobuf" Version="0.0.3" /> -->
|
||||||
<!-- <PackageReference Include="Foursat.FrontOffice.BFF.Commission.Protobuf" Version="0.0.2" /> -->
|
<!-- <PackageReference Include="Foursat.FrontOffice.BFF.Commission.Protobuf" Version="0.0.2" /> -->
|
||||||
<PackageReference Include="Foursat.FrontOffice.BFF.DiscountShop.Protobuf" Version="0.0.3" />
|
<PackageReference Include="Foursat.FrontOffice.BFF.DiscountShop.Protobuf" Version="0.0.3" />
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using FrontOffice.BFF.Configuration.Protobuf.Protos.AppVersion;
|
||||||
|
using Blazored.LocalStorage;
|
||||||
|
|
||||||
|
namespace FrontOffice.Main.Utilities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// سرویس مدیریت نسخه اپلیکیشن و کش
|
||||||
|
/// وقتی نسخه جدید منتشر بشه، این سرویس متوجه میشه و کش رو پاک میکنه
|
||||||
|
/// </summary>
|
||||||
|
public class AppVersionService
|
||||||
|
{
|
||||||
|
private readonly AppVersionContract.AppVersionContractClient _client;
|
||||||
|
private readonly ILocalStorageService _localStorage;
|
||||||
|
private readonly ILogger<AppVersionService> _logger;
|
||||||
|
|
||||||
|
private const string APP_NAME = "FrontOffice";
|
||||||
|
private const string LOCAL_VERSION_KEY = "app_version";
|
||||||
|
private const string LAST_CHECK_KEY = "app_version_last_check";
|
||||||
|
|
||||||
|
public AppVersionService(
|
||||||
|
AppVersionContract.AppVersionContractClient client,
|
||||||
|
ILocalStorageService localStorage,
|
||||||
|
ILogger<AppVersionService> logger)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
_localStorage = localStorage;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// بررسی نسخه اپلیکیشن و پاک کردن کش در صورت نیاز
|
||||||
|
/// </summary>
|
||||||
|
public async Task CheckVersionAndClearCacheIfNeededAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// دریافت نسخه فعلی از localStorage
|
||||||
|
var localVersion = await _localStorage.GetItemAsStringAsync(LOCAL_VERSION_KEY);
|
||||||
|
|
||||||
|
// بررسی نسخه از سرور
|
||||||
|
var response = await _client.GetAppVersionAsync(new GetAppVersionRequest
|
||||||
|
{
|
||||||
|
AppName = APP_NAME,
|
||||||
|
CurrentClientVersion = localVersion
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.Found)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("App version not found on server for {AppName}", APP_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverVersion = response.CurrentVersion;
|
||||||
|
|
||||||
|
// اگر نسخه جدید باشه یا پاک کردن کش لازم باشه
|
||||||
|
if (localVersion != serverVersion || response.RequiresFullCacheClear)
|
||||||
|
{
|
||||||
|
_logger.LogInformation(
|
||||||
|
"New version detected: {OldVersion} -> {NewVersion}, CacheClear: {CacheClear}",
|
||||||
|
localVersion ?? "null", serverVersion, response.RequiresFullCacheClear);
|
||||||
|
|
||||||
|
// پاک کردن کش
|
||||||
|
await ClearAllCacheAsync();
|
||||||
|
|
||||||
|
// ذخیره نسخه جدید
|
||||||
|
await _localStorage.SetItemAsStringAsync(LOCAL_VERSION_KEY, serverVersion);
|
||||||
|
await _localStorage.SetItemAsStringAsync(LAST_CHECK_KEY, DateTime.UtcNow.ToString("O"));
|
||||||
|
|
||||||
|
_logger.LogInformation("Cache cleared and version updated to {Version}", serverVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error checking app version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پاک کردن همه کشهای اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
private async Task ClearAllCacheAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// لیست کلیدهایی که باید حفظ بشن (مثل توکن و اطلاعات کاربر)
|
||||||
|
var keysToKeep = new HashSet<string>
|
||||||
|
{
|
||||||
|
"access_token",
|
||||||
|
"refresh_token",
|
||||||
|
"user_info",
|
||||||
|
"user_roles"
|
||||||
|
};
|
||||||
|
|
||||||
|
// دریافت همه کلیدها
|
||||||
|
var allKeys = await _localStorage.KeysAsync();
|
||||||
|
|
||||||
|
// پاک کردن کلیدهایی که در لیست حفظ نیستن
|
||||||
|
foreach (var key in allKeys)
|
||||||
|
{
|
||||||
|
if (!keysToKeep.Contains(key) && key != LOCAL_VERSION_KEY)
|
||||||
|
{
|
||||||
|
await _localStorage.RemoveItemAsync(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Local storage cache cleared, {Count} keys removed",
|
||||||
|
allKeys.Count() - keysToKeep.Count);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error clearing cache");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت اطلاعات نسخه فعلی
|
||||||
|
/// </summary>
|
||||||
|
public async Task<AppVersionInfo?> GetCurrentVersionInfoAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _client.GetAppVersionAsync(new GetAppVersionRequest
|
||||||
|
{
|
||||||
|
AppName = APP_NAME
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.Found)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new AppVersionInfo
|
||||||
|
{
|
||||||
|
CurrentVersion = response.CurrentVersion,
|
||||||
|
MinRequiredVersion = response.MinRequiredVersion,
|
||||||
|
RequiresUpdate = response.RequiresUpdate,
|
||||||
|
UpdateMessage = response.UpdateMessage,
|
||||||
|
ReleaseNotes = response.ReleaseNotes,
|
||||||
|
LastUpdated = response.LastUpdated?.ToDateTime()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error getting version info");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppVersionInfo
|
||||||
|
{
|
||||||
|
public string CurrentVersion { get; set; } = string.Empty;
|
||||||
|
public string MinRequiredVersion { get; set; } = string.Empty;
|
||||||
|
public bool RequiresUpdate { get; set; }
|
||||||
|
public string? UpdateMessage { get; set; }
|
||||||
|
public string? ReleaseNotes { get; set; }
|
||||||
|
public DateTime? LastUpdated { get; set; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user