| index fc5bf7520..8fee34533 100644 |
| --- a/internal/registry/registry.go |
| +++ b/internal/registry/registry.go |
| @@ -1097,7 +1097,7 @@ WHERE kind = 'instance' AND next_due > 0 AND next_due <= ? ORDER BY host`, now) |
| // Fingerprint summarizes the route table over a fresh connection, for the |
| // edge's cheap change poll. It is content-accurate over the reload-relevant |
| // columns (status, socket, addr, version, hibernate, channel, backing, |
| -// tunnel): it hashes the actual values, not a length-weighted aggregate, so |
| +// tunnel, db_path): it hashes the actual values, not a length-weighted aggregate, so |
| // two DIFFERENT values of the SAME length (channel canary/1 -> canary/2, a |
| // git short-sha version bump) change the string exactly like any other |
| // write. `grants` stays deliberately excluded (registry.go:93's rule: grants |
| @@ -1113,6 +1113,10 @@ WHERE kind = 'instance' AND next_due > 0 AND next_due <= ? ORDER BY host`, now) |
| // construction — the old length-weighted aggregate could not see a version |
| // bump land, so the header would serve stale until an unrelated column |
| // happened to change too. |
| +// |
| +// db_path is hashed too (issue #69): a re-add that only re-points a route's |
| +// database must reach a running edge, or the activator keeps waking the host |
| +// on the stale cached path. |
| func (r *Registry) Fingerprint() (string, error) { |
| db, err := sql.Open("sqlite", r.path) |
| if err != nil { |
| @@ -1123,7 +1127,7 @@ func (r *Registry) Fingerprint() (string, error) { |
| return "", err |
| } |
| rows, err := db.Query(` |
| -SELECT rowid, status, socket, addr, version, hibernate, channel, backing, tunnel |
| +SELECT rowid, status, socket, addr, version, hibernate, channel, backing, tunnel, db_path |
| FROM routes ORDER BY rowid`) |
| if err != nil { |
| return "", err |
| @@ -1133,12 +1137,12 @@ FROM routes ORDER BY rowid`) |
| n := 0 |
| for rows.Next() { |
| var rowid, hibernate int64 |
| - var status, socket, addr, version, channel, backing, tunnel string |
| - if err := rows.Scan(&rowid, &status, &socket, &addr, &version, &hibernate, &channel, &backing, &tunnel); err != nil { |
| + var status, socket, addr, version, channel, backing, tunnel, dbPath string |
| + if err := rows.Scan(&rowid, &status, &socket, &addr, &version, &hibernate, &channel, &backing, &tunnel, &dbPath); err != nil { |
| return "", err |
| } |
| - fmt.Fprintf(h, "%d\x1f%s\x1f%s\x1f%s\x1f%s\x1f%d\x1f%s\x1f%s\x1f%s\x1e", |
| - rowid, status, socket, addr, version, hibernate, channel, backing, tunnel) |
| + fmt.Fprintf(h, "%d\x1f%s\x1f%s\x1f%s\x1f%s\x1f%d\x1f%s\x1f%s\x1f%s\x1f%s\x1e", |
| + rowid, status, socket, addr, version, hibernate, channel, backing, tunnel, dbPath) |
| n++ |
| } |
| if err := rows.Err(); err != nil { |