Retry state conflicts and always render server picker
Build and Deploy Gateway / build-and-push (push) Successful in 25s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-19 00:36:39 +03:00
parent dc1fd76c44
commit 7cb25d0633
4 changed files with 27 additions and 10 deletions
+20 -6
View File
@@ -53,6 +53,13 @@ const operationErrorContext: Record<string, string> = {
'route-rules': 'routing',
};
function asHarborApiError(error: unknown) {
const candidate = error && typeof error === 'object' ? error as Record<string, unknown> : {};
return error instanceof HarborApiError
? error
: new HarborApiError({ code: candidate.code }, Number(candidate.status));
}
export function App() {
const previewReady = new URLSearchParams(window.location.search).has('preview-ready');
const [{ snapshot: state, transport }, dispatch] = useReducer(
@@ -135,19 +142,26 @@ export function App() {
try {
return await applyMutation(action);
} catch (err) {
let safeError = asHarborApiError(err);
if (safeError.code === 'STATE_CONFLICT' && context !== 'routing') {
await loadState();
try {
return await applyMutation(action);
} catch (retryError) {
safeError = asHarborApiError(retryError);
}
}
await loadState();
const candidate = err && typeof err === 'object' ? err as Record<string, unknown> : {};
const safeError = err instanceof HarborApiError
? err
: new HarborApiError({ code: candidate.code }, Number(candidate.status));
setError({
context,
profileId,
message: context === 'routing' && safeError.code === 'STATE_CONFLICT'
? 'Правила уже изменились в другом окне. Проверьте статусы строк и сохраните ещё раз.'
: safeError.message,
: safeError.code === 'STATE_CONFLICT'
? 'Harbor снова получил новые данные во время действия. Повторите ещё раз.'
: safeError.message,
code: safeError.code,
correlationId: safeError.correlationId,
correlationId: safeError.code === 'STATE_CONFLICT' ? '' : safeError.correlationId,
retry: safeError.retryable && safeError.code !== 'STATE_CONFLICT'
? () => run(key, action, context, target, profileId)
: null,
@@ -487,7 +487,7 @@ function ProfileGroup({
inert={!expanded ? true : undefined}
>
<div className="client-profile-body-inner">
{!localStatus && renderServerPicker(profile, {
{renderServerPicker(profile, {
disabled: controlsBlocked,
leaving: false,
revealVersion: feature.revealVersions[profile.id] || 0,