Documentation ¶
Overview ¶
Package sqlcache provides an experimental caching middleware for database/sql users. This liberates your Go program from maintaining imperative code that implements the cache-aside pattern. Your program will perceive the database client/driver as a read-through cache.
Usage:
import ( "database/sql" redis "github.com/go-redis/redis/v7" "github.com/prashanthpai/sqlcache" "github.com/jackc/pgx/v4/stdlib" ) func main() { ... rc := redis.NewUniversalClient(&redis.UniversalOptions{ Addrs: []string{"127.0.0.1:6379"}, }) // create a sqlcache.Interceptor instance with the desired backend interceptor, err := sqlcache.NewInterceptor(&sqlcache.Config{ Cache: sqlcache.NewRedis(rc, "sqc"), }) ... // wrap pgx driver with the interceptor and register it sql.Register("pgx-with-cache", interceptor.Driver(stdlib.GetDefaultDriver())) // open the database using the wrapped driver db, err := sql.Open("pgx-with-cache", dsn) ... }
Caching is controlled using cache attributes which are SQL comments starting with `@cache-` prefix. Only queries with cache attributes are cached.
Example query:
rows, err := db.QueryContext(context.TODO(), ` -- @cache-ttl 30 -- @cache-max-rows 10 SELECT name, pages FROM books WHERE pages > $1`, 100)
Index ¶
- func NoopHash(query string, args []driver.NamedValue) (string, error)
- type Config
- type Interceptor
- func (i *Interceptor) ConnQueryContext(ctx context.Context, conn driver.QueryerContext, query string, ...) (context.Context, driver.Rows, error)
- func (i *Interceptor) Disable()
- func (i *Interceptor) Driver(d driver.Driver) driver.Driver
- func (i *Interceptor) Enable()
- func (i *Interceptor) Stats() *Stats
- func (i *Interceptor) StmtQueryContext(ctx context.Context, conn driver.StmtQueryContext, query string, ...) (context.Context, driver.Rows, error)
- type KeyRWLock
- type Redis
- type Ristretto
- type Stats
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Config ¶
type Config struct { // Cache must be set to a type that implements the cache.Cacher interface // which abstracts the backend cache implementation. This is a required // field and cannot be nil. Cache cache.Cacher // OnError is called whenever methods of cache.Cacher interface or HashFunc // returns error. Since sqlcache package does not log any failures, you can // use this hook to log errors or even choose to disable/bypass sqlcache. OnError func(error) // HashFunc can be optionally set to provide a custom hashing function. By // default sqlcache uses mitchellh/hashstructure which internally uses FNV. // If hash collision is a concern to you, consider using NoopHash. HashFunc func(query string, args []driver.NamedValue) (string, error) }
Config is the configuration passed to NewInterceptor for creating new Interceptor instances.
type Interceptor ¶
type Interceptor struct { sqlmw.NullInterceptor KeyRWLock // contains filtered or unexported fields }
Interceptor is a ngrok/sqlmw interceptor that caches SQL queries and their responses.
func NewInterceptor ¶
func NewInterceptor(config *Config) (*Interceptor, error)
NewInterceptor returns a new instance of sqlcache interceptor initialised with the provided config.
func (*Interceptor) ConnQueryContext ¶
func (i *Interceptor) ConnQueryContext(ctx context.Context, conn driver.QueryerContext, query string, args []driver.NamedValue) (context.Context, driver.Rows, error)
ConnQueryContext intecepts database/sql's DB.QueryContext Conn.QueryContext calls.
func (*Interceptor) Disable ¶
func (i *Interceptor) Disable()
Disable disables the interceptor resulting in cache bypass. All queries would go directly to the SQL backend.
func (*Interceptor) Driver ¶
func (i *Interceptor) Driver(d driver.Driver) driver.Driver
Driver returns the supplied driver.Driver with a new object that has all of its calls intercepted by the sqlcache.Interceptor. Any DB call without a context passed will not be intercepted.
func (*Interceptor) Enable ¶
func (i *Interceptor) Enable()
Enable enables the interceptor. Interceptor instance is enabled by default on creation.
func (*Interceptor) StmtQueryContext ¶
func (i *Interceptor) StmtQueryContext(ctx context.Context, conn driver.StmtQueryContext, query string, args []driver.NamedValue) (context.Context, driver.Rows, error)
StmtQueryContext intecepts database/sql's stmt.QueryContext calls from a prepared statement.
type Redis ¶
type Redis struct {
// contains filtered or unexported fields
}
Redis implements cache.Cacher interface to use redis as backend with go-redis as the redis client library.
func NewRedis ¶
func NewRedis(c redis.UniversalClient, keyPrefix string) *Redis
NewRedis creates a new instance of redis backend using go-redis client. All keys created in redis by sqlcache will have start with prefix.
type Ristretto ¶
type Ristretto struct {
// contains filtered or unexported fields
}
Ristretto implements cache.Cacher interface to use ristretto as backend with go-redis as the redis client library.
func NewRistretto ¶
NewRistretto creates a new instance of ristretto backend wrapping the provided *ristretto.Cache instance. While creating the ristretto instance, please note that number of rows will be used as "cost" (in ristretto's terminology) for each cache item.