Skip to content

Implementar Optimistic Locking dentro de contexto transacional #19

@wallanpsantos

Description

@wallanpsantos

Título: Fix optimistic locking - ensure transactional context
Labels: critical, concurrency, locking
Prioridade: CRÍTICA

Problema Atual (Ponto 3 do Feedback):

  • Locking otimista aplicado sem contexto transacional
  • Risco de lost updates sem rollback

Solução Proposta:

// DataProvider - Locking dentro de transação
@Repository
@Transactional
public class OptimisticLockingWalletRepository implements WalletRepository {
    
    @Transactional
    @Retryable(value = {OptimisticLockingFailureException.class}, 
               maxAttempts = 3,
               backoff = @Backoff(delay = 100, multiplier = 2))
    @Override
    public Wallet save(Wallet wallet) {
        try {
            WalletEntity entity = walletEntityMapper.toEntity(wallet);
            WalletEntity saved = walletJpaRepository.save(entity); // JPA @Version handling
            return walletEntityMapper.toDomain(saved);
            
        } catch (OptimisticLockingFailureException e) {
            log.warn("Optimistic locking conflict for wallet: {}, attempt: {}", 
                    wallet.getId(), getCurrentAttempt());
            throw e; // Retry automático via @Retryable
        }
    }
    
    @Transactional
    @Override
    public void executeWithOptimisticLocking(String walletId, Function<Wallet, Wallet> operation) {
        // Leitura + atualização versionada dentro da mesma transação
        Wallet wallet = findByIdWithLock(walletId);
        Wallet updated = operation.apply(wallet);
        save(updated); // Vai falhar se versão conflitar
    }
}

// Entity JPA com @Version
@Entity
public class WalletEntity {
    @Version
    private Long version; // JPA gerencia automaticamente
}

Tarefas:

  • Adicionar @Version em WalletEntity

  • Implementar retry automático com @retryable

  • Envolver leituras/atualizações na mesma transação

  • Criar método executeWithOptimisticLocking

  • Configurar Spring Retry

    @Configuration
    @EnableRetry
    public class RetryConfig {
        
        @Bean
        public RetryTemplate retryTemplate() {
            RetryTemplate template = new RetryTemplate();
            
            ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
            backOffPolicy.setInitialInterval(100);
            backOffPolicy.setMultiplier(2.0);
            backOffPolicy.setMaxInterval(2000);
            
            template.setBackOffPolicy(backOffPolicy);
            return template;
        }
    }
  • Testes de race conditions

  • Métricas de conflitos de versão

Metadata

Metadata

Assignees

Labels

architectureAlteração na arquiteturacriticalAlta Prioridade

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions