feat: expose monitoring tg media repair details
All checks were successful
CI / hygiene (push) Successful in 2s
Build and Deploy / build-and-deploy (push) Successful in 45s
CI / go (push) Successful in 31s
CI / python (push) Successful in 2s

This commit is contained in:
Grendgi
2026-06-17 17:22:50 +03:00
parent 696b7eda6f
commit cdbdea250d
2 changed files with 72 additions and 3 deletions

View File

@@ -558,17 +558,81 @@ func (a *app) probeMediaMetadata(ctx context.Context) componentProbe {
return componentProbe{Name: "media_metadata", Status: "down", LatencyMs: time.Since(start).Milliseconds(), Error: err.Error()}
}
if missingFiles > 0 {
recent, recentErr := a.recentMissingMedia(ctx)
details := map[string]any{
"messages_with_media": withMedia,
"missing_media_files": missingFiles,
}
if recentErr != nil {
details["recent_error"] = recentErr.Error()
} else {
details["recent_missing_media"] = recent
}
return componentProbe{
Name: "media_metadata",
Status: "down",
LatencyMs: time.Since(start).Milliseconds(),
Error: "messages_with_media=" + strconv.FormatInt(withMedia, 10) +
" missing_media_files=" + strconv.FormatInt(missingFiles, 10),
Details: details,
}
}
return componentProbe{Name: "media_metadata", Status: "ok", LatencyMs: time.Since(start).Milliseconds()}
}
func (a *app) recentMissingMedia(ctx context.Context) ([]map[string]any, error) {
rows, err := a.db.Query(ctx, `
SELECT
m.id,
m.tg_message_id,
m.date,
c.id AS channel_id,
c.identifier,
COALESCE(c.title, '') AS channel_title,
s.slug,
s.title AS section_title
FROM messages m
JOIN channels c ON c.id = m.channel_id
LEFT JOIN sections s ON s.id = c.section_id
WHERE m.has_media = true
AND jsonb_array_length(COALESCE(m.media_files, '[]'::jsonb)) = 0
ORDER BY m.date DESC, m.id DESC
LIMIT 5`)
if err != nil {
return nil, err
}
defer rows.Close()
out := make([]map[string]any, 0, 5)
for rows.Next() {
var (
id int64
tgMessageID int64
date time.Time
channelID int64
identifier string
channelTitle string
sectionSlug sql.NullString
sectionTitle sql.NullString
)
if err := rows.Scan(&id, &tgMessageID, &date, &channelID, &identifier, &channelTitle, &sectionSlug, &sectionTitle); err != nil {
return nil, err
}
out = append(out, map[string]any{
"message_id": id,
"tg_message_id": tgMessageID,
"message_date": date,
"channel_id": channelID,
"identifier": identifier,
"channel_title": nullableString(channelTitle),
"section_slug": nullString(sectionSlug),
"section_title": nullString(sectionTitle),
"repair_action": "/api/v1/channels/" + strconv.FormatInt(channelID, 10) + "/backfill-media",
})
}
return out, rows.Err()
}
func (a *app) handleAccessMe(w http.ResponseWriter, r *http.Request) {
scope := readAccess(r)
writeJSON(w, http.StatusOK, map[string]any{