AURORA-1850: правка ячейки пересчитывает только затронутое поддерево #244
Open
aep
wants to merge 20 commits from
feat/235-aurora-1850-upd-form-cells-subtree into feat/215-aurora-1844-upd-form-cells-full-rows
pull from: feat/235-aurora-1850-upd-form-cells-subtree
merge into: RSHB:feat/215-aurora-1844-upd-form-cells-full-rows
RSHB:main
RSHB:feat/236-aurora-1843-svod2-server-paging-perf
RSHB:feat/236-aurora-1843-svod2-server-paging-web
RSHB:feat/236-aurora-1843-svod2-server-paging
RSHB:feat/214-aurora-1841-dict-vsp-virtual
RSHB:feat/220-aurora-1842-svod2-column-virtual
RSHB:feat/216-aurora-1846-form4-sheet-sum
RSHB:feat/233-aurora-1848-sheet-json-no-pydantic-b
RSHB:feat/234-aurora-1839-cell-memo
RSHB:feat/233-aurora-1848-sheet-json-no-pydantic
RSHB:feat/237-aurora-1845-ws-connection-cache
RSHB:feat/215-aurora-1844-upd-form-cells-full-rows
RSHB:feat/226-aurora-1837-cell-styles-css
RSHB:feat/207-aurora-1831-project-tn-race
RSHB:feat/208-aurora-1832-phase-dates-tz
RSHB:feat/209-aurora-1833-greenlet-dev
RSHB:feat/206-aurora-1830-users-me-local-email
RSHB:feat/212-aurora-1838-ws-immutable-update
RSHB:feat/211-aurora-1836-row-measure
RSHB:feat/205-aurora-1922-pg15-migration-0012
RSHB:feat/213-aurora-1840-sheet-modals
RSHB:feat/210-aurora-1835-svod1-formatter
RSHB:test
RSHB:svod2-filter-fix2
RSHB:indent-export
RSHB:export-hierarchy
RSHB:svod2-filter-fix
RSHB:fix-id-column
RSHB:export-year-fix
RSHB:form3-source
RSHB:columns-svod-2
RSHB:export-optimize-refresh
RSHB:last-column
RSHB:svod-fix
RSHB:fix-columns
RSHB:form3-expense
RSHB:sattelite-fix
RSHB:delete-sattelite-rows
RSHB:form3-pages
RSHB:form1-sub_sub-fix
RSHB:sort-fix
RSHB:fixes-form
RSHB:new-expenses
RSHB:new-rows
RSHB:fix-style
RSHB:phase-template-edit
RSHB:fixes
RSHB:add-btn-reset-filter
RSHB:vsp-choice-fix
RSHB:project-filters-fix
RSHB:width-column-header-name
RSHB:task-filter-navigation
RSHB:auth
RSHB:icons-program-project
RSHB:export-optimize
RSHB:org-unit-limits
RSHB:auth-v2
RSHB:tasks-filters
RSHB:insert-row-fix
RSHB:svod-roles
RSHB:new-role-fix
RSHB:phase-edit-fix
RSHB:new-role
RSHB:delete-from-cell
RSHB:svod-cahe-and-table-direction
RSHB:direction-stage-fix
RSHB:backslash-fix
RSHB:svod
RSHB:front-svod-form-1
RSHB:projects-filters
RSHB:remove-row-fix
RSHB:computed-fix
RSHB:modal-add-year-project
RSHB:name-fix
RSHB:audit-logs-projects
RSHB:meta-form-3
RSHB:project-back-fix
RSHB:fix-sticky-columns
RSHB:fixies-3-form
RSHB:tech-num-fix
RSHB:fix-logic-limitation
RSHB:projects-fix
RSHB:3-form-project
RSHB:project-add-year-handler
RSHB:projects-summary-handler
RSHB:AURORA-1247
RSHB:projects-handlers
RSHB:vsp-choose-form2-2
RSHB:directions-fix
RSHB:add-validation
RSHB:add-checkbox-export-vsp
RSHB:fix-update-column-config
RSHB:fix-editable-columns
RSHB:add-biome-front
RSHB:vsp-choose-form2
RSHB:export-form-4
RSHB:booking-fix
RSHB:fix-front-tables
RSHB:phase-directions
RSHB:AURORA-1225
RSHB:fix-mapping-form-2-oper
RSHB:AURORA-1076-fix
RSHB:fix-add-row-program-4-form
RSHB:form2-limit-migrations
RSHB:delete-projects
RSHB:AURORA-1076
RSHB:form-4-add-row
RSHB:fix-logs
RSHB:AURORA-1206
RSHB:AURORA-894
RSHB:add-line-log-hotfix
RSHB:form-export-fix
RSHB:form-4-sql
RSHB:table-optimization-fix
RSHB:header_forms
RSHB:form-4-expense-item-filters
RSHB:entity-type-hotfix
RSHB:form-3-phases-timezones
RSHB:form-4-handlers
RSHB:export-fix
RSHB:close-date-vsp-fix
RSHB:deleted-user-auth-fix
RSHB:smeta-fix
RSHB:front-fixes
RSHB:line_id_code_full
RSHB:line_id_code
RSHB:timezones
RSHB:filenames-fix
RSHB:AURORA-1174-73
RSHB:project-sheets
RSHB:AURORA-1166
RSHB:websocket-projects
RSHB:project-front
RSHB:form3-permissions
RSHB:location_from_to_placement_type
RSHB:fix-vsp-filters
RSHB:fix-tests-and-functions
RSHB:mig2-fix
RSHB:vsp_fixes
RSHB:fix-ssp-title
RSHB:AURORA-1148
RSHB:fix-vsp-form-edit
RSHB:sql-funcs2-fix
RSHB:AURORA-1132
RSHB:logs
RSHB:AURORA-1147
RSHB:export-optimization
RSHB:AURORA-1131
RSHB:sql-funcs-fix
RSHB:vsp-dropdown-form
RSHB:form_2-back
RSHB:migrations
RSHB:websocket-self-flag
RSHB:reload-fix
RSHB:test-stand-fix
RSHB:excel-empty-fix
RSHB:requirements-fix
RSHB:AURORA-1096-back
RSHB:AURORA-1098
RSHB:AURORA-1096
RSHB:ws-user-id-fix
RSHB:expense-item-handler
RSHB:fix-date-phase
RSHB:excel-fix
RSHB:vsp-edit-field-fix
RSHB:vsp-fix-back
RSHB:vsp-back
RSHB:create-form-back
RSHB:export-direction-fix
RSHB:change-role-fix
RSHB:org-unit-users-fix
RSHB:audit-fix
RSHB:org-archive
RSHB:del_row_fix
RSHB:websocket_locks
RSHB:new_line_id
RSHB:admin-back
RSHB:form-fix
RSHB:ws
RSHB:ssp-fix
RSHB:stages-back
RSHB:form_124_write
RSHB:form_124
RSHB:new-model
RSHB:test-tsygankov
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No description provided.
Delete Branch "feat/235-aurora-1850-upd-form-cells-subtree"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #235. Jira: AURORA-1850 (эпик AURORA-1834). Стек: база feat/215-aurora-1844-upd-form-cells-full-rows (PR #231), не
test.Что сделано
Миграция
0051_upd_form_cells_subtree:v3._form_affected_rowsдля FORM_1 и FORM_2 больше не собирает лист целиком.v_form{1,2}_sheet_sections->*_sheet_jsonb->v_form2_view/ новаяv_form1_viewполучили последним параметромp_focus_lines integer[] DEFAULT NULL(NULL — весь лист,'{}'— пустой результат).sort_orderсчитает построитель по лёгкому скелету листа (_sort_rank), одинаково для GET и правки; tie-break D6 (узел раньше строки; для OTCH9Fidпосле(expense_item_id, month))._form_affected_rows(STABLE) и дельта АХР (get_form2_ahr_satellite_delta) вызывают построители с фокусом; дельта теперь включает предков SUB_SUB_ITEM.SET jit = offнаv_form2_sheet_sections,v_form1_sheet_sections,_form_affected_rows, дельте.api/src,web/,perf/не менялись.before-0051.sql— тела 8 функций ревизии 0050 (база ревью и отката).Тесты
pytest --init_db, весь набор: 3 failed (исходные чужие:test_backend_calls_form3_add_project_and_add_line_functions, два вtest_export_service_query_params.py), 252 passed, 4 skipped (те же 4, что на базе; в новых файлах skip нет). Затем файлы feature после финальных правок: 54 passed, 0 skipped.pytest --init_db, весь набор), HEADb5a245e: 3 failed (те же 3), 256 passed, 4 skipped. Миграция проходит с нуля.(expense_item_id, month), D6: tie-break поid); содержимое одинаково.v_form_view, побайтноdata::text, по каждой строке листа, оба пути (_form_affected_rowsи построитель с фокусом). 0 вложенныхv_form_viewна пути правки (track_functions). Защита 0037.Проверить руками
Замер до/после
Добавит контроллер после прогона на стенде (design.md, «Замер до/после», шаги 1–7). На тестовых данных GET AHR 105 -> ~114 мс (+8 %), первая реализация (+93 %) отвергнута.
Rulings I made
budget_line,vsp), что GET;vsp_idNOT NULL + FK доказано, JOIN оставлен.dfip_1850_base,dfip_1850_snap(и временныеdfip_1850_*) одобрены.before-0051.sqlв каталоге change.v_form1_viewтолько AHR/CAP/OPER, раскладка тестов, регулярка для защиты 0037).Claude Opus 5.5по плану (в части коммитов исполнителей — Haiku 5.5)._form_affected_rows) не чистится ради отсутствия повторного прогона PG15 — deferred.Все решения без обсуждения — в design.md ->
## Decisions made without discussion.Находки
8a843b3)b1fbac2655a69c655a69c655a69c655a69cDeferred: T1.1, T2.10, T2.11, T2.12, T2.14, T4.1, T4.2, T5.2, T9.1, M-1, M-3, M-5.
🤖 Generated with Claude Code
Ночной замер на стенде perf/ (29.10, масштаб 1, CPU 1x, arm-ka-* остановлены) — часть 1 (1154 строки)
Сборки: «до» — 1844
f0cac30(D0 + миграция 0050), «после» — этот PRb5a245e(та же БД + 0051). Перед замерами после восстановления дампа —ANALYZE.Корректность (условие мержа) — выполнено
compare_responses.py dumpна 1844 и на 1850, без правок между снимками): все 25 ответов листов FORM_1/FORM_2 (все owner, с direction, FORM_2/AHR c sections) совпали байт в байт (exact=25, перестановок 0); весь набор из 56 запросов (листы FORM_1/2/4, своды 1/2, сводные, отчёты проектов) тоже exact=56. OTCH9F с совпадающим ключом на стенде перестановок не дал. Примечание: первый проход я снял с coauthor-прогоном между снимками — данные менялись, расхождение было артефактом методики, переснято отдельно (snap2-*)._form_affected_rowsпротив эталона изsheet_contract.py(фильтр 0050 поv_form_view, побайтноdata::text), только чтение: FORM_2/AHR 50 случайных строк + 2 пакета (5 строк, sections NULL иplan,q1), FORM_2 CAP/OPER/AHR_RENT и FORM_1/AHR по 20 + 2 пакета — 140 из 140 совпали (EQ_OK).Скорость, шаг 6 (coauthor FORM_2/AHR, rate 1 и 5, 3 повтора;
sql/coauthor/sql_top.json)upd_form_cellv_form_view(toplevel=false)v_form2_view(p_form_id, p_sheet, p_sections)callsШаг 5, GET без регресса — НЕ выполнен (цель, не условие мержа)
psql/asyncpg, одно соединение, 5 прогревов, 20 чередований
count(*) v_form_view(7,'AHR',NULL,NULL)иupd_form_cellв транзакции с ROLLBACK (tools/get_vs_upd.py), два прогона на сторону после ANALYZE:GET FORM_2/AHR на 1850 медленнее 1844 на +16 % (порог +10 %). Через API это тоже видно: 12 GET листа в coauthor-прогоне 349 мс (1850) — но там шла нагрузка правками, сравнивать по psql-цифрам.
Диагностика без изменения кода (в откатываемой транзакции,
tools/get_jit_probe.py): как есть (jit=off наv_form2_sheet_sections) — медиана 278;ALTER FUNCTION ... RESET jit(сервер jit=on) — медиана 262, но среднее 775 (выбросы компиляции JIT); сессияjit=off— 263. JIT не причина регресса GET; риски из design (force_custom_plan, снятие jit=off с построителей) я не применял — код PR не правлю. Гипотеза (не проверена): лишняя цена — ранжирование скелета_sort_rankв полном GET. Решение — за человеком.Шаг 7 (2092 строки после grow) — допишу частью 2.
Файлы:
/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1850/(snap2-1844, snap2-1850, snap2-compare*.txt, eq.txt, getupd-.txt, jit-probe.txt, api--co.log); прогоныperf/results/n-p1844-co,n-p1850-coв worktree perf-bench.🤖 Generated with Claude Code
Ночной замер — часть 2 (итог)
Сборки как в части 1 («до» — 1844
f0cac30, «после» —b5a245e). Добавлено: уточнение шага 5 (GET) и шаг 7 (послеgen.grow).Шаг 5: GET листа, +16 %
Лист FORM_2/AHR (form 7, роль rf, 1154 строки), вызов
count(*) FROM v3.v_form_view(7,'AHR',NULL,NULL), одно соединение, 5 прогревов + 20 чередований GET/upd_form_cell(в транзакции с ROLLBACK), после ANALYZE; 2 прогона на сторону (tools/get_vs_upd.py):_sort_rankв полном GET.Шаг 7: после grow (D1, FORM_2/AHR 2092 строки), coauthor rate 1 и 5, 3 повтора
Прогон завершился rc=1 (04:08): 2 из 6 повторов (#1 при rate 1 и rate 5) не стартовали — бот-соавтор вышел с кодом 2, сервер отказал в первых правках с
RaiseError: computed_field: q3.actual_m2 / plan.q1 / seq_dfip.q4 / q3.actual_m1 / seq_ssp.q3 / seq_ssp.q1 (значение синхронизируется из сателлитного листа), HTTP 400: бот выбирает вычисляемые поля. Это дефект выбора ячеек ботом на выращенных данных, не регресс PR. Итог по 4 повторам (по 2 на rate):upd_form_cell, 313 вызововv_form_viewcomputed_field; на D0 было 15–25 %)v_form2_viewна GET листа, 12 вызовов под нагрузкойВердикт по критериям Jira: upd ≤ 50 мс, nested 0, очередь ≥ 0.95 — выполнены (D0 и после grow); GET ≤ +10 % — НЕ выполнен (+15.8 %). Решение — за человеком.
Файлы:
/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1850/(getupd-*.txt, jit-probe.txt, api-1850-grow-co.log),logs/n-p1850-grow-co.log, прогонperf/results/n-p1850-grow-co/sql/coauthor/sql_top.json.Checkout
From your project repository, check out a new branch and test the changes.