blob: c07bf1522e4d836359472b27138cf4b34f2882c7 [file] [log] [blame]
Serge Bazanskide4e8412023-02-15 23:28:04 +01001package bmdb
2
3import (
Serge Bazanski424e2012023-02-15 23:31:49 +01004 "context"
Serge Bazanskide4e8412023-02-15 23:28:04 +01005 "database/sql"
6 "fmt"
7
8 "k8s.io/klog/v2"
9
10 "source.monogon.dev/cloud/bmaas/bmdb/model"
Serge Bazanski424e2012023-02-15 23:31:49 +010011 "source.monogon.dev/cloud/bmaas/bmdb/reflection"
Serge Bazanskide4e8412023-02-15 23:28:04 +010012)
13
14// Open creates a new Connection to the BMDB for the calling component. Multiple
15// connections can be opened (although there is no advantage to doing so, as
16// Connections manage an underlying CockroachDB connection pool, which performs
17// required reconnects and connection pooling automatically).
18func (b *BMDB) Open(migrate bool) (*Connection, error) {
19 if migrate {
20 if b.Config.Database.Migrations == nil {
21 klog.Infof("Using default migrations source.")
22 m, err := model.MigrationsSource()
23 if err != nil {
24 klog.Exitf("failed to prepare migrations source: %w", err)
25 }
26 b.Config.Database.Migrations = m
27 }
28 if err := b.Database.MigrateUp(); err != nil {
29 return nil, fmt.Errorf("migration failed: %w", err)
30 }
31 }
32 db, err := b.Database.Connect()
33 if err != nil {
34 return nil, err
35 }
36 return &Connection{
37 bmdb: b,
38 db: db,
39
40 DatabaseName: b.Config.Database.DatabaseName,
41 Address: b.Config.Database.EndpointHost,
42 InMemory: b.Config.Database.InMemory,
43 }, nil
44}
45
46// Connection to the BMDB. Internally, this contains a sql.DB connection pool,
47// so components can (and likely should) reuse Connections as much as possible
48// internally.
49type Connection struct {
50 bmdb *BMDB
51 db *sql.DB
52
53 // The database name that we're connected to.
54 DatabaseName string
55 // The address of the CockroachDB endpoint we've connected to.
56 Address string
57 // Whether this connection is to an in-memory database. Note: this only works if
58 // this Connection came directly from calling Open on a BMDB that was defined to
59 // be in-memory. If you just connect to an in-memory CRDB manually, this will
60 // still be false.
61 InMemory bool
62}
Serge Bazanski424e2012023-02-15 23:31:49 +010063
64// Reflect returns a reflection.Schema as detected by inspecting the table
65// information of this connection to the BMDB. The Schema can then be used to
66// retrieve arbitrary tag/machine information without going through the
67// concurrency/ordering mechanism of the BMDB.
68//
69// This should only be used to implement debugging tooling and should absolutely
70// not be in the path of any user requests.
71//
72// This Connection will be used not only to query the Schema information, but
73// also for all subsequent data retrieval operations on it. Please ensure that
74// the Schema is rebuilt in the event of a database connection failure. Ideally,
75// you should be rebuilding the schema often, to follow what is currently
76// available on the production database - but not for every request. Use a cache
77// or something.
78func (c *Connection) Reflect(ctx context.Context) (*reflection.Schema, error) {
79 return reflection.Reflect(ctx, c.db)
80}