dsndriver

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2023 License: Apache-2.0 Imports: 8 Imported by: 0

README

MySQL Hotswap DSN Driver

Go Reference

This driver is a drop-in replacement for the real Go MySQL driver with one extra feature: it hotswaps the DSN on MySQL error 1045 (access denied). This allows frequently rotating the MySQL password without app downtime or "access denied" errors.

Since the hotswap is handled at the driver-level, you don't have to handle the "access denied" error everywhere the *sql.DB is used. Instead, a single hotswap callback function is set:

import dsndriver "github.com/go-mysql/hotswap-dsn-driver"

// Set hotswap callback function
dsndriver.SetHotswapFunc(func(ctx context.Context, currentDSN string) (newDSN string) {
    // Reload latest DSN and return.
    // Be sure to respect ctx, too.
    return "user:new_pass@tcp(127.0.0.1)/"
})

db, err := sql.Open("mysql-hotswap-dsn", "user:pass@tcp(127.0.0.1)/")

// Use db as usual

To use this driver, only two changes are required as shown above:

  1. Set the hotswap callback func by calling SetHotswapFunc
  2. Use driver name "mysql-hotswap-dsn" instead of "mysql": sql.Open("mysql-hotswap-dsn", "<dsn>")

When using this driver, you do not need to import github.com/go-sql-driver/mysql (but you can if you need to).

The hotswap function is called only for MySQL error 1045. Other errors are ignored. This driver only implements driver- and connector-related interfaces. None of the query-related interfaces are implemented, which means this driver never interferes with queries, transactions, etc.

See the Go docs for additional information.

Documentation

Overview

Package dsndriver provides a MySQL driver that can hot swap the DSN. The driver is registered as "mysql-hotswap-dsn" and is a transparent, drop-in replacement for the real Go MySQL driver: github.com/go-sql-driver/mysql. To use this driver:

import dsndriver "github.com/go-mysql/hotswap-dsn-driver"

// Set hot swap callback function only once, at start
dsndriver.SetHotswapFunc(func(ctx context.Context, currentDSN string) (newDSN string) {
    // User-provided code to load and return new DSN
    // if it has changed, else return an empty string.
    return "user:new-pass@tcp(127.0.0.1)/"
})

db, err := sql.Open("mysql-hotswap-dsn", "user:pass@tcp(127.0.0.1)/")

Then use the db as normal. This driver only implement connection-related interface, and it only hot swaps the DSN by calling the hot sap function when a new connection returns MySQL error code 1045 (access denied). All other functionality is handled by the real MySQL driver directly.

To use this driver, it is not necessary to import github.com/go-sql-driver/mysql. This package and github.com/go-sql-driver/mysql can be imported together if the latter is needed for its exported identifiers.

The first connection to return MySQL error 1045 (access denied) calls the hotswap function and blocks other failed connections until it returns. Once the hotswap function returns, the first failed connection is retried with the new DSN. Once this returns (successful or not), it unblocks other failed/waiting connections which also retry (in parallel) with the new DSN. If the new DSN works, all connections return successfully to the caller and no errors are reported. If the new DSN does not work, the process is repeated. There is currently no TTL, backoff, or cooldown period between hotswaps.

Index

Constants

This section is empty.

Variables

View Source
var Debug bool = false

Debug prints debug info using the Go log package, if true.

Functions

func NewConnector

func NewConnector(dsn string, myc driver.Connector) *connector

NewConnector creates a new connector that wraps a mysql.Connector. Do not call this function; it is called by the driver.

func SetHotswapFunc

func SetHotswapFunc(f func(ctx context.Context, currentDSN string) (newDSN string))

SetHotswapFunc sets the callback function to hot swap the DSN. This must be set only once before any calls to sql.Open. It is not safe to set again or at any other time.

The current DSN is passed to the callback function which should return the new DSN if and only if the DSN has changed. Any non-empty return string is used as the new DSN. If the DSN has not changed, or if there is an error, return an empty string.

The callback function must respect the context and return an empty string if the context is canceled.

The callback function is called serially. The first connection to return MySQL error code 1045 (access denied) will invoke the callback. While the callback is running, other connections that fail with MySQL error code 1045 will wait on the first to hot swap the DSN. All connections respect the context. The callback is abandoned (its return value ignored) if the context is canceled while it is running.

func SetHotswapFuncWithFallback

func SetHotswapFuncWithFallback(f func(ctx context.Context, currentDSN string) (newDSN string), fallbackInterval time.Duration)

--------------------------------------------------------------------------

Types

type MySQLDriver

type MySQLDriver struct{}

MySQLDriver implements driver.Driver and driver.DriverContext.

func (MySQLDriver) Open

func (d MySQLDriver) Open(dsn string) (driver.Conn, error)

func (MySQLDriver) OpenConnector

func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL