Skip to content

Commit

Permalink
feat: use lazy connections
Browse files Browse the repository at this point in the history
Running an import action (or any action for that matter) which is not
touching posgres resources should not trigger the initialisation of the
postgres provider.

Same behaviour as terraform-provider-mysql.

Fixes cyrilgdn#140

Signed-off-by: Enrico Stahn <enrico.stahn@gmail.com>
  • Loading branch information
estahn authored and cyrilgdn committed Nov 11, 2020
1 parent 04979fe commit 87e6022
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 34 deletions.
77 changes: 43 additions & 34 deletions postgresql/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,43 +119,9 @@ func (c *Config) NewClient(database string) (*Client, error) {
dbRegistryLock.Lock()
defer dbRegistryLock.Unlock()

dsn := c.connStr(database)
dbEntry, found := dbRegistry[dsn]
if !found {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, fmt.Errorf("Error connecting to PostgreSQL server: %w", err)
}

// We don't want to retain connection
// So when we connect on a specific database which might be managed by terraform,
// we don't keep opened connection in case of the db has to be dopped in the plan.
db.SetMaxIdleConns(0)
db.SetMaxOpenConns(c.MaxConns)

defaultVersion, _ := semver.Parse(defaultExpectedPostgreSQLVersion)
version := &c.ExpectedVersion
if defaultVersion.Equals(c.ExpectedVersion) {
// Version hint not set by user, need to fingerprint
version, err = fingerprintCapabilities(db)
if err != nil {
db.Close()
return nil, fmt.Errorf("error detecting capabilities: %w", err)
}
}

dbEntry = dbRegistryEntry{
db: db,
version: *version,
}
dbRegistry[dsn] = dbEntry
}

client := Client{
config: *c,
databaseName: database,
db: dbEntry.db,
version: dbEntry.version,
}

return &client, nil
Expand Down Expand Up @@ -305,9 +271,52 @@ func (c *Config) getDatabaseUsername() string {
// return their database resources. Use of QueryRow() or Exec() is encouraged.
// Query() must have their rows.Close()'ed.
func (c *Client) DB() *sql.DB {
c.connectDB()
return c.db
}

func (c *Client) connectDB() (*Client, error) {
dbRegistryLock.Lock()
defer dbRegistryLock.Unlock()

dsn := c.config.connStr(c.databaseName)
dbEntry, found := dbRegistry[dsn]
if !found {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, fmt.Errorf("Error connecting to PostgreSQL server: %w", err)
}

// We don't want to retain connection
// So when we connect on a specific database which might be managed by terraform,
// we don't keep opened connection in case of the db has to be dopped in the plan.
db.SetMaxIdleConns(0)
db.SetMaxOpenConns(c.config.MaxConns)

defaultVersion, _ := semver.Parse(defaultExpectedPostgreSQLVersion)
version := &c.config.ExpectedVersion
if defaultVersion.Equals(c.config.ExpectedVersion) {
// Version hint not set by user, need to fingerprint
version, err = fingerprintCapabilities(db)
if err != nil {
db.Close()
return nil, fmt.Errorf("error detecting capabilities: %w", err)
}
}

dbEntry = dbRegistryEntry{
db: db,
version: *version,
}
dbRegistry[dsn] = dbEntry
}

c.db = dbEntry.db
c.version = dbEntry.version

return nil, nil
}

// fingerprintCapabilities queries PostgreSQL to populate a local catalog of
// capabilities. This is only run once per Client.
func fingerprintCapabilities(db *sql.DB) (*semver.Version, error) {
Expand Down
1 change: 1 addition & 0 deletions postgresql/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func startTransaction(client *Client, database string) (*sql.Tx, error) {
return nil, err
}
}
// spew.Dump(client)
db := client.DB()
txn, err := db.Begin()
if err != nil {
Expand Down

0 comments on commit 87e6022

Please sign in to comment.