Files
sqlite3/litestream/api.go

102 lines
2.3 KiB
Go
Raw Permalink Normal View History

// Package litestream implements a Litestream lightweight read-replica VFS.
package litestream
import (
2025-11-26 12:53:07 +00:00
"context"
"log/slog"
"sync"
"time"
"github.com/benbjohnson/litestream"
2025-11-20 11:35:01 +00:00
"github.com/ncruces/go-sqlite3/vfs"
)
2025-11-20 16:54:51 +00:00
const (
// The default poll interval.
DefaultPollInterval = 1 * time.Second
// The default cache size: 10 MiB.
DefaultCacheSize = 10 * 1024 * 1024
)
func init() {
vfs.Register("litestream", liteVFS{})
}
var (
liteMtx sync.RWMutex
// +checklocks:liteMtx
liteDBs = map[string]*liteDB{}
)
// ReplicaOptions represents options for [NewReplica].
type ReplicaOptions struct {
// Where to log error messages. May be nil.
Logger *slog.Logger
2025-11-20 16:54:51 +00:00
// Replica poll interval.
// Should be less than the compaction interval
// used by the replica at MinLevel+1.
PollInterval time.Duration
2025-11-20 16:54:51 +00:00
// CacheSize is the maximum size of the page cache in bytes.
// Zero means DefaultCacheSize, negative disables caching.
CacheSize int
}
// NewReplica creates a read-replica from a Litestream client.
2025-11-27 16:28:16 +00:00
func NewReplica(name string, client ReplicaClient, options ReplicaOptions) {
if options.Logger != nil {
options.Logger = options.Logger.With("name", name)
} else {
options.Logger = slog.New(slog.DiscardHandler)
}
if options.PollInterval <= 0 {
options.PollInterval = DefaultPollInterval
}
2025-11-20 16:54:51 +00:00
if options.CacheSize == 0 {
options.CacheSize = DefaultCacheSize
}
liteMtx.Lock()
defer liteMtx.Unlock()
liteDBs[name] = &liteDB{
client: client,
2025-11-20 16:54:51 +00:00
opts: options,
cache: pageCache{size: options.CacheSize},
}
}
// RemoveReplica removes a replica by name.
func RemoveReplica(name string) {
liteMtx.Lock()
defer liteMtx.Unlock()
delete(liteDBs, name)
}
2025-11-26 12:53:07 +00:00
2025-11-27 16:28:16 +00:00
// NewPrimary creates a new primary that replicates through client.
2025-11-26 12:53:07 +00:00
// If restore is not nil, the database is first restored.
2025-11-27 16:28:16 +00:00
func NewPrimary(ctx context.Context, path string, client ReplicaClient, restore *RestoreOptions) (*litestream.DB, error) {
2025-11-26 12:53:07 +00:00
lsdb := litestream.NewDB(path)
lsdb.Replica = litestream.NewReplicaWithClient(lsdb, client)
if restore != nil {
err := lsdb.Replica.Restore(ctx, *restore)
if err != nil {
return nil, err
}
}
err := lsdb.Open()
if err != nil {
return nil, err
}
return lsdb, nil
}
2025-11-27 16:28:16 +00:00
type (
ReplicaClient = litestream.ReplicaClient
RestoreOptions = litestream.RestoreOptions
)