Rewrites the internal/api comment blocks to rule 32: task, milestone and rule ids gone, the stories behind them restated as the constraint they left, stale references corrected (the stream secret is wired from config, the timezone handler already refreshes the scheduler, the Android app is the native client, the design docs cited are not in the repo). Also rewraps comment lines over 80 columns left by the earlier batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
3.1 KiB
Go
85 lines
3.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/apierror"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/library"
|
|
)
|
|
|
|
// coverageRollupResp is the wire shape for GET /api/admin/library/coverage.
|
|
// All fields are non-negative counts. with_art + pending + settled = total;
|
|
// pending_no_mbid is a subset of pending.
|
|
type coverageRollupResp struct {
|
|
Total int64 `json:"total"`
|
|
WithArt int64 `json:"with_art"`
|
|
Pending int64 `json:"pending"`
|
|
Settled int64 `json:"settled"`
|
|
PendingNoMbid int64 `json:"pending_no_mbid"`
|
|
}
|
|
|
|
// handleGetLibraryCoverage implements GET /api/admin/library/coverage.
|
|
// Surfaces a library-wide rollup of albums.cover_art_source for the admin
|
|
// dashboard gauge. Always 200; zeros on an empty library.
|
|
func (h *handlers) handleGetLibraryCoverage(w http.ResponseWriter, r *http.Request) {
|
|
q := dbq.New(h.pool)
|
|
row, err := q.GetAlbumCoverageRollup(r.Context())
|
|
if err != nil {
|
|
writeErrWithLog(w, h.logger, "admin: get coverage rollup", apierror.InternalMsg("lookup failed", err))
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, coverageRollupResp{
|
|
Total: row.Total,
|
|
WithArt: row.WithArt,
|
|
Pending: row.Pending,
|
|
Settled: row.Settled,
|
|
PendingNoMbid: row.PendingNoMbid,
|
|
})
|
|
}
|
|
|
|
// fingerprintCoverageResp is the wire shape for GET
|
|
// /api/admin/library/fingerprints. fingerprinted + rejected + pending = total.
|
|
// Missing tracks are not counted: there is no file to fingerprint. Enabled
|
|
// travels with the counts because with fingerprinting off pending never
|
|
// shrinks, and a gauge that implies progress would be promising work nothing is
|
|
// doing.
|
|
type fingerprintCoverageResp struct {
|
|
Total int64 `json:"total"`
|
|
Fingerprinted int64 `json:"fingerprinted"`
|
|
Rejected int64 `json:"rejected"`
|
|
Pending int64 `json:"pending"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
|
|
// fingerprintCoverage reads the gauge against the current settings: a print at
|
|
// another length counts as pending, because the backfill will re-derive it.
|
|
func (h *handlers) fingerprintCoverage(ctx context.Context) (fingerprintCoverageResp, error) {
|
|
cfg := h.fingerprintSettings.Get()
|
|
row, err := library.FingerprintCoverage(ctx, h.pool, cfg)
|
|
if err != nil {
|
|
return fingerprintCoverageResp{}, err
|
|
}
|
|
return fingerprintCoverageResp{
|
|
Total: row.Total,
|
|
Fingerprinted: row.Fingerprinted,
|
|
Rejected: row.Rejected,
|
|
Pending: row.Pending,
|
|
Enabled: cfg.Enabled,
|
|
}, nil
|
|
}
|
|
|
|
// handleGetFingerprintCoverage implements GET /api/admin/library/fingerprints:
|
|
// how far the fingerprint backfill has got. The backfill is its own
|
|
// worker spanning many passes, with no scan run to attach a tally to, so its
|
|
// progress is read live here. Always 200; zeros on an empty library.
|
|
func (h *handlers) handleGetFingerprintCoverage(w http.ResponseWriter, r *http.Request) {
|
|
cov, err := h.fingerprintCoverage(r.Context())
|
|
if err != nil {
|
|
writeErrWithLog(w, h.logger, "admin: get fingerprint coverage", apierror.InternalMsg("lookup failed", err))
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, cov)
|
|
}
|