bug(#254): POST /custom-pois возвращает 201 но row не persisted в DB (missing commit?) #261

Closed
opened 2026-05-17 06:58:18 +00:00 by lekss361 · 1 comment
Owner

Симптом

После deploy PR #257 (merge 8cc9447) — post-deploy smoke:

$ curl -X POST https://gendsgn.ru/api/v1/custom-pois \
    -H "X-Session-Id: smoke-test-001" \
    -H "Content-Type: application/json" \
    -d '{"name":"Smoke test POI","weight":2.0,"lon":60.597,"lat":56.838,"notes":"deploy verify"}'

HTTP/1.1 201 Created
X-Session-Id: smoke-test-001
{"id":1,"user_id":"smoke-test-001","parcel_cad":null,"name":"Smoke test POI",
 "category":null,"weight":2.0,"lon":60.597,"lat":56.838,"notes":"deploy verify",
 "created_at":"2026-05-17T06:51:59.688099Z","updated_at":"2026-05-17T06:51:59.688099Z"}

Через 5 минут:

SELECT * FROM user_custom_pois;
-- (0 rows)

И:

$ curl https://gendsgn.ru/api/v1/custom-pois?user_id=smoke-test-001 -H "X-Session-Id: smoke-test-001"
[]

$ curl -X PATCH https://gendsgn.ru/api/v1/custom-pois/1 -H "X-Session-Id: smoke-test-001" -d '{"weight":3.5}'
HTTP 404 {"detail":"Custom POI not found"}

Root cause hypothesis

backend/app/services/site_finder/custom_pois.py create_custom_poi — скорее всего отсутствует db.commit() после db.execute(INSERT ... RETURNING ...). SQLAlchemy session возвращает RETURNING row из in-flight transaction (отсюда id=1 в response), но при HTTP response close — transaction откатывается потому что не было explicit commit.

Аналогично для update_custom_poi, delete_custom_poi.

Fix

В backend/app/services/site_finder/custom_pois.py:

  • После INSERT: db.commit() → потом return result
  • После UPDATE: db.commit()
  • После DELETE: db.commit()

ИЛИ register dependency что использует with db.begin(): context. См. pattern в weight_profiles.py create_profile.

Дополнительно

backend/app/api/v1/custom_pois.py endpoints могут использовать Depends(get_db) который возвращает Session (не SessionLocal() + begin()). Если get_db имеет yield-based context который коммитит при finally — нужно проверить почему НЕ работает.

Проверить:

  1. Реальный код create_custom_poi в service
  2. Транзакционная модель get_db в core/db.py
  3. Tests в test_custom_pois.py — они проходили потому что использовали db.flush() + проверка через тот же session (без real commit)

Acceptance

  • POST /custom-pois → row реально в DB после request close
  • GET возвращает созданные POI
  • PATCH/DELETE работают на real rows
  • Tests дополнить assertion с fresh session (через db.commit() + reopen)

Severity

🔴 P0 — фича из PR #257 не работает (нет persistence). Frontend PR #258 тоже не сможет работать pока этот не fixed.

Workaround

До fix — ничего нельзя сохранить через UI. Frontend useAddCustomPoi мутация будет возвращать 201, optimistic update сразу invalidate, но GET вернёт пусто → marker disappear immediately.

(QA discovery 2026-05-17 06:52 UTC, post-deploy verify PR #257)

## Симптом После deploy PR #257 (merge `8cc9447`) — post-deploy smoke: ```bash $ curl -X POST https://gendsgn.ru/api/v1/custom-pois \ -H "X-Session-Id: smoke-test-001" \ -H "Content-Type: application/json" \ -d '{"name":"Smoke test POI","weight":2.0,"lon":60.597,"lat":56.838,"notes":"deploy verify"}' HTTP/1.1 201 Created X-Session-Id: smoke-test-001 {"id":1,"user_id":"smoke-test-001","parcel_cad":null,"name":"Smoke test POI", "category":null,"weight":2.0,"lon":60.597,"lat":56.838,"notes":"deploy verify", "created_at":"2026-05-17T06:51:59.688099Z","updated_at":"2026-05-17T06:51:59.688099Z"} ``` Через 5 минут: ```sql SELECT * FROM user_custom_pois; -- (0 rows) ``` И: ```bash $ curl https://gendsgn.ru/api/v1/custom-pois?user_id=smoke-test-001 -H "X-Session-Id: smoke-test-001" [] $ curl -X PATCH https://gendsgn.ru/api/v1/custom-pois/1 -H "X-Session-Id: smoke-test-001" -d '{"weight":3.5}' HTTP 404 {"detail":"Custom POI not found"} ``` ## Root cause hypothesis `backend/app/services/site_finder/custom_pois.py` `create_custom_poi` — скорее всего отсутствует `db.commit()` после `db.execute(INSERT ... RETURNING ...)`. SQLAlchemy session возвращает RETURNING row из in-flight transaction (отсюда `id=1` в response), но при HTTP response close — transaction откатывается потому что не было explicit commit. Аналогично для `update_custom_poi`, `delete_custom_poi`. ## Fix В `backend/app/services/site_finder/custom_pois.py`: - После INSERT: `db.commit()` → потом return result - После UPDATE: `db.commit()` - После DELETE: `db.commit()` ИЛИ register dependency что использует `with db.begin():` context. См. pattern в `weight_profiles.py` create_profile. ## Дополнительно `backend/app/api/v1/custom_pois.py` endpoints могут использовать `Depends(get_db)` который возвращает `Session` (не `SessionLocal()` + `begin()`). Если `get_db` имеет yield-based context который коммитит при finally — нужно проверить почему НЕ работает. Проверить: 1. Реальный код `create_custom_poi` в service 2. Транзакционная модель `get_db` в `core/db.py` 3. Tests в `test_custom_pois.py` — они проходили потому что использовали `db.flush()` + проверка через тот же session (без real commit) ## Acceptance - [ ] `POST /custom-pois` → row реально в DB после request close - [ ] GET возвращает созданные POI - [ ] PATCH/DELETE работают на real rows - [ ] Tests дополнить assertion с **fresh** session (через `db.commit()` + reopen) ## Severity 🔴 **P0** — фича из PR #257 не работает (нет persistence). Frontend PR #258 тоже не сможет работать pока этот не fixed. ## Workaround До fix — ничего нельзя сохранить через UI. Frontend `useAddCustomPoi` мутация будет возвращать 201, optimistic update сразу invalidate, но GET вернёт пусто → marker disappear immediately. (QA discovery 2026-05-17 06:52 UTC, post-deploy verify PR #257)
Author
Owner

Re-verify 2026-05-17 07:19 UTC — НЕ воспроизводится.

POST /api/v1/custom-pois → 201 {"id":5,...}
GET /api/v1/custom-pois → [{"id":5,...}]
SELECT * FROM user_custom_pois → 1 row (id=5)

Pencil-check custom_pois.py:132db.commit() присутствует во всех 3 mutations (create/update/delete). См. PR #262 (regression tests).

Гипотеза первого симптома: мой first smoke POST id=1 совпал по времени с deploy PR #258 (frontend) ~06:50 UTC — возможно container restart прервал транзакцию между INSERT и commit, либо PR #257 deploy не успел применить миграцию полностью до того как PR #258 запустился. После того как оба deploys устаканились — всё работает.

Закрываю как not reproducible, оставляю PR #262 (regression tests добавлены, полезны для будущего).

**Re-verify 2026-05-17 07:19 UTC — НЕ воспроизводится.** ``` POST /api/v1/custom-pois → 201 {"id":5,...} GET /api/v1/custom-pois → [{"id":5,...}] SELECT * FROM user_custom_pois → 1 row (id=5) ``` Pencil-check `custom_pois.py:132` — `db.commit()` **присутствует** во всех 3 mutations (create/update/delete). См. PR #262 (regression tests). **Гипотеза первого симптома:** мой first smoke POST `id=1` совпал по времени с deploy PR #258 (frontend) ~06:50 UTC — возможно container restart прервал транзакцию между INSERT и commit, либо PR #257 deploy не успел применить миграцию полностью до того как PR #258 запустился. После того как оба deploys устаканились — всё работает. Закрываю как **not reproducible**, оставляю PR #262 (regression tests добавлены, полезны для будущего).
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#261
No description provided.