feat(replicas): auto-heal slave data drift and no-store public settings

Add sync-replica-data repair on deploy, a publisher-side replica watch
(60s + after tenant/settings writes), REFRESH PUBLICATION after migrate,
and Cache-Control no-store on program-settings and get_version.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-18 12:32:30 +03:30
co-authored by Cursor
parent 668bbcc1db
commit 16d562caa5
13 changed files with 456 additions and 11 deletions
+5
View File
@@ -8,6 +8,7 @@ import { PrismaService } from '../prisma/prisma.service';
import { AuditService } from '../audit/audit.service';
import { AdminNotifyService } from '../notifications/admin-notify.service';
import { ProgramSettingsService } from '../program-settings/program-settings.service';
import { ReplicaWatchService } from '../replica-watch/replica-watch.service';
import { CreateTenantDto } from './dto/create-tenant.dto';
import { UpdateTenantDto } from './dto/update-tenant.dto';
@@ -18,6 +19,7 @@ export class TenantsService {
private readonly audit: AuditService,
private readonly notify: AdminNotifyService,
private readonly programSettings: ProgramSettingsService,
private readonly replicaWatch: ReplicaWatchService,
) {}
async findAll(product?: ProductType) {
@@ -124,6 +126,7 @@ export class TenantsService {
`سوپرادمین: نسخه جدید «${tenant.nameFa}» (${tenant.domain}) ایجاد شد.`,
);
this.replicaWatch.kick();
return this.sanitize(tenant);
} catch (error) {
this.handleUnique(error);
@@ -245,6 +248,7 @@ export class TenantsService {
: `سوپرادمین: نسخه «${tenant.nameFa}» به‌روزرسانی شد.`,
);
this.replicaWatch.kick();
return this.sanitize(tenant);
} catch (error) {
this.handleUnique(error);
@@ -273,6 +277,7 @@ export class TenantsService {
`سوپرادمین: نسخه «${before.nameFa}» (${before.domain}) حذف شد.`,
);
this.replicaWatch.kick();
return { ok: true };
}