Подтвердить что ты не робот

JPA: шаблон для обработки OptimisticLockException

Каков правильный шаблон для обработки OLE в веб-службе REST? это то, что я делаю сейчас, например,

protected void doDelete(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ...
    ...
    ...

    try {
        try {
            em.getTransaction().begin();
            // ... remove the entity
            em.getTransaction().commit();
        } catch (RollbackException e) {
            if (e.getCause() instanceof OptimisticLockException) {
                try {
                    CLog.e("optimistic lock exception, waiting to retry ...");
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
                doDelete(request, response);
                return;
            }
        }

        // ... write response

    } catch (NoResultException e) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
        return;
    } finally {
        em.close();
    }
}

В любое время, когда вы видите сон в коде, есть вероятность, что это неверно. есть ли лучший способ справиться с этим?

другой подход заключался бы в немедленной отправке отказа клиенту, но я бы предпочел не беспокоиться об этом. правильная вещь, кажется, делает все, что требуется, чтобы сделать запрос успешным на сервере, даже если это занимает некоторое время.

спасибо.

4b9b3361

Ответ 1

Если вы получаете оптимистичное исключение блокировки, это означает, что некоторые другие транзакции имеют зафиксированные изменения для объектов, которые вы пытались обновить/удалить. Поскольку другая транзакция совершена, повторная попытка немедленно может иметь хорошие шансы на успех.

Я также сделаю метод неудачным после попыток N, а не ожидая возникновения StackOverflowException.

Ответ 2

"Политически правильный" ответ в покое заключается в возврате HTTP 409 (Conflict), который отлично сочетается с идеей оптимистической блокировки. Ваш клиент должен управлять им, возможно, через несколько секунд спустя.

Я бы не добавил логику, чтобы повторить попытку в вашем приложении, так как ваш клиент уже будет обрабатывать ситуации, когда вы возвращаете 40X-код.

Ответ 3

Если вы собираетесь продолжать повторную попытку до тех пор, пока она не будет работать, почему бы не отключить оптимистичную блокировку? Вы должны позволить вызывающему абоненту знать, что они приняли решение, основанное на устаревшей информации! Если вы контролируете обе стороны, может быть возвращен соответствующий код 400. Если это публично, может быть более дружелюбным к произвольным клиентам, чтобы просто вернуть 500. (Конечно, тогда вы увековечиваете недоиспользование соответствующих кодов ответа! Такая дилемма)

Ответ 4

Кстати, catch (InterruptedException e) {} всегда плохая идея, потому что система попросила ваше вычисление отменить, и вы игнорируете его. В контексте веб-службы, InterruptedException будет еще одной веской причиной для сообщения об ошибке клиенту.