From 516da671c61b3a2ae238b57fcc569707e36cf14f Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Thu, 25 Dec 2025 18:45:01 +0330 Subject: [PATCH] feat(AppVersion): Add AppVersionService for cache invalidation on version update - 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 --- src/FrontOffice.Main/App.razor.cs | 5 + src/FrontOffice.Main/ConfigureServices.cs | 4 + src/FrontOffice.Main/FrontOffice.Main.csproj | 2 +- .../Utilities/AppVersionService.cs | 156 ++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/FrontOffice.Main/Utilities/AppVersionService.cs diff --git a/src/FrontOffice.Main/App.razor.cs b/src/FrontOffice.Main/App.razor.cs index e11e668..4b99d91 100644 --- a/src/FrontOffice.Main/App.razor.cs +++ b/src/FrontOffice.Main/App.razor.cs @@ -11,10 +11,15 @@ public partial class App { [Inject] private ILocalStorageService LocalStorage { get; set; } = default!; [Inject] private AuthService AuthService { get; set; } = default!; + [Inject] private AppVersionService AppVersionService { get; set; } = default!; + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); + // Check app version and clear cache if needed + await AppVersionService.CheckVersionAndClearCacheIfNeededAsync(); + // Check for referral code in URL query parameters var uri = Navigation.ToAbsoluteUri(Navigation.Uri); var query = QueryHelpers.ParseQuery(uri.Query); diff --git a/src/FrontOffice.Main/ConfigureServices.cs b/src/FrontOffice.Main/ConfigureServices.cs index b0b8611..aeaf20b 100644 --- a/src/FrontOffice.Main/ConfigureServices.cs +++ b/src/FrontOffice.Main/ConfigureServices.cs @@ -20,6 +20,7 @@ using FrontOffice.BFF.NetworkMembership.Protobuf.Protos.NetworkMembership; using FrontOffice.BFF.DiscountShop.Protobuf.Protos.DiscountShop; using FrontOffice.BFF.City.Protobuf; using FrontOffice.BFF.Configuration.Protobuf.Protos.Configuration; +using FrontOffice.BFF.Configuration.Protobuf.Protos.AppVersion; using FrontOffice.Main.Utilities; namespace Microsoft.Extensions.DependencyInjection; @@ -61,6 +62,8 @@ public static class ConfigureServices services.AddScoped(); services.AddScoped(); services.AddScoped(); + // App Version Service for cache invalidation + services.AddScoped(); // Device detection: very light, dependency-free services.AddTransient(); // PDF generation (Chromium only) @@ -110,6 +113,7 @@ public static class ConfigureServices services.AddScoped(CreateAuthenticatedClient); services.AddScoped(CreateAuthenticatedClient); services.AddScoped(CreateAuthenticatedClient); + services.AddScoped(CreateAuthenticatedClient); return services; } diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index d26a51a..8134865 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/FrontOffice.Main/Utilities/AppVersionService.cs b/src/FrontOffice.Main/Utilities/AppVersionService.cs new file mode 100644 index 0000000..f301685 --- /dev/null +++ b/src/FrontOffice.Main/Utilities/AppVersionService.cs @@ -0,0 +1,156 @@ +using FrontOffice.BFF.Configuration.Protobuf.Protos.AppVersion; +using Blazored.LocalStorage; + +namespace FrontOffice.Main.Utilities; + +/// +/// سرویس مدیریت نسخه اپلیکیشن و کش +/// وقتی نسخه جدید منتشر بشه، این سرویس متوجه میشه و کش رو پاک می‌کنه +/// +public class AppVersionService +{ + private readonly AppVersionContract.AppVersionContractClient _client; + private readonly ILocalStorageService _localStorage; + private readonly ILogger _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 logger) + { + _client = client; + _localStorage = localStorage; + _logger = logger; + } + + /// + /// بررسی نسخه اپلیکیشن و پاک کردن کش در صورت نیاز + /// + 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"); + } + } + + /// + /// پاک کردن همه کش‌های اپلیکیشن + /// + private async Task ClearAllCacheAsync() + { + try + { + // لیست کلیدهایی که باید حفظ بشن (مثل توکن و اطلاعات کاربر) + var keysToKeep = new HashSet + { + "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"); + } + } + + /// + /// دریافت اطلاعات نسخه فعلی + /// + public async Task 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; } +}