feat(agendamento): publicar o atraso do ciclo como métrica e aviso - #31
Merged
Merged
Conversation
Saturação do ciclo era invisível. Acima de mil empresas o excedente escorrega para o ciclo seguinte em silêncio, e quem descobria era o contador reclamando que a nota não apareceu. A métrica é o atraso da empresa mais antiga da fila: há quanto tempo ela já deveria ter sido consultada. Escolhida por não depender de parâmetro nenhum — subir EmpresasPorCiclo zeraria uma contagem de "não enfileiradas", mesmo com o atraso continuando por falta de worker. O valor sai da primeira empresa da seleção, que já vem ordenada pela consulta mais antiga, sem custo de consulta extra. Medidor da biblioteca padrão, não OpenTelemetry: emitir não exige dependência, só consumir exige. Instrumenta hoje e liga o coletor quando houver — e o Polly já publica no medidor dele desde a nova tentativa do object storage. Os medidores leem de campo em memória porque o valor só muda quando o ciclo roda, de trinta em trinta minutos, e consultar o banco no retorno de chamada faria uma consulta a cada raspagem. O aviso no log dispara em quarenta e cinco minutos. Acima de um ciclo inteiro de propósito: empresa que atinge o teto de lotes volta para a fila na hora e espera até trinta minutos pelo ciclo seguinte, o que é operação normal — um e alerta que grita à toa é alerta que ninguém lê. Abaixo do prazo prometido para sobrar tempo de reagir. O ciclo passa a enfileirar pelo IBackgroundJobClient, no lugar da API estática do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica não teria teste. O intervalo de sondagem da fila passa a ser declarado em cinco segundos. Herdado do padrão do provedor, acrescentaria ao mesmo atraso que a econtabil.captura.atraso_maximo (segundos) econtabil.captura.empresas_elegiveis econtabil.captura.empresas_enfileiradas O atraso sai da primeira empresa da lista — a seleção já vem ordenada pela consulta mais antiga, então não custa consulta extra ao banco. Interval fixado em 5 s, que era o item solto do relatório. Herdar o padrão do provedor acrescentaria espera ao mesmo atraso que a métrica acompanha. Três decisões que mudei em relação ao que eu tinha te dito O limiar não é 30 minutos, é 45. Eu errei na conta. Empresa que atinge o teto de lotes volta para a fila na hora e espera até um ciclo inteiro — 30 minutos — pelo próximo. Isso é operação normal. Um limiar de 30 dispararia sem nada estar errado, e alerta que grita à toa é alerta que ninguém lê. 45 fica acima do ruído e 15 minutos abaixo do prazo prometido. É configurável. Troquei BackgroundJob estático por IBackgroundJobClient no ciclo de sincronização. Não era escopo, mas o job era impossível de testar sem subir o armazenamento do Hangfire — e é o que a própria biblioteca recomenda. Os outros três jobs ainda usam a API estática; fica como dívida registrada, não mexi neles. A verificação em produção não aconteceu ainda. As três empresas estão agendadas para 03:07 e 03:30 UTC, e agora são 02:48 — nenhuma elegível, que é o estado saudável. O ciclo roda a cada 30 minutos, então o log aparece na virada. Os quatro testes cobrem os caminhos, inclusive lendo a métrica por um teste que só chamasse RegistrarCiclo provariaque o campo foi escrito, não que a métrica sai. E uma coisa que a conta do SLA revelou SemNovidade = 1h: empresa sem novidade só volta a ser consultada uma hora depois. Se uma nota chega logo após a checagem, ela espera até uma hora inteira só para ser detectada — antes de qualquer fila, worker ou processamento. O orçamento de 1 hora já está estourado por política, não por gargalo. A métrica que acabei de entregar mede o atraso da fila, que é a parte que EmpresasPorCiclo e Workers resolvem. Ela não vai acusar esse outro atraso, porque ele não é saturação — é a frequência configurada funcionando como projetada. Para prometer 1 hora com folga, IntervaloSemNovidade teria que cair para 20 ou 30 minutos. O custo disso é direto: dobra ou triplica as consultas por CNPJ, e a cota da SEFAZ é por CNPJ somando todos os sistemas. É exatamente o botão que causou os bloqueios 656 que investigamos. Essa é uma decisão de negócio, não técnica — quanto risco de bloqueio vale um prazo menor. Não mexi em nada. feat(agendamento): publicar o atraso do ciclo como métrica e aviso Saturação do ciclo era invisível. Acima de mil empara o ciclo seguinte em silêncio, e quem descobria era o contador reclamando que a nota não apareceu. A métrica é o atraso da empresa mais antiga da fila: há quanto tempo ela já deveria ter sido consultada. Escolhida por não depender de parâmetro nenhum — subir EmpresasPorCiclo zeraria uma contagem de "não enfileiradas", mesmo com o atraso continuando por falta de worker. O valor sai da primeira empresa da seleção, que já vem ordenada pela consulta mais antiga, sem custo de consulta extra. Medidor da biblioteca padrão, não OpenTelemetry: emitir não exige dependência, só consumir exige. Instrumenta hoje e liga o coletor quando hno medidor dele desde a nova tentativa do object storage. Os medidores leem de campo em memória porque o valor só muda quando o ciclo roda, de trinta em trinta minutos, e consultar o banco no retorno de chamada faria uma consulta a cada rasp O aviso no log dispara em quarenta e cinco minutos. Acima de um ciclo inteiro de propósito: empresa que atinge o teto de lotes volta para a fila na hora e espera até trinta minutos pelo ciclo seguinte, o que é operação normal — um limiar menor gritaria à toa, e alerta que grita à toa é alerta que ninguém lê. Abaixo do prazo prometido para sobrar tempo de reagir. O ciclo passa a enfileirar pelo IBackgroundJobClient, no lugar da API estática do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica O ciclo passa a enfileirar pelo IBackgroundJobCli do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica não teria teste. O intervalo de sondagem da fila passa a ser declado do padrão do provedor, acrescentaria ao mesmo atraso que a métrica acompanha.
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.
Saturação do ciclo era invisível. Acima de mil empresas o excedente escorrega para o ciclo seguinte em silêncio, e quem descobria era o contador reclamando que a nota não apareceu.
A métrica é o atraso da empresa mais antiga da fila: há quanto tempo ela já deveria ter sido consultada. Escolhida por não depender de parâmetro nenhum — subir EmpresasPorCiclo zeraria uma contagem de "não enfileiradas", mesmo com o atraso continuando por falta de worker. O valor sai da primeira empresa da seleção, que já vem ordenada pela consulta mais antiga, sem custo de consulta extra.
Medidor da biblioteca padrão, não OpenTelemetry: emitir não exige dependência, só consumir exige. Instrumenta hoje e liga o coletor quando houver — e o Polly já publica no medidor dele desde a nova tentativa do object storage. Os medidores leem de campo em memória porque o valor só muda quando o ciclo roda, de trinta em trinta minutos, e consultar o banco no retorno de chamada faria uma consulta a cada raspagem.
O aviso no log dispara em quarenta e cinco minutos. Acima de um ciclo inteiro de propósito: empresa que atinge o teto de lotes volta para a fila na hora e espera até trinta minutos pelo ciclo seguinte, o que é operação normal — um e alerta que grita à toa é alerta que ninguém lê. Abaixo do prazo prometido para sobrar tempo de reagir.
O ciclo passa a enfileirar pelo IBackgroundJobClient, no lugar da API estática do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica não teria teste.
O intervalo de sondagem da fila passa a ser declarado em cinco segundos. Herdado do padrão do provedor, acrescentaria ao mesmo atraso que a
econtabil.captura.atraso_maximo (segundos)
econtabil.captura.empresas_elegiveis
econtabil.captura.empresas_enfileiradas
O atraso sai da primeira empresa da lista — a seleção já vem ordenada pela consulta mais antiga, então não custa consulta extra ao banco.
Interval fixado em 5 s, que era o item solto do relatório. Herdar o padrão do provedor acrescentaria espera ao mesmo atraso que a métrica acompanha.
Três decisões que mudei em relação ao que eu tinha te dito
O limiar não é 30 minutos, é 45. Eu errei na conta. Empresa que atinge o teto de lotes volta para a fila na hora e espera até um ciclo inteiro — 30 minutos — pelo próximo. Isso é operação normal. Um limiar de 30 dispararia sem nada estar errado, e alerta que grita à toa é alerta que ninguém lê. 45 fica acima do ruído e 15 minutos abaixo do prazo prometido. É configurável.
Troquei BackgroundJob estático por IBackgroundJobClient no ciclo de sincronização. Não era escopo, mas o job era impossível de testar sem subir o armazenamento do Hangfire — e é o que a própria biblioteca recomenda. Os outros três jobs ainda usam a API estática; fica como dívida registrada, não mexi neles.
A verificação em produção não aconteceu ainda. As três empresas estão agendadas para 03:07 e 03:30 UTC, e agora são 02:48 — nenhuma elegível, que é o estado saudável. O ciclo roda a cada 30 minutos, então o log aparece na virada. Os quatro testes cobrem os caminhos, inclusive lendo a métrica por um teste que só chamasse RegistrarCiclo provariaque o campo foi escrito, não que a métrica sai.
E uma coisa que a conta do SLA revelou
SemNovidade = 1h: empresa sem novidade só volta a ser consultada uma hora depois. Se uma nota chega logo após a checagem, ela espera até uma hora inteira só para ser detectada — antes de qualquer fila, worker ou processamento. O orçamento de 1 hora já está estourado por política, não por gargalo.
A métrica que acabei de entregar mede o atraso da fila, que é a parte que EmpresasPorCiclo e Workers resolvem. Ela não vai acusar esse outro atraso, porque ele não é saturação — é a frequência configurada funcionando como projetada.
Para prometer 1 hora com folga, IntervaloSemNovidade teria que cair para 20 ou 30 minutos. O custo disso é direto: dobra ou triplica as consultas por CNPJ, e a cota da SEFAZ é por CNPJ somando todos os sistemas. É exatamente o botão que causou os bloqueios 656 que investigamos.
Essa é uma decisão de negócio, não técnica — quanto risco de bloqueio vale um prazo menor. Não mexi em nada.
feat(agendamento): publicar o atraso do ciclo como métrica e aviso
Saturação do ciclo era invisível. Acima de mil empara o ciclo seguinte em silêncio, e quem descobria era o contador reclamando que a nota não apareceu.
A métrica é o atraso da empresa mais antiga da fila: há quanto tempo ela já deveria ter sido consultada. Escolhida por não depender de parâmetro nenhum — subir EmpresasPorCiclo zeraria uma contagem de "não enfileiradas", mesmo com o atraso continuando por falta de worker. O valor sai da primeira empresa da seleção, que já vem ordenada pela consulta mais antiga, sem custo de consulta extra.
Medidor da biblioteca padrão, não OpenTelemetry: emitir não exige dependência, só consumir exige. Instrumenta hoje e liga o coletor quando hno medidor dele desde a nova tentativa do object storage. Os medidores leem de campo em memória porque o valor só muda quando o ciclo roda, de trinta em trinta minutos, e consultar o banco no retorno de chamada faria uma consulta a cada rasp
O aviso no log dispara em quarenta e cinco minutos. Acima de um ciclo inteiro de propósito: empresa que atinge o teto de lotes volta para a fila na hora e espera até trinta minutos pelo ciclo seguinte, o que é operação normal — um limiar menor gritaria à toa, e alerta que grita à toa é alerta que ninguém lê. Abaixo do prazo prometido para sobrar tempo de reagir.
O ciclo passa a enfileirar pelo IBackgroundJobClient, no lugar da API estática do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica
O ciclo passa a enfileirar pelo IBackgroundJobCli do Hangfire. É o que a própria biblioteca recomenda e é o que permite exercitar o ciclo sem subir o armazenamento de trabalhos — sem isso, a métrica não teria teste.
O intervalo de sondagem da fila passa a ser declado do padrão do provedor, acrescentaria ao mesmo atraso que a métrica acompanha.