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
@@ -14,6 +14,7 @@ import { join } from 'path';
import { Prisma, ProductType, Setting, SettingTemplate } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';
import { AuditService } from '../audit/audit.service';
import { ReplicaWatchService } from '../replica-watch/replica-watch.service';
import { isSecretOrServerOnlySettingKey } from './secret-setting-keys';
import { isRuntimeProgramSettingKey } from './runtime-setting-keys';
import { DEPLOY_SETTING_CATALOG_KEYS } from './deploy-setting-catalog-keys';
@@ -57,6 +58,7 @@ export class ProgramSettingsService implements OnModuleInit {
constructor(
private readonly prisma: PrismaService,
private readonly audit: AuditService,
private readonly replicaWatch: ReplicaWatchService,
) {}
async onModuleInit() {
@@ -173,6 +175,7 @@ export class ProgramSettingsService implements OnModuleInit {
});
const items = await this.listTenantRows(tenantId);
this.replicaWatch.kick();
return {
tenant: this.tenantMeta(tenant),
items,
@@ -320,6 +323,7 @@ export class ProgramSettingsService implements OnModuleInit {
});
const items = await this.listTenantRows(tenantId);
this.replicaWatch.kick();
return {
tenant: this.tenantMeta(tenant),
apiBase,
@@ -390,6 +394,7 @@ export class ProgramSettingsService implements OnModuleInit {
after: { keys: incoming.map((r) => r.key), tenants: tenants.length } as Prisma.InputJsonValue,
});
this.replicaWatch.kick();
return {
keys: incoming.map((r) => r.key),
tenantsUpdated: tenants.length,
@@ -416,6 +421,7 @@ export class ProgramSettingsService implements OnModuleInit {
after: result as Prisma.InputJsonValue,
});
this.replicaWatch.kick();
return { key, ...result };
}