Skip to content

Commit a63eda8

Browse files
authored
fix(site-replication): identify the local site by deployment ID instead of list position (#219)
1 parent 3266866 commit a63eda8

18 files changed

Lines changed: 219 additions & 7 deletions

‎app/(dashboard)/site-replication/page.tsx‎

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ import { Spinner } from "@/components/ui/spinner"
3535
import { useDataTable } from "@/hooks/use-data-table"
3636
import { usePermissions } from "@/hooks/use-permissions"
3737
import { useSiteReplication } from "@/hooks/use-site-replication"
38+
import { useSystem } from "@/hooks/use-system"
3839
import { formatDateTime, niceBytes } from "@/lib/functions"
3940
import { useDialog } from "@/lib/feedback/dialog"
4041
import { useMessage } from "@/lib/feedback/message"
42+
import { extractServerDeploymentId, resolveSiteReplicationLocalSite } from "@/lib/site-replication-local-site"
4143
import { isHttpsSiteReplicationEndpoint } from "@/lib/site-replication-tls"
4244
import type {
4345
SiteReplicationInfo,
@@ -117,9 +119,11 @@ export default function SiteReplicationPage() {
117119
resyncSiteReplication,
118120
setSiteReplicationIlmExpiry,
119121
} = useSiteReplication()
122+
const { getSystemInfo } = useSystem()
120123

121124
const [info, setInfo] = useState<SiteReplicationInfo | null>(null)
122125
const [status, setStatus] = useState<SiteReplicationStatus | null>(null)
126+
const [serverDeploymentId, setServerDeploymentId] = useState("")
123127
const [loading, setLoading] = useState(false)
124128
const [error, setError] = useState<string | null>(null)
125129
const [featureUnavailable, setFeatureUnavailable] = useState(false)
@@ -140,6 +144,14 @@ export default function SiteReplicationPage() {
140144
setFeatureUnavailable(false)
141145
setStatusUnavailable(false)
142146

147+
// The local deployment ID is the only stable way to tell which entry of
148+
// the shared, deployment-ID-sorted site list belongs to this server. Fetch
149+
// it alongside the replication data; a failure here only degrades the
150+
// "current site" identification, so it must not fail the whole page.
151+
const serverDeploymentIdPromise = getSystemInfo(undefined, { suppress403Redirect: true })
152+
.then(extractServerDeploymentId)
153+
.catch(() => "")
154+
143155
try {
144156
let nextInfo: SiteReplicationInfo | null = null
145157
let nextStatus: SiteReplicationStatus | null = null
@@ -168,25 +180,30 @@ export default function SiteReplicationPage() {
168180
}
169181
}
170182

183+
setServerDeploymentId(await serverDeploymentIdPromise)
171184
setInfo(nextInfo)
172185
setStatus(nextStatus)
173186
} catch (loadError) {
174187
setError((loadError as Error).message || t("Load Failed"))
175188
} finally {
176189
setLoading(false)
177190
}
178-
}, [getSiteReplicationInfo, getSiteReplicationStatus, t])
191+
}, [getSiteReplicationInfo, getSiteReplicationStatus, getSystemInfo, t])
179192

180193
useEffect(() => {
181194
void loadData()
182195
}, [loadData])
183196

184197
const peers = info?.sites ?? []
185198
const ilmExpiryEnabled = peers.some((peer) => peer.replicateIlmExpiry)
186-
const localDeploymentId =
187-
Object.keys(status?.metrics.metrics ?? {})[0] ??
188-
peers.find((peer) => peer.name && peer.name === info?.name)?.deploymentId ??
189-
""
199+
// Never pick the local site by array or key position: every site returns
200+
// the same list in the same order (issue rustfs/rustfs#7072).
201+
const localSite = resolveSiteReplicationLocalSite({
202+
serverDeploymentId,
203+
localName: info?.name,
204+
peers,
205+
})
206+
const localDeploymentId = localSite.deploymentId
190207
const localPeer = peers.find((peer) => peer.deploymentId === localDeploymentId) ?? null
191208
const localSummary = (localDeploymentId && status?.statsSummary[localDeploymentId]) || null
192209
const localMetric = (localDeploymentId && status?.metrics.metrics[localDeploymentId]) || null
@@ -586,6 +603,13 @@ export default function SiteReplicationPage() {
586603
label={t("Deployment ID")}
587604
value={<span className="font-mono text-xs break-all">{localDeploymentId || "--"}</span>}
588605
/>
606+
{info?.enabled && !localDeploymentId ? (
607+
<p className="text-xs text-muted-foreground" role="note">
608+
{localSite.ambiguousName
609+
? t("Multiple peers share the local site name, so the current site cannot be identified.")
610+
: t("The current site could not be identified because the server did not report its deployment ID.")}
611+
</p>
612+
) : null}
589613
</CardContent>
590614
</Card>
591615

‎hooks/use-system.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ export function useSystem() {
77
const api = useApi()
88

99
const getSystemInfo = useCallback(
10-
async (signal?: AbortSignal) => {
11-
return api.get("/info", signal ? { signal, dedupe: false } : undefined)
10+
async (signal?: AbortSignal, options?: { suppress403Redirect?: boolean }) => {
11+
return api.get("/info", {
12+
...(signal ? { signal, dedupe: false } : {}),
13+
...(options?.suppress403Redirect ? { suppress403Redirect: true } : {}),
14+
})
1215
},
1316
[api],
1417
)

‎i18n/locales/ar-MA.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "يحتوي الملف المُصدَّر على معلومات حساسة. يرجى الحفاظ عليه بأمان.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "يتم عرض المفتاح السري مرة واحدة فقط. انسخه أو صدّره قبل الإغلاق.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "يكتشف الخادم هوية الموقع المحلي من نشر RustFS النشط.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "تشترك عدة مواقع نظيرة في اسم الموقع المحلي نفسه، لذا يتعذر تحديد الموقع الحالي.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "تعذر تحديد الموقع الحالي لأن الخادم لم يُبلغ عن معرّف النشر الخاص به.",
11661168
"The two passwords are inconsistent": "كلمتا المرور غير متطابقتين",
11671169
"The value is used only for the initial join request.": "تُستخدم هذه القيمة فقط في طلب الانضمام الأولي.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "لا يمكن التراجع عن هذا الإجراء وسيتجاوز عملية الحذف العادية.",

‎i18n/locales/de-DE.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "Die exportierte Datei enthält sensible Informationen. Bitte bewahren Sie sie sicher auf.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "Der geheime Schlüssel wird nur einmal angezeigt. Kopieren oder exportieren Sie ihn vor dem Schließen.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "Der Server erkennt die lokale Site-Identität aus der aktiven RustFS-Bereitstellung.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Mehrere Peers verwenden denselben lokalen Site-Namen, daher kann die aktuelle Site nicht ermittelt werden.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "Die aktuelle Site konnte nicht ermittelt werden, da der Server seine Deployment-ID nicht gemeldet hat.",
11661168
"The two passwords are inconsistent": "Die beiden Passwörter stimmen nicht überein",
11671169
"The value is used only for the initial join request.": "Dieser Wert wird nur für die erste Beitrittsanfrage verwendet.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "Diese Aktion kann nicht rückgängig gemacht werden und umgeht den normalen Löschprozess.",

‎i18n/locales/en-US.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "The exported file contains sensitive information. Please keep it secure.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "The secret key is shown only once. Copy or export it before closing.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "The server detects the local site identity from the active RustFS deployment.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Multiple peers share the local site name, so the current site cannot be identified.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "The current site could not be identified because the server did not report its deployment ID.",
11661168
"The two passwords are inconsistent": "The two passwords are inconsistent",
11671169
"The value is used only for the initial join request.": "The value is used only for the initial join request.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "This action cannot be undone and will bypass the normal deletion process.",

‎i18n/locales/es-ES.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "El archivo exportado contiene información sensible. Manténgalo seguro.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "La clave secreta se muestra una sola vez. Cópiala o expórtala antes de cerrar.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "El servidor detecta la identidad del sitio local a partir de la implementación activa de RustFS.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Varios pares comparten el nombre del sitio local, por lo que no se puede identificar el sitio actual.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "No se pudo identificar el sitio actual porque el servidor no informó su ID de despliegue.",
11661168
"The two passwords are inconsistent": "Las dos contraseñas no coinciden",
11671169
"The value is used only for the initial join request.": "El valor se usa solo para la solicitud inicial de unión.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "Esta acción no se puede deshacer y omitirá el proceso normal de eliminación.",

‎i18n/locales/fr-FR.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "Le fichier exporté contient des informations sensibles. Veuillez le conserver en sécurité.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "La clé secrète n’est affichée qu’une seule fois. Copiez-la ou exportez-la avant de fermer.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "Le serveur détecte l'identité du site local à partir du déploiement RustFS actif.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Plusieurs pairs partagent le nom du site local, le site actuel ne peut donc pas être identifié.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "Le site actuel n'a pas pu être identifié car le serveur n'a pas signalé son ID de déploiement.",
11661168
"The two passwords are inconsistent": "Les deux mots de passe sont différents",
11671169
"The value is used only for the initial join request.": "Cette valeur est utilisée uniquement pour la demande de jonction initiale.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "Cette action ne peut pas être annulée et contournera le processus de suppression normal.",

‎i18n/locales/id-ID.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "File yang diekspor berisi informasi sensitif. Harap jaga keamanannya.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "Kunci rahasia hanya ditampilkan sekali. Salin atau ekspor sebelum menutup.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "Server mendeteksi identitas situs lokal dari deployment RustFS yang aktif.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Beberapa peer menggunakan nama situs lokal yang sama, sehingga situs saat ini tidak dapat diidentifikasi.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "Situs saat ini tidak dapat diidentifikasi karena server tidak melaporkan deployment ID-nya.",
11661168
"The two passwords are inconsistent": "Kedua kata sandi tidak cocok",
11671169
"The value is used only for the initial join request.": "Nilai ini hanya digunakan untuk permintaan bergabung awal.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "Tindakan ini tidak dapat dibatalkan dan akan melewati proses penghapusan normal.",

‎i18n/locales/it-IT.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "Il file esportato contiene informazioni sensibili. Conservalo in modo sicuro.",
11641164
"The secret key is shown only once. Copy or export it before closing.": "La chiave segreta viene mostrata una sola volta. Copiala o esportala prima di chiudere.",
11651165
"The server detects the local site identity from the active RustFS deployment.": "Il server rileva l'identità del sito locale dalla distribuzione RustFS attiva.",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "Più peer condividono il nome del sito locale, quindi il sito corrente non può essere identificato.",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "Impossibile identificare il sito corrente perché il server non ha riportato il proprio ID di deployment.",
11661168
"The two passwords are inconsistent": "Le due password non corrispondono",
11671169
"The value is used only for the initial join request.": "Il valore viene usato solo per la richiesta iniziale di adesione.",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "Questa azione non può essere annullata e bypasserà il normale processo di eliminazione.",

‎i18n/locales/ja-JP.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@
11631163
"The exported file contains sensitive information. Please keep it secure.": "エクスポートされたファイルには機密情報が含まれています。安全に保管してください。",
11641164
"The secret key is shown only once. Copy or export it before closing.": "シークレットキーが表示されるのは一度だけです。閉じる前にコピーまたはエクスポートしてください。",
11651165
"The server detects the local site identity from the active RustFS deployment.": "サーバーはアクティブな RustFS デプロイメントからローカルサイトの識別情報を検出します。",
1166+
"Multiple peers share the local site name, so the current site cannot be identified.": "複数のピアが同じローカルサイト名を共有しているため、現在のサイトを特定できません。",
1167+
"The current site could not be identified because the server did not report its deployment ID.": "サーバーが deployment ID を報告しなかったため、現在のサイトを特定できません。",
11661168
"The two passwords are inconsistent": "2つのパスワードが一致しません",
11671169
"The value is used only for the initial join request.": "この値は初回参加リクエストでのみ使用されます。",
11681170
"This action cannot be undone and will bypass the normal deletion process.": "この操作は元に戻せず、通常の削除プロセスをバイパスします。",

0 commit comments

Comments
 (0)