Instalação e operação¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-21
Provisionar uma instalação nova (lado X-Adm — antes de ir ao cliente)¶
- Par de chaves da instalação (a privada é a credencial do cliente):
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out <cliente>-private.pem openssl rsa -in <cliente>-private.pem -pubout -out <cliente>-public.pem - Registrar a pública no PowerSync do cliente: converter para JWK (modulus base64url) e
colocar inline em
client_auth.jwks.keysdopowersync.yaml(repo powersync do cliente), comkidnovo (ex.:<cliente>-ps-v1) eaudiencedo cliente; rebuild + redeploy da imagem (config assada). - Token de write-back: o
INTEGRADOR_API_TOKENda instância do Integrador do cliente (env no Coolify) — é o que vai empowersync.upload.token. O mesmo token autentica o heartbeat. - Montar o pacote:
dist/com o fat jar (./gradlew shadowJar), ointegrador-client.propertiespreenchido (URLs,jwt.kid/issuer/audience/subjectcasando com o passo 2, caminhos do ZIM reais,cliente=<slug>para a observabilidade) e o<cliente>-private.pem. - Validar antes de entregar: rodar
--debugapontando para a instância real — conectar,[r]listar pendentes; processar só com aval do cliente (grava status na nuvem). O programapAbastprecisa estar instalado no ZIM (contrato).
Requisitos¶
- Máquina do ERP (Windows x64) com Java 8 ou superior (
java -version). - ERP X-Adm instalado, com o programa ZIM
pAbastdesta integração (contrato). - Acesso HTTPS de saída para
ps.<cliente>.xadm.bizeint.<cliente>.xadm.biz— só isso: o heartbeat usa o mesmoint.<cliente>do write-back, sem liberação nova de firewall.
Instalar¶
- Crie uma pasta (ex.:
C:\integrador-client) e coloque nela os arquivos entregues: integrador-client-<versão>.jarintegrador-client.properties(a partir dointegrador-client.properties.exemplo)<cliente>-private.pem— credencial da instalação; não copiar, não enviarrodar.bat- Preencha o
integrador-client.properties(o exemplo documenta cada chave; as principais: URLs da nuvem, token de upload, caminho dozimrtmu.exee da pasta do X-Adm).
Caminhos com espaços são aceitos. Use /, não coloque aspas e mantenha cada
propriedade em sua própria linha, por exemplo:
zim.executavel=C:/Program Files (x86)/Zim/7.11/zimrtmu.exe
zim.diretorio=D:/XADM/XADMUSR/xadmXApiMDFe1
java -jar integrador-client-<versão>.jar --version deve imprimir a versão.
4. Inicie com rodar.bat. A primeira linha do log é a versão; em seguida o programa
conecta, sincroniza e passa a processar pendentes a cada ciclo.
5. Para iniciar junto com o Windows: agende o rodar.bat no Agendador de Tarefas
("Ao iniciar o computador", conta local, "Executar estando o usuário conectado ou não").
Modo debug (homologação com a equipe ZIM)¶
java -jar integrador-client-<versão>.jar --debug
Nada roda sozinho: o operador comanda pelo console o que processar —
[i]tem (1 registro = 1 linha no arquivo de envio), [p]edido (o próximo contrato pendente
com cliente/fones/produtos/itens num arquivo só), [t]udo (um ciclo normal),
[r]ecarregar a lista de pendentes, [s]air. Cada comando gera o arquivo de envio, roda o
pAbast e mostra no console as linhas do envio e do retorno entre |pipes| (padding
visível) + o resultado; ao final, a lista de pendentes é recarregada sozinha. No debug os
arquivos dXpEnvio/dXpRetorno ficam no disco (na pasta do X-Adm) para inspeção, com a
máscara do layout anexada ao final e as versões dXpEnvio.json/dXpRetorno.json
(pretty print) ao lado — o próximo processamento apaga e reescreve; no modo normal os
arquivos são apagados após aplicar.
A sincronização com a nuvem continua normal em segundo plano.
Acompanhar¶
- Logs em
logs\integrador-client.log(o dia corrente); ao virar o dia, o anterior é zipado comologs\anomesdia.integrador-client.log.zip(30 dias guardados). - Linha de sucesso de um lote:
lote aplicado: N gravado(s), …seguida doswrite-back … aceito. - Saída do próprio ZIM:
pAbast-saida.logna pasta do X-Adm (sobrescrito a cada lote). Quando o lote falha, as últimas linhas dela vão também para o log do cliente (saída do pAbast …). - Sinal de vida:
heartbeat enviado (inicio)na largada eheartbeat enviado (periodico)a cada hora. A instalação aparece sozinha na aba Deploy do central-ui, com a versão e os fluxos.
Heartbeat (sinal de vida)¶
Na largada e a cada intervalo o programa avisa a plataforma que está vivo: versão, fluxos ativos e nome da máquina. O central acompanha e alerta quando uma instalação passa de 6 horas úteis sem sinal (runbook do central). Não há nada obrigatório a configurar; as duas chaves são opcionais:
| Chave | Padrão | O que faz |
|---|---|---|
heartbeat.url |
o powersync.upload.url com o caminho /api/v1/heartbeat |
endereço do heartbeat; URL malformada para na largada (exit 2) |
heartbeat.intervaloMinutos |
60 |
minutos entre heartbeats; 0 desliga (inclusive o da largada); negativo para na largada |
O heartbeat nunca derruba o programa: qualquer falha só vira WARN no log. O --debug não manda
heartbeat. O contrato é do integrador-server:
heartbeat.md.
Encerrar / reiniciar¶
Fechar a janela (ou finalizar o processo java.exe) é seguro em qualquer momento: lote em
andamento volta a pendente sozinho na próxima subida (recuperação automática), e a fila de
write-back fica guardada no banco local — nada se perde.
Exit codes¶
Seguem a taxonomia da casa (contrato canônico):
| Exit | Significado no integrador-client |
|---|---|
| 0 | encerramento normal (interrupção pedida) |
| 1 | falha inesperada no daemon (ver log) |
| 2 | configuração/ambiente inválido — properties com chave faltando/errada ou JVM 32 bits (a extensão nativa do PowerSync não carrega; rode com Java 64 bits). A mensagem diz qual dos dois |
| 4 | ocupado: outra instância já roda nesta pasta de dados (lock); nada foi feito, seguro tentar depois |
(3 = erro externo não é usado: falha de rede/nuvem não derruba o daemon — o SDK retenta sozinho.)
Problemas comuns¶
| Sintoma | Causa provável | O que fazer |
|---|---|---|
| Sai na hora com "erro de configuração: chave …" (exit 2) | properties incompleto ou caminho errado | corrigir a chave citada na mensagem |
| Sai na hora com "Necessário Java 64 bits …" (exit 2) | rodou com o java 32 bits do PATH |
apontar pra uma JRE 64 bits (o PowerSync só carrega em 64 bits) |
pAbast não terminou em Ns — matando o processo |
falta de licença ZIM ou ZIM travado | nada — o lote tenta de novo sozinho; se persistir, liberar licença |
pAbast terminou com exit code N |
falha geral do ZIM | ver pAbast-saida.log na pasta do X-Adm |
retorno inválido — lote volta a pendente |
pAbast escreveu retorno fora do contrato | conferir o contrato §4 |
retorno do pAbast com N linha(s) de tentativa abortada … descartadas |
o ZIM deu conflito, recomeçou o lote e não limpou o dXpRetorno |
nada — o cliente aproveitou a rodada final e aplicou o lote normalmente; é defeito do ZIM a corrigir (contrato §4 e §8) |
retorno do pAbast ecoou a linha de continuação 'IMPORTA_PIED' como registro — descartada |
o ZIM deu conflito e respondeu também à linha de continuação | nada — os 999 foram aplicados e o lote retenta sozinho; é defeito do ZIM a corrigir (contrato §4 e §8) |
pAbast falhou depois do handshake … Conferir no ERP: … |
o ZIM caiu no meio do lote (exit ≠ 0, travou ou retorno fora do contrato) e pode ter gravado parte | o lote é reenviado sozinho; conferir no ERP os registros citados (cadastro duplicado, item sem pedido). O dXpRetorno e a saída do ZIM estão no log logo acima |
write-back … HTTP 4xx/5xx repetido |
token errado ou nuvem fora | conferir powersync.upload.token; a fila re-tenta sozinha |
heartbeat recusado: HTTP 401 |
token errado (é o mesmo do write-back) | conferir powersync.upload.token |
heartbeat recusado: HTTP 404 |
o integrador-server do cliente ainda não tem a rota do heartbeat (versão antiga) | atualizar o integrador-server do cliente; o programa segue normal enquanto isso |
heartbeat recusado: HTTP 502 |
o integrador-server não conseguiu repassar ao central (central fora, ou o central recusou) | transitório se passar sozinho; se repetir, ver o log do integrador-server (heartbeat_recusado = config errada lá) |
heartbeat recusado: HTTP 503 |
falta CLIENTE_ID ou CENTRAL_API_TOKEN no integrador-server do cliente |
configurar as envs no Coolify do integrador-server |
heartbeat não entregue: … |
rede ou integrador-server fora do ar | nada — o próximo heartbeat tenta de novo |
401 ao conectar no PowerSync |
chave PEM/kid/audience não batem com a instância | conferir chaves jwt.* e o .pem |
Registro parado em 1XX |
erro de dado (terminal) | corrigir o dado na origem (nuvem); o registro não é retentado |
Erros de configuração (exit 2) ficam no console e em logs/integrador-client.log, com a
chave e o caminho a corrigir. Eles não abrem incidente no GlitchTip/Sentry porque exigem
correção local da instalação, não investigação de falha do aplicativo.
O que vai para o GlitchTip¶
O programa roda na máquina do cliente, então o que chega ao GlitchTip (bug.xadm.biz, projeto
integrador-client) é o que dá para diagnosticar de longe. Filtre por cliente:<slug> — o slug é
a chave cliente do .properties.
| Vira incidente | Não vira |
|---|---|
todo WARN e ERROR do programa, com a exceção anexada quando há |
erro de configuração e JVM de 32 bits (ação do operador, não falha do app) |
| remessa travada ou retida, uma vez por causa | conflito de concorrência no dRels3 — o lote retenta sozinho |
| erro terminal no encerramento de MDF-e | o eco do dXpEnvio/dXpRetorno, que viaja dentro do incidente |
Cada incidente carrega junto: as linhas cruas do dXpEnvio e do dXpRetorno do lote (em
blocos, entre |pipes|, como no log local), os marcos do ciclo, e a configuração com que o
processo subiu — com powersync.upload.token e a chave privada mascarados, como no log.
As linhas cruas levam dado de cliente
O layout do pAbast tem cgc_cpf, nome_prop e fantasia: CPF/CNPJ e nome aparecem no
incidente. É decisão consciente — o GlitchTip é hospedado na infraestrutura da X-Adm, não em
serviço de terceiro, e o evento é descartado pela retenção de 90 dias. Quem lê o projeto
é quem já tem acesso ao GlitchTip da casa.
Desligar o envio¶
Suba o programa com a variável de ambiente SENTRY_DSN vazia:
set SENTRY_DSN=
java -jar integrador-client-<versão>.jar
A variável, quando definida, vence o app.json embarcado no jar — vazia desliga, preenchida
manda para o projeto que ela apontar. É assim que o e2e local e o desenvolvimento rodam sem sujar
o painel de produção. Sem a variável definida, vale o DSN do jar.
Para conferir o caminho até o GlitchTip numa instalação nova:
java -jar integrador-client-<versão>.jar --sentry-teste
O evento de teste sai com environment=smoke e cliente=smoke — não se mistura com incidente de
cliente real.
Atualizar versão¶
Parar o programa, trocar o jar pelo novo (mesma pasta), iniciar de novo. O banco local e o properties são preservados.
Ao passar para a primeira versão com heartbeat, o integrador-server do cliente precisa já ter a rota do heartbeat. Na ordem inversa o programa só loga WARN 404 a cada hora, mas o integrador-server registra ERROR a cada chamada autenticada que não acha a rota.