(low) JobSettingsPanel/isPendingFor: одна общая updateMutation — спиннер/opacity рассинхронизируются при параллельных Save #1429

Closed
opened 2026-06-15 05:54:44 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: concurrency · Файл: frontend/src/components/admin/JobSettingsPanel.tsx:106-135, 209-216

JobSettingsPanel.tsx:106 — единственный экземпляр updateMutation на все строки. isPendingFor (строки 209-215) определяет индикацию через updateMutation.variables?.job_type===job_type, но в TanStack Query variables хранит только последний вызванный mutate. При двух быстрых Save (строка A, затем B) variables становится {job_type:B}: спиннер «…» и opacity:0.6 (строка 305) у строки A пропадают, хотя её PUT ещё в полёте, а у B — горят. Данные не теряются (onSuccess пишет toRowDraft(data) по data.job_type, строки 119-122 — корректно), баг чисто индикационный. Импакт: пользователь видит, что строка A «не сохраняется», может нажать Save повторно → дубль PUT. Чинить: либо отслеживать pending по множеству job_type (Set в useState вокруг mutate/settled), либо использовать отдельные мутации, либо useMutationState для in-flight по ключу.

Почему баг: useMutation в TanStack Query — один in-flight стейт. updateMutation.isPending становится true на любой mutate, а variables перезаписывается каждым новым mutate. Значит isPendingFor может одновременно вернуть false для реально сохраняемой строки A (variables уже = B) и true для B. Пользователь видит, что строка A «не сохраняется» (нет '…'/затемнения), может нажать Save повторно, отправив дубль PUT. Это рассинхрон UI-состояния с реальным состоянием запросов при конкурентных правках.

Как чинить: Трекать pending по job_type отдельно (например useState<Set> или useMutationState), либо использовать отдельную мутацию на строку через фабрику/ключ. Минимум — хранить Set сохраняемых job_type и помечать строку saving по членству в нём.


deep-audit «армия ботов 2» · verify+harden, confidence 0.82 · unit U85

**Severity:** low · **Категория:** concurrency · **Файл:** `frontend/src/components/admin/JobSettingsPanel.tsx:106-135, 209-216` JobSettingsPanel.tsx:106 — единственный экземпляр updateMutation на все строки. isPendingFor (строки 209-215) определяет индикацию через updateMutation.variables?.job_type===job_type, но в TanStack Query variables хранит только последний вызванный mutate. При двух быстрых Save (строка A, затем B) variables становится {job_type:B}: спиннер «…» и opacity:0.6 (строка 305) у строки A пропадают, хотя её PUT ещё в полёте, а у B — горят. Данные не теряются (onSuccess пишет toRowDraft(data) по data.job_type, строки 119-122 — корректно), баг чисто индикационный. Импакт: пользователь видит, что строка A «не сохраняется», может нажать Save повторно → дубль PUT. Чинить: либо отслеживать pending по множеству job_type (Set в useState вокруг mutate/settled), либо использовать отдельные мутации, либо useMutationState для in-flight по ключу. **Почему баг:** useMutation в TanStack Query — один in-flight стейт. updateMutation.isPending становится true на любой mutate, а variables перезаписывается каждым новым mutate. Значит isPendingFor может одновременно вернуть false для реально сохраняемой строки A (variables уже = B) и true для B. Пользователь видит, что строка A «не сохраняется» (нет '…'/затемнения), может нажать Save повторно, отправив дубль PUT. Это рассинхрон UI-состояния с реальным состоянием запросов при конкурентных правках. **Как чинить:** Трекать pending по job_type отдельно (например useState<Set<string>> или useMutationState), либо использовать отдельную мутацию на строку через фабрику/ключ. Минимум — хранить Set сохраняемых job_type и помечать строку saving по членству в нём. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.82 · unit U85</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:54:44 +00:00
bot-backend added the
scope/backend
label 2026-06-15 11:02:03 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1429
No description provided.