oficina / home Public

Clone
git clone https://amadan.net/oficina/home

Plain git — no account needed to clone.

Download

Download this file

1package home
2
3import (
4 "context"
5 "database/sql"
6 "log/slog"
7 "sort"
8 "time"
9
10 "amadan.net/rastrillo/rastrillo/db"
11)
12
13// LogSchemaInventory reports only compiled migration names and counts. Unknown
14// database strings never enter logs, and the report grants no operator authority.
15func LogSchemaInventory(parent context.Context, d *db.DB, cfg Runtime, logger *slog.Logger) {
16 if parent == nil || d == nil || logger == nil || (cfg.role != "credential" && cfg.role != "directory") {
17 return
18 }
19 ctx, cancel := context.WithTimeout(parent, 2*time.Second)
20 defer cancel()
21 defer logLegacySchemaDiagnostic(ctx, d.Writer(), cfg.role, logger)
22 expected := map[string]bool{}
23 known := map[string]bool{}
24 for _, m := range cfg.Schema().All() {
25 expected[m.ID] = true
26 }
27 for _, role := range []string{"credential", "directory"} {
28 for _, m := range (Runtime{role: role}).Schema().All() {
29 known[m.ID] = true
30 }
31 }
32 rows, err := d.Writer().QueryContext(ctx, "SELECT CASE WHEN typeof(id)='text' AND length(id)<=256 THEN id END FROM rastrillo_migrations LIMIT 1001")
33 if err != nil {
34 logger.Info("schema inventory unavailable")
35 return
36 }
37 var extra []string
38 unknown, count := 0, 0
39 for rows.Next() {
40 var id sql.NullString
41 if rows.Scan(&id) != nil {
42 rows.Close()
43 logger.Info("schema inventory unavailable")
44 return
45 }
46 count++
47 if count > 1000 {
48 break
49 }
50 if id.Valid && expected[id.String] {
51 continue
52 }
53 if id.Valid && known[id.String] {
54 extra = append(extra, id.String)
55 } else {
56 unknown++
57 }
58 }
59 if rows.Err() != nil || rows.Close() != nil {
60 logger.Info("schema inventory unavailable")
61 return
62 }
63 sort.Strings(extra)
64 logger.Info("schema inventory", "role", cfg.role, "known_extra", extra, "unclassified", unknown, "truncated", count > 1000)
65}
66