feat(AppVersion): Add version tracking system for frontend cache invalidation
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 AppVersion entity with CurrentVersion, MinRequiredVersion, RequiresFullCacheClear - Add GetAppVersion query to check app version and compare with client version - Add GetAllAppVersions query for admin panel - Add UpdateAppVersion command to update/create app versions - Add appversion.proto for gRPC communication - Add AppVersionService for gRPC endpoints - Add database migration for AppVersions table
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
|||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Commands.UpdateAppVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command برای آپدیت یا ایجاد نسخه جدید اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public record UpdateAppVersionCommand : IRequest<Unit>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// نام اپلیکیشن (FrontOffice, BackOffice, MobileApp)
|
||||||
|
/// </summary>
|
||||||
|
public string AppName { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شماره نسخه جدید (مثلاً 1.2.3)
|
||||||
|
/// </summary>
|
||||||
|
public string CurrentVersion { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حداقل نسخه مورد نیاز
|
||||||
|
/// </summary>
|
||||||
|
public string? MinRequiredVersion { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا کش کامل باید پاک بشه؟
|
||||||
|
/// </summary>
|
||||||
|
public bool RequiresFullCacheClear { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیام آپدیت
|
||||||
|
/// </summary>
|
||||||
|
public string? UpdateMessage { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// توضیحات تغییرات این نسخه
|
||||||
|
/// </summary>
|
||||||
|
public string? ReleaseNotes { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دلیل آپدیت (برای لاگ)
|
||||||
|
/// </summary>
|
||||||
|
public string? UpdateReason { get; init; }
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
using CMSMicroservice.Domain.Entities.Configuration;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Commands.UpdateAppVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler برای آپدیت یا ایجاد نسخه جدید اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public class UpdateAppVersionCommandHandler : IRequestHandler<UpdateAppVersionCommand, Unit>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
private readonly ILogger<UpdateAppVersionCommandHandler> _logger;
|
||||||
|
|
||||||
|
public UpdateAppVersionCommandHandler(
|
||||||
|
IApplicationDbContext context,
|
||||||
|
ILogger<UpdateAppVersionCommandHandler> logger)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> Handle(UpdateAppVersionCommand request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// پیدا کردن نسخه موجود برای این اپ
|
||||||
|
var existingVersion = await _context.AppVersions
|
||||||
|
.Where(v => v.AppName == request.AppName && !v.IsDeleted)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (existingVersion != null)
|
||||||
|
{
|
||||||
|
// آپدیت نسخه موجود
|
||||||
|
existingVersion.CurrentVersion = request.CurrentVersion;
|
||||||
|
existingVersion.MinRequiredVersion = request.MinRequiredVersion ?? request.CurrentVersion;
|
||||||
|
existingVersion.RequiresFullCacheClear = request.RequiresFullCacheClear;
|
||||||
|
existingVersion.UpdateMessage = request.UpdateMessage;
|
||||||
|
existingVersion.ReleaseNotes = request.ReleaseNotes;
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"App version updated: {AppName} v{Version}, CacheClear={CacheClear}, Reason={Reason}",
|
||||||
|
request.AppName, request.CurrentVersion, request.RequiresFullCacheClear, request.UpdateReason);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ایجاد نسخه جدید
|
||||||
|
var newVersion = new AppVersion
|
||||||
|
{
|
||||||
|
AppName = request.AppName,
|
||||||
|
CurrentVersion = request.CurrentVersion,
|
||||||
|
MinRequiredVersion = request.MinRequiredVersion ?? request.CurrentVersion,
|
||||||
|
RequiresFullCacheClear = request.RequiresFullCacheClear,
|
||||||
|
UpdateMessage = request.UpdateMessage,
|
||||||
|
ReleaseNotes = request.ReleaseNotes,
|
||||||
|
IsActive = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.AppVersions.Add(newVersion);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"New app version created: {AppName} v{Version}, CacheClear={CacheClear}, Reason={Reason}",
|
||||||
|
request.AppName, request.CurrentVersion, request.RequiresFullCacheClear, request.UpdateReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
return Unit.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Queries.GetAllAppVersions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query برای دریافت همه نسخههای اپلیکیشنها
|
||||||
|
/// </summary>
|
||||||
|
public record GetAllAppVersionsQuery(bool IncludeInactive = false) : IRequest<List<AppVersionItemDto>>;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DTO برای هر آیتم نسخه اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public record AppVersionItemDto
|
||||||
|
{
|
||||||
|
public long Id { get; init; }
|
||||||
|
public string AppName { get; init; } = string.Empty;
|
||||||
|
public string CurrentVersion { get; init; } = string.Empty;
|
||||||
|
public string MinRequiredVersion { get; init; } = string.Empty;
|
||||||
|
public bool RequiresFullCacheClear { get; init; }
|
||||||
|
public string? UpdateMessage { get; init; }
|
||||||
|
public string? ReleaseNotes { get; init; }
|
||||||
|
public bool IsActive { get; init; }
|
||||||
|
public DateTime Created { get; init; }
|
||||||
|
public DateTime? LastModified { get; init; }
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Queries.GetAllAppVersions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler برای دریافت همه نسخههای اپلیکیشنها
|
||||||
|
/// </summary>
|
||||||
|
public class GetAllAppVersionsQueryHandler : IRequestHandler<GetAllAppVersionsQuery, List<AppVersionItemDto>>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
|
||||||
|
public GetAllAppVersionsQueryHandler(IApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<AppVersionItemDto>> Handle(GetAllAppVersionsQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var query = _context.AppVersions
|
||||||
|
.Where(v => !v.IsDeleted);
|
||||||
|
|
||||||
|
if (!request.IncludeInactive)
|
||||||
|
{
|
||||||
|
query = query.Where(v => v.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
var versions = await query
|
||||||
|
.OrderBy(v => v.AppName)
|
||||||
|
.Select(v => new AppVersionItemDto
|
||||||
|
{
|
||||||
|
Id = v.Id,
|
||||||
|
AppName = v.AppName,
|
||||||
|
CurrentVersion = v.CurrentVersion,
|
||||||
|
MinRequiredVersion = v.MinRequiredVersion,
|
||||||
|
RequiresFullCacheClear = v.RequiresFullCacheClear,
|
||||||
|
UpdateMessage = v.UpdateMessage,
|
||||||
|
ReleaseNotes = v.ReleaseNotes,
|
||||||
|
IsActive = v.IsActive,
|
||||||
|
Created = v.Created,
|
||||||
|
LastModified = v.LastModified
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return versions;
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Queries.GetAppVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query برای دریافت آخرین نسخه یک اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public record GetAppVersionQuery(string AppName, string? CurrentClientVersion = null) : IRequest<AppVersionDto?>;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DTO برای اطلاعات نسخه اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public record AppVersionDto
|
||||||
|
{
|
||||||
|
public bool Found { get; init; }
|
||||||
|
public string AppName { get; init; } = string.Empty;
|
||||||
|
public string CurrentVersion { get; init; } = string.Empty;
|
||||||
|
public string MinRequiredVersion { get; init; } = string.Empty;
|
||||||
|
public bool RequiresFullCacheClear { get; init; }
|
||||||
|
public bool RequiresUpdate { get; init; }
|
||||||
|
public string? UpdateMessage { get; init; }
|
||||||
|
public string? ReleaseNotes { get; init; }
|
||||||
|
public DateTime? LastUpdated { get; init; }
|
||||||
|
}
|
||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
using CMSMicroservice.Domain.Entities.Configuration;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.AppVersionCQ.Queries.GetAppVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler برای دریافت آخرین نسخه اپلیکیشن
|
||||||
|
/// </summary>
|
||||||
|
public class GetAppVersionQueryHandler : IRequestHandler<GetAppVersionQuery, AppVersionDto?>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
|
||||||
|
public GetAppVersionQueryHandler(IApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AppVersionDto?> Handle(GetAppVersionQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var appVersion = await _context.AppVersions
|
||||||
|
.Where(v => v.AppName == request.AppName && v.IsActive && !v.IsDeleted)
|
||||||
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (appVersion == null)
|
||||||
|
{
|
||||||
|
return new AppVersionDto
|
||||||
|
{
|
||||||
|
Found = false,
|
||||||
|
AppName = request.AppName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// مقایسه ورژن کلاینت با حداقل نسخه مورد نیاز
|
||||||
|
bool requiresUpdate = false;
|
||||||
|
if (!string.IsNullOrEmpty(request.CurrentClientVersion) && !string.IsNullOrEmpty(appVersion.MinRequiredVersion))
|
||||||
|
{
|
||||||
|
requiresUpdate = CompareVersions(request.CurrentClientVersion, appVersion.MinRequiredVersion) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AppVersionDto
|
||||||
|
{
|
||||||
|
Found = true,
|
||||||
|
AppName = appVersion.AppName,
|
||||||
|
CurrentVersion = appVersion.CurrentVersion,
|
||||||
|
MinRequiredVersion = appVersion.MinRequiredVersion,
|
||||||
|
RequiresFullCacheClear = appVersion.RequiresFullCacheClear,
|
||||||
|
RequiresUpdate = requiresUpdate,
|
||||||
|
UpdateMessage = appVersion.UpdateMessage,
|
||||||
|
ReleaseNotes = appVersion.ReleaseNotes,
|
||||||
|
LastUpdated = appVersion.LastModified ?? appVersion.Created
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// مقایسه دو نسخه (مثلاً 1.2.3 با 1.3.0)
|
||||||
|
/// برگشت: منفی = اولی کوچکتر، مثبت = اولی بزرگتر، صفر = برابر
|
||||||
|
/// </summary>
|
||||||
|
private static int CompareVersions(string version1, string version2)
|
||||||
|
{
|
||||||
|
var v1Parts = version1.Split('.').Select(s => int.TryParse(s, out var n) ? n : 0).ToArray();
|
||||||
|
var v2Parts = version2.Split('.').Select(s => int.TryParse(s, out var n) ? n : 0).ToArray();
|
||||||
|
|
||||||
|
var maxLen = Math.Max(v1Parts.Length, v2Parts.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < maxLen; i++)
|
||||||
|
{
|
||||||
|
var v1 = i < v1Parts.Length ? v1Parts[i] : 0;
|
||||||
|
var v2 = i < v2Parts.Length ? v2Parts[i] : 0;
|
||||||
|
|
||||||
|
if (v1 != v2)
|
||||||
|
return v1.CompareTo(v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,7 @@ public interface IApplicationDbContext
|
|||||||
DbSet<CommissionPayoutHistory> CommissionPayoutHistories { get; }
|
DbSet<CommissionPayoutHistory> CommissionPayoutHistories { get; }
|
||||||
DbSet<WorkerExecutionLog> WorkerExecutionLogs { get; }
|
DbSet<WorkerExecutionLog> WorkerExecutionLogs { get; }
|
||||||
DbSet<DayaLoanContract> DayaLoanContracts { get; }
|
DbSet<DayaLoanContract> DayaLoanContracts { get; }
|
||||||
|
DbSet<AppVersion> AppVersions { get; }
|
||||||
|
|
||||||
// ============= Discount Shop =============
|
// ============= Discount Shop =============
|
||||||
DbSet<DiscountProduct> DiscountProducts { get; }
|
DbSet<DiscountProduct> DiscountProducts { get; }
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
namespace CMSMicroservice.Domain.Entities.Configuration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نسخه اپلیکیشنهای فرانتاند
|
||||||
|
/// وقتی ورژن آپدیت بشه، فرانتها باید کش و دادههای محلی رو پاک کنن
|
||||||
|
/// </summary>
|
||||||
|
public class AppVersion : BaseAuditableEntity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// نام اپلیکیشن (FrontOffice, BackOffice, MobileApp)
|
||||||
|
/// </summary>
|
||||||
|
public string AppName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شماره نسخه فعلی (مثلاً 1.2.3)
|
||||||
|
/// </summary>
|
||||||
|
public string CurrentVersion { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حداقل نسخه مورد نیاز - اگر کاربر از این پایینتر باشه باید آپدیت کنه
|
||||||
|
/// </summary>
|
||||||
|
public string MinRequiredVersion { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا کش کامل باید پاک بشه؟
|
||||||
|
/// </summary>
|
||||||
|
public bool RequiresFullCacheClear { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیام آپدیت برای نمایش به کاربر
|
||||||
|
/// </summary>
|
||||||
|
public string? UpdateMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// توضیحات تغییرات این نسخه
|
||||||
|
/// </summary>
|
||||||
|
public string? ReleaseNotes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فعال یا غیرفعال
|
||||||
|
/// </summary>
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
@@ -87,6 +87,7 @@ public class ApplicationDbContext : DbContext, IApplicationDbContext
|
|||||||
// Configuration
|
// Configuration
|
||||||
public DbSet<SystemConfiguration> SystemConfigurations => Set<SystemConfiguration>();
|
public DbSet<SystemConfiguration> SystemConfigurations => Set<SystemConfiguration>();
|
||||||
public DbSet<SystemConfigurationHistory> SystemConfigurationHistories => Set<SystemConfigurationHistory>();
|
public DbSet<SystemConfigurationHistory> SystemConfigurationHistories => Set<SystemConfigurationHistory>();
|
||||||
|
public DbSet<AppVersion> AppVersions => Set<AppVersion>();
|
||||||
|
|
||||||
// Club Management
|
// Club Management
|
||||||
public DbSet<ClubMembership> ClubMemberships => Set<ClubMembership>();
|
public DbSet<ClubMembership> ClubMemberships => Set<ClubMembership>();
|
||||||
|
|||||||
+3699
File diff suppressed because it is too large
Load Diff
+48
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddAppVersionsTable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AppVersions",
|
||||||
|
schema: "CMS",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
AppName = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
CurrentVersion = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
MinRequiredVersion = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
RequiresFullCacheClear = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
UpdateMessage = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
ReleaseNotes = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
LastModified = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifiedBy = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AppVersions", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AppVersions",
|
||||||
|
schema: "CMS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -451,6 +451,58 @@ namespace CMSMicroservice.Infrastructure.Persistence.Migrations
|
|||||||
b.ToTable("WorkerExecutionLogs", "CMS");
|
b.ToTable("WorkerExecutionLogs", "CMS");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("CMSMicroservice.Domain.Entities.Configuration.AppVersion", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AppName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Created")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CurrentVersion")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModified")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("LastModifiedBy")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MinRequiredVersion")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseNotes")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("RequiresFullCacheClear")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UpdateMessage")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AppVersions", "CMS");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("CMSMicroservice.Domain.Entities.Configuration.SystemConfiguration", b =>
|
modelBuilder.Entity("CMSMicroservice.Domain.Entities.Configuration.SystemConfiguration", b =>
|
||||||
{
|
{
|
||||||
b.Property<long>("Id")
|
b.Property<long>("Id")
|
||||||
|
|||||||
@@ -57,6 +57,8 @@
|
|||||||
<Protobuf Include="Protos\discountorder.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
<Protobuf Include="Protos\discountorder.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||||
<!-- Geography System (GMS) -->
|
<!-- Geography System (GMS) -->
|
||||||
<Protobuf Include="Protos\city.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
<Protobuf Include="Protos\city.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||||
|
<!-- App Version Tracking System -->
|
||||||
|
<Protobuf Include="Protos\appversion.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PushToFoursatNuget" AfterTargets="Pack">
|
<Target Name="PushToFoursatNuget" AfterTargets="Pack">
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package appversion;
|
||||||
|
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
|
||||||
|
option csharp_namespace = "CMSMicroservice.Protobuf.Protos.AppVersion";
|
||||||
|
|
||||||
|
// Service for tracking app versions and cache invalidation
|
||||||
|
service AppVersionContract
|
||||||
|
{
|
||||||
|
// Get current version for an app - called by frontends to check if cache clear is needed
|
||||||
|
rpc GetAppVersion(GetAppVersionRequest) returns (GetAppVersionResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/AppVersion/Get"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update/Create app version - called by admin when deploying new version
|
||||||
|
rpc UpdateAppVersion(UpdateAppVersionRequest) returns (google.protobuf.Empty){
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/AppVersion/Update"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all app versions
|
||||||
|
rpc GetAllAppVersions(GetAllAppVersionsRequest) returns (GetAllAppVersionsResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/AppVersion/GetAll"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to get current version for specific app
|
||||||
|
message GetAppVersionRequest
|
||||||
|
{
|
||||||
|
string app_name = 1; // e.g., "FrontOffice", "BackOffice", "Mobile"
|
||||||
|
google.protobuf.StringValue current_client_version = 2; // Current version on client for comparison
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response with version info
|
||||||
|
message GetAppVersionResponse
|
||||||
|
{
|
||||||
|
bool found = 1; // Whether the app was found
|
||||||
|
string app_name = 2;
|
||||||
|
string current_version = 3;
|
||||||
|
string min_required_version = 4;
|
||||||
|
bool requires_full_cache_clear = 5;
|
||||||
|
bool requires_update = 6; // True if client version < min_required_version
|
||||||
|
google.protobuf.StringValue update_message = 7;
|
||||||
|
google.protobuf.StringValue release_notes = 8;
|
||||||
|
google.protobuf.Timestamp last_updated = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to update/create app version
|
||||||
|
message UpdateAppVersionRequest
|
||||||
|
{
|
||||||
|
string app_name = 1;
|
||||||
|
string current_version = 2;
|
||||||
|
google.protobuf.StringValue min_required_version = 3;
|
||||||
|
bool requires_full_cache_clear = 4;
|
||||||
|
google.protobuf.StringValue update_message = 5;
|
||||||
|
google.protobuf.StringValue release_notes = 6;
|
||||||
|
google.protobuf.StringValue update_reason = 7; // For admin logs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to get all app versions
|
||||||
|
message GetAllAppVersionsRequest
|
||||||
|
{
|
||||||
|
bool include_inactive = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response with all app versions
|
||||||
|
message GetAllAppVersionsResponse
|
||||||
|
{
|
||||||
|
repeated AppVersionItem items = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AppVersionItem
|
||||||
|
{
|
||||||
|
int64 id = 1;
|
||||||
|
string app_name = 2;
|
||||||
|
string current_version = 3;
|
||||||
|
string min_required_version = 4;
|
||||||
|
bool requires_full_cache_clear = 5;
|
||||||
|
string update_message = 6;
|
||||||
|
string release_notes = 7;
|
||||||
|
bool is_active = 8;
|
||||||
|
google.protobuf.Timestamp created = 9;
|
||||||
|
google.protobuf.Timestamp last_modified = 10;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using CMSMicroservice.Protobuf.Protos.AppVersion;
|
||||||
|
using CMSMicroservice.WebApi.Common.Services;
|
||||||
|
using CMSMicroservice.Application.AppVersionCQ.Queries.GetAppVersion;
|
||||||
|
using CMSMicroservice.Application.AppVersionCQ.Queries.GetAllAppVersions;
|
||||||
|
using CMSMicroservice.Application.AppVersionCQ.Commands.UpdateAppVersion;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.WebApi.Services;
|
||||||
|
|
||||||
|
public class AppVersionService : AppVersionContract.AppVersionContractBase
|
||||||
|
{
|
||||||
|
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||||||
|
|
||||||
|
public AppVersionService(IDispatchRequestToCQRS dispatchRequestToCQRS)
|
||||||
|
{
|
||||||
|
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<GetAppVersionResponse> GetAppVersion(GetAppVersionRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
return await _dispatchRequestToCQRS.Handle<GetAppVersionRequest, GetAppVersionQuery, GetAppVersionResponse>(request, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<Empty> UpdateAppVersion(UpdateAppVersionRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
return await _dispatchRequestToCQRS.Handle<UpdateAppVersionRequest, UpdateAppVersionCommand>(request, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<GetAllAppVersionsResponse> GetAllAppVersions(GetAllAppVersionsRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
return await _dispatchRequestToCQRS.Handle<GetAllAppVersionsRequest, GetAllAppVersionsQuery, GetAllAppVersionsResponse>(request, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user