ExposedTransactionRunner: Exposed's default 3x retry re-runs claim+delivery on SQLException, multiplying duplicate deliveries

Aberta
#134 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
3/5
Tempo estimado
Meio dia
Facilidade para iniciantes
62/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
kotlin
Domínio
backend, databases

Direção de pesquisa

Start with ExposedTransactionRunner.runInTransaction in the okapi-exposed module, which wraps the block in Exposed's transaction(database), and with processNext() to see the claim, deliver, update sequence. Check how Exposed's DatabaseConfig retry setting reaches that call. Done when a test shows the deliverer is invoked once when the store update throws SQLException, and the existing tests still pass.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

bug

Severity: Medium (duplicate delivery amplification) · Area: okapi-exposed ExposedTransactionRunner · Found in: code review of main @ e5630a1

Problem

ExposedTransactionRunner.runInTransaction is transaction(database) { block() }. Exposed retries the entire block on SQLException up to DatabaseConfig.defaultMaxAttempts times. The default is 3, which I confirmed in the bytecode of exposed-core 1.6.0.

For the outbox scheduler the block is processNext(): claim → network delivery → update. If the update or commit fails with an SQLException (deadlock victim, serialization failure, connection reset, oversized last_error, see the related issue), Exposed rolls back and re-runs the whole cycle immediately. It re-claims the same rows and delivers them again, up to 3 times per tick, with no backoff. The delivery side effect isn't transactional, so these retries only add duplicates and load on the downstream.

The purger and the metrics reads are idempotent, so retries are harmless there. The processor path is the problem.

Suggested fix

Disable Exposed's automatic retry for okapi's runner, e.g. transaction(database) { maxAttempts = 1; block() } (or the equivalent DatabaseConfig), and let okapi's own scheduler retry on the next tick. Add a test asserting that a deliverer is invoked once when the store update throws SQLException.

Linguagem predominante
Kotlin
Estrelas
14
Forks
0
Merge médio
9h 54min
PRs com merge (30d)
11

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de softwaremill/okapi

Todas as issues de softwaremill/okapi

Issues semelhantes

Mais issues de Kotlin

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.