plz / database.v
47 lines · 40 sloc · 2.03 KB · 937c8e999c24a3e84663b9b84629a6fab6ff2114
Raw
1module main
2
3import veb
4
5// reconnect_db drops the current DB handle and opens a fresh connection.
6// Used to recover from stale connections (e.g. an idle Postgres connection
7// dropped by NAT or by PG's idle_session_timeout). v's db.pg has no built-in
8// reconnect, so without this the process keeps using a dead handle until restart.
9pub fn (mut app App) reconnect_db() ! {
10 app.db.close() or {}
11 app.db = connect_db(app.config)!
12}
13
14// get_users_count_with_reconnect retries the user count query once after
15// reconnecting on failure. This is the recovery path for the specific bug
16// where a dead DB handle made get_users_count() silently return 0 and the
17// site rendered the "welcome / register" page until systemd restart.
18pub fn (mut app App) get_users_count_with_reconnect() !int {
19 if count := app.get_users_count() {
20 return count
21 } else {
22 app.warn('db query failed, attempting reconnect: ${err}')
23 app.reconnect_db() or { return error('db unavailable; reconnect failed: ${err}') }
24 return app.get_users_count()!
25 }
26}
27
28// db_error renders a 503 response describing a database failure.
29// We render an explicit page rather than letting callers fall back to a
30// misleading default (e.g. redirecting to /register on a swallowed error).
31pub fn (mut ctx Context) db_error(err IError) veb.Result {
32 ctx.res.set_status(.service_unavailable)
33 body := '<!DOCTYPE html><html><head><meta charset="utf-8"><title>Gitly — database unavailable</title></head><body style="font-family:sans-serif;max-width:640px;margin:4em auto;padding:0 1em;"><h1>Database unavailable</h1><p>Gitly could not reach its database. This is usually transient — please try again in a moment.</p><pre style="background:#f4f4f4;padding:1em;overflow:auto;white-space:pre-wrap;">${err}</pre></body></html>'
34 return ctx.html(body)
35}
36
37fn sql_table(name string) string {
38 return '"' + name.to_lower().replace('"', '""') + '"'
39}
40
41fn sql_literal(value string) string {
42 return "'" + value.replace("'", "''") + "'"
43}
44
45fn sql_like_pattern(value string) string {
46 return sql_literal('%' + value + '%')
47}
48