feat(infra): nova tentativa no object storage para não queimar cota d… - #29
Merged
Merged
Conversation
…a SEFAZ Falha ao arquivar aborta o lote inteiro, o ponteiro de NSU não avança, e a rodada seguinte busca os mesmos documentos na SEFAZ de novo. A consulta é o recurso racionado; a gravação no MinIO não custa nada. Um soluço de rede de meio segundo custava uma ida à SEFAZ. O pipeline repete até três vezes, com espera exponencial e jitter, e limita cada tentativa em 30 segundos. O jitter importa porque a sincronização roda em paralelo por empresa: sem ele, as que falharem juntas voltariam juntas e a segunda tentativa recriaria a rajada. Sem disjuntor, de propósito. Ele seria por processo e em memória, enquanto o que precisa ser contido já é contido no lugar certo: o bloqueio por empresa vive no banco, sobrevive a reinício e vale para todas as instâncias. Um disjuntor sobre "o MinIO" ainda pararia a captura de todas as empresas por causa de uma, sem nada em troca — se o storage caiu de vez, o job já falha rápido e o ciclo seguinte retoma. Pela mesma razão nada foi acrescentado à SEFAZ: 656 não é falha transitória, e repetir aprofunda o bloqueio. Classificação por lista de permissão Quase toda exceção do SDK herda de MinioException, inclusive ObjectNotFoundException, AccessDeniedException e InvalidBucketNameException. Um Handle<MinioException> genérico repetiria arquivo inexistente e credencial errada três vezes para chegar ao mesmo lugar. Repete-se apenas o que se sabe transitório; o resto é definitivo. A lista de permissão também envelhece melhor: exceção nova do SDK entra como definitiva, que é o padrão seguro. Um stream por tentativa O MemoryStream é criado dentro do pipeline. Reaproveitá-lo faria a segunda tentativa encontrá-lo no fim e gravar um objeto de zero byte — sem erro nenhum, porque do ponto de vista do SDK o envio deu certo, e o XML sumiria em silêncio. Repetir é seguro porque a operação é idempotente: o mesmo nome com o mesmo conteúdo produz o mesmo objeto, e o XML autorizado nunca muda.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…a SEFAZ
Falha ao arquivar aborta o lote inteiro, o ponteiro de NSU não avança, e a rodada seguinte busca os mesmos documentos na SEFAZ de novo. A consulta é o recurso racionado; a gravação no MinIO não custa nada. Um soluço de rede de meio segundo custava uma ida à SEFAZ.
O pipeline repete até três vezes, com espera exponencial e jitter, e limita cada tentativa em 30 segundos. O jitter importa porque a sincronização roda em paralelo por empresa: sem ele, as que falharem juntas voltariam juntas e a segunda tentativa recriaria a rajada.
Sem disjuntor, de propósito. Ele seria por processo e em memória, enquanto o que precisa ser contido já é contido no lugar certo: o bloqueio por empresa vive no banco, sobrevive a reinício e vale para todas as instâncias. Um disjuntor sobre "o MinIO" ainda pararia a captura de todas as empresas por causa de uma, sem nada em troca — se o storage caiu de vez, o job já falha rápido e o ciclo seguinte retoma. Pela mesma razão nada foi acrescentado à SEFAZ: 656 não é falha transitória, e repetir aprofunda o bloqueio.
Classificação por lista de permissão
Quase toda exceção do SDK herda de MinioException, inclusive ObjectNotFoundException, AccessDeniedException e InvalidBucketNameException. Um Handle genérico repetiria arquivo inexistente e credencial errada três vezes para chegar ao mesmo lugar. Repete-se apenas o que se sabe transitório; o resto é definitivo. A lista de permissão também envelhece melhor: exceção nova do SDK entra como definitiva, que é o padrão seguro.
Um stream por tentativa
O MemoryStream é criado dentro do pipeline. Reaproveitá-lo faria a segunda tentativa encontrá-lo no fim e gravar um objeto de zero byte — sem erro nenhum, porque do ponto de vista do SDK o envio deu certo, e o XML sumiria em silêncio. Repetir é seguro porque a operação é idempotente: o mesmo nome com o mesmo conteúdo produz o mesmo objeto, e o XML autorizado nunca muda.