4.2 KiB
4.2 KiB
Blueprint 10 — Ntfy Notifications
- ID: BP-10
- Feature: Notificações via ntfy sobre sucesso/falha de jobs
- Requisitos: RF-017
- Depende de: BP-05 (Worker Pool)
- Status: concluído
Objetivo
Implementar um cliente HTTP que envia notificações para um servidor ntfy (self-hosted ou público) ao final de cada job, informando se a conversão foi concluída com sucesso ou falhou. Respeitar DRY_RUN.
Contexto
- BP-05 definiu o worker pool com um fluxo de
processque termina chamandofinishJob(statusdoneouerror). O notificador será chamado antes do finish. config.ServiceforneceráNtfyEnabled,NtfyURL,NtfyTopic,NtfyToken.- O padrão segue a mesma abordagem do
Rescanner: interface injetada noworker.Pool, substituível para testes.
Restrições e Convenções
- Sem comentários; erros com
%w; logs comslog.With("job_id", id). - Resiliência: falha ao enviar notificação não deve interromper o pipeline. Logar o erro e seguir.
DRY_RUN=true: não enviar notificação; logar a intenção.- Se
NTFY_ENABLED=falseouNtfyURL/NtfyTopicvazios: pular (log debug). - Token (
NTFY_TOKEN) é opcional; se presente, enviar comoAuthorization: Bearer <token>. - Timeout de 10s no HTTP client.
- Mensagens em inglês.
Design
internal/ntfy/client.go
type Client struct {
cfg *config.Service
hc *http.Client
}
func New(cfg *config.Service) *Client
// Notify envia uma notificação com o resultado do job.
// Implementa worker.Notifier.
func (c *Client) Notify(ctx context.Context, job *models.Job) error
- Endpoint:
POST {NtfyURL}/{NtfyTopic} - Prioridade:
4(high) para erro,3(default) para sucesso. - Tags:
white_check_mark(done),x(error). - Corpo:
json.Marshal(ntfyMessage{...})com title, message, priority, tags. - Header
Authorization: Bearer <NtfyToken>apenas se token != "".
internal/worker/notifier.go
type Notifier interface {
Notify(ctx context.Context, job *models.Job) error
}
type NoopNotifier struct{}
func (NoopNotifier) Notify(ctx context.Context, job *models.Job) error {
return nil
}
Adicionar campo Notifier ao worker.Pool e chamar p.Notifier.Notify(ctx, job) antes de finishJob.
Wiring em cmd/server/main.go
notifier := ntfy.New(cfgSvc)(ouNoopNotifier{}seNtfyEnabled=false).- Passar
notifieraoworker.New(..., notifier).
Config (novas chaves editáveis)
| Key | Default | Descrição |
|---|---|---|
NTFY_ENABLED |
false |
Habilita notificações ntfy |
NTFY_URL |
— | URL base do servidor ntfy |
NTFY_TOPIC |
— | Tópico para publicar |
NTFY_TOKEN |
— | Token de autenticação (opcional) |
Tarefas
- Adicionar
Notifierinterface eminternal/worker/. - Criar
internal/ntfy/client.go(New,Notify). - Adicionar keys ntfy ao
config(Key + validação + editableKeys + Config struct + buildConfig). - Chamar
Notifier.Notifynoworker.processantes definishJob. - Wiring no
main.go:ntfy.New(cfgSvc)→worker.New(...). - Atualizar documentos:
README.md,AGENTS.md,requirements.md,architecture.md.
Testes
internal/ntfy/client_test.go (httptest.Server):
NotifyenviaPOST /<topic>com prioridade/título/tags corretos para job concluído.Notifyenvia prioridadehighe tagxpara job com erro.DRY_RUN=true→ nenhum request é feito.NtfyEnabled=false→ nenhum request, retorna nil.- Token presente → header
Authorization: Bearer <token>. - Timeout/erro de rede → erro logado, não interrompe.
internal/worker/worker_test.go (atualizar):
- Verificar que
Notifierfake é chamado antes dofinishJobtanto em sucesso quanto em erro. - Verificar que
NoopNotifiernão causa efeitos colaterais.
Definição de Pronto
- DoD comum atendido.
go test ./internal/ntfy/... ./internal/worker/...verde.make run-prod: notificações enviadas ao final de cada job (se habilitado).
Arquivos
- Criar:
internal/ntfy/client.go(+_test.go),internal/worker/notifier.go. - Modificar:
internal/config/config.go,internal/worker/worker.go,cmd/server/main.go.