Проблема
PdoPaymentAttemptStore (#604) пишет через соединение MODX, а modX открывает $modx->pdo с PDO::ERRMODE_SILENT (core/src/Revolution/modX.php перекрывает driver_options). Хранилище рассчитывает на исключения и результат execute() не проверяет:
create() — $stmt->execute([...]) без проверки;
update() — $stmt->execute($params) без проверки;
fetchOne() — то же.
Исключение ловится только в recordEvent().
Проверено на dev (MariaDB 10.6.23, beta ac8e267e, sql_mode = STRICT_TRANS_TABLES,…) вызовами самого хранилища на $modx->pdo:
PDO ERRMODE: 0 (SILENT)
created attempt #1 status=new currency=RUB
update(status=paid, currency=40 символов) → вернул status=new currency=RUB
строка в БД: {"status":"new","currency":"RUB"}
update() завершился «успешно», вернул прежнюю строку, в журнал ничего не попало. У create() при ошибке будет RuntimeException('Failed to load created payment attempt') — отказ есть, но текст скрывает причину.
Последствие
В PaymentLifecycleService::commit() попытка обновляется через writeWithEvent(), затем вызывается syncOrderStatus(). Если update() молча не прошёл, событие будет записано как обработанное, попытка останется в прежнем статусе, а статус заказа всё равно сменится. Вероятность низкая — вебхук пишет короткие поля (status, refunded_amount, refund_external_id, refundedon), — но расхождение не будет видно ни в журнале, ни в ответе.
Что сделать
В PdoShipmentStore::executeWrite() уже есть нужный образец: проверяется результат execute(), разбирается errorInfo(), дубль отличается от прочих ошибок, остальное бросается наружу.
- Применить тот же приём в
create(), update(), fetchOne().
create(): при нарушении уникальности — понятное исключение или возврат существующей попытки; при прочих ошибках — исключение с errorInfo.
- Тест хранилища на соединении с
ERRMODE_SILENT, как у MODX.
Критерии приёмки
Контекст
Проблема
PdoPaymentAttemptStore(#604) пишет через соединение MODX, аmodXоткрывает$modx->pdoсPDO::ERRMODE_SILENT(core/src/Revolution/modX.phpперекрываетdriver_options). Хранилище рассчитывает на исключения и результатexecute()не проверяет:create()—$stmt->execute([...])без проверки;update()—$stmt->execute($params)без проверки;fetchOne()— то же.Исключение ловится только в
recordEvent().Проверено на dev (MariaDB 10.6.23,
betaac8e267e,sql_mode = STRICT_TRANS_TABLES,…) вызовами самого хранилища на$modx->pdo:update()завершился «успешно», вернул прежнюю строку, в журнал ничего не попало. Уcreate()при ошибке будетRuntimeException('Failed to load created payment attempt')— отказ есть, но текст скрывает причину.Последствие
В
PaymentLifecycleService::commit()попытка обновляется черезwriteWithEvent(), затем вызываетсяsyncOrderStatus(). Еслиupdate()молча не прошёл, событие будет записано как обработанное, попытка останется в прежнем статусе, а статус заказа всё равно сменится. Вероятность низкая — вебхук пишет короткие поля (status,refunded_amount,refund_external_id,refundedon), — но расхождение не будет видно ни в журнале, ни в ответе.Что сделать
В
PdoShipmentStore::executeWrite()уже есть нужный образец: проверяется результатexecute(), разбираетсяerrorInfo(), дубль отличается от прочих ошибок, остальное бросается наружу.create(),update(),fetchOne().create(): при нарушении уникальности — понятное исключение или возврат существующей попытки; при прочих ошибках — исключение сerrorInfo.ERRMODE_SILENT, как у MODX.Критерии приёмки
update()не проглатываетсяcreate()различает дубль и прочие ошибкиERRMODE_SILENTКонтекст
PdoShipmentStore, исправлен черезexecuteWrite()