20 Commits

Author SHA1 Message Date
Rodrigo Verdiani
e554149e8b feat(job): job progress tracking 2026-07-07 09:05:19 -03:00
Rodrigo Verdiani
2eead05c34 feat: expirar jobs stuck com status timeout
Adiciona mecanismo de expiração periódica para jobs que ficam presos
nos status received ou processing além de um threshold configurável.

- models: novo status StatusTimeout
- store: migration v2 com índice em jobs(status); método ExpireStuck
  que faz UPDATE atômico para os status alvo anteriores ao threshold
- expirer: novo pacote com goroutine periódica que chama ExpireStuck
  e loga WARN quando algum job é expirado
- config: campos JobTimeoutMinutes (default 120) e
  ExpirerIntervalMinutes (default 10), lidos via env vars
  JOB_TIMEOUT_MINUTES e EXPIRER_INTERVAL_MINUTES
- main: instancia e inicia o Expirer no startup
- dashboard: card Timeout com contagem; badge neutral na tabela de jobs
2026-07-07 08:43:33 -03:00
Rodrigo Verdiani
7e5f4cb155 feat(worker): adicionar logs estruturados ao longo do ciclo do job
- Enriquecer logger com artist e album após carregar o job do banco
- Logar início do job com path e contagem de FLACs encontrados
- Logar cada arquivo antes de chamar o ffmpeg
- Emitir Error('job failed') ou Info('job completed') em finishJob,
  garantindo que todo encerramento gere entrada na tabela de logs
2026-07-07 08:43:26 -03:00
Rodrigo Verdiani
708dc5fda9 fix: use context.Background() ao enfileirar jobs
O contexto da requisição HTTP era passado para o Enqueue, causando
'context canceled' quando a conexão encerrava antes do INSERT no
SQLite completar. Jobs devem ser persistidos independentemente do
ciclo de vida da requisição.
2026-07-07 08:43:20 -03:00
Rodrigo Verdiani
e60ec521e1 fix(ntfy): migrate to JSON publishing to fix 400 invalid JSON error
POST to root / with application/json body instead of /<topic>
with plain-text headers. Prevents ntfy error 40024 when ErrorMsg
contains JSON content.
2026-07-07 08:33:27 -03:00
Rodrigo Verdiani
715d680f97 feat(logger): include attributes in persisted log message
Store attributes as key=value pairs in the SQLite log message
so they are visible in the web UI. job_id is extracted into the
dedicated column and excluded from the message text.
2026-07-06 22:58:28 -03:00
Rodrigo Verdiani
2fd56d0f36 fix(webhook): rename route from /webhook/lidarr to /webhook
Simplify the webhook endpoint path to match the URL documented
in the Lidarr integration guide.

Also add a Lidarr integration section to README covering Coda
environment variables, Lidarr webhook configuration, and the
full end-to-end flow.
2026-07-06 22:50:30 -03:00
Rodrigo Verdiani
f02c46b6c7 fix(ntfy): post to root URL with topic in JSON body
The ntfy API requires JSON payloads to be sent to the root URL (/)
with the topic field in the body. Posting to /<topic> with a JSON
body causes ntfy to treat it as plain text, rendering the raw JSON
as the notification content.

- Add Topic field to message struct
- Pass topic into buildMessage and include it in the payload
- Replace notificationURL with rootURL that resolves to base URL root
- Remove unused strings import
- Fix tests: add DRY_RUN=false override to prevent .env interference
2026-07-06 22:37:39 -03:00
Rodrigo Verdiani
a227278932 fix: handle library conversion and sqlite locking 2026-07-06 22:29:42 -03:00
Rodrigo Verdiani
b7e6b288cd feat: implement BP-10 ntfy notifications 2026-07-06 22:07:43 -03:00
Rodrigo Verdiani
63919dd6c3 feat: implement BP-09 web interface 2026-07-06 21:51:12 -03:00
Rodrigo Verdiani
213f16bdbf feat: implement BP-08 library scan and convert 2026-07-06 21:27:06 -03:00
Rodrigo Verdiani
0915c689fe feat: implement BP-07 webhook trigger 2026-07-06 21:18:02 -03:00
Rodrigo Verdiani
27abb91ff3 feat: implement BP-06 lidarr integration 2026-07-06 21:10:12 -03:00
Rodrigo Verdiani
6cf1058107 feat: implement BP-05 job pipeline 2026-07-06 21:04:30 -03:00
Rodrigo Verdiani
b3a7956e98 feat: implement BP-04 audio conversion core 2026-07-06 20:53:16 -03:00
Rodrigo Verdiani
a856850451 feat: implement BP-03 runtime configuration 2026-07-06 20:41:20 -03:00
Rodrigo Verdiani
2dbb0b54a0 feat: implement BP-02 structured logging to SQLite 2026-07-06 20:34:42 -03:00
Rodrigo Verdiani
6ffa161d5f feat: implement BP-01 persistence and models
Add SQLite persistence layer with domain types for jobs, logs, and config.
- internal/models: Job, LogEntry, JobStatus, JobSource types
- internal/store: Store with WAL pragmas, idempotent migrations
- JobRepository, LogRepository, ConfigRepository with full CRUD
- Wire store.New into main.go server startup
- 15 passing tests covering all repositories
2026-07-06 20:27:48 -03:00
Rodrigo Verdiani
e1a262fec0 feat: scaffold Coda transcoder with docs, dev tooling and web base
Add the initial foundation for Coda, a Go/Docker service that converts
FLAC albums to MP3 320 kbps CBR, triggered by Lidarr webhooks or manually
from the web UI.

- docs: requirements and architecture (SQLite persistence, media volume,
  work window, manual FLAC search, env + web config)
- config: .env loader with env precedence
- web: embed/dev asset split, chi server, index template (DaisyUI + htmx)
- build: Makefile (setup/css/run/build/test/lint), Dockerfile (Tailwind
  standalone CLI + DaisyUI, no Node), .env.example, ignore rules
- docs: AGENTS.md and README for the project
2026-07-06 20:06:25 -03:00