move-migrations-to-option (#1)

Removes global variables and sets up migrations as optional.

Reviewed-on: #1
Co-authored-by: Mason Payne <mason@masonitestudios.com>
Co-committed-by: Mason Payne <mason@masonitestudios.com>
main
Mason Payne 2024-10-16 18:04:01 -06:00 committed by payne8
parent 72df3adf0d
commit b08636ba39
5 changed files with 40 additions and 38 deletions

27
db.go
View File

@ -16,25 +16,20 @@ type Migrations struct {
type Options func(*LibSqlDB) error
// use something like this in the user's code -> //go:embed migrations/*.sql
var _migrationFiles embed.FS
var migrations []Migrations
// func NewLibSqlDB is defined in embedded.go and remote-only.go files
// these files are used to define the LibSqlDB struct and the NewLibSqlDB function
// they have different initializations based on the environment, embedded or remote-only
// Windows does not currently support the embedded database, so the remote-only file is used
// setupMigrations initializes the filesystem and reads the migration files into the migrations variable
func setupMigrations() error {
func (t *LibSqlDB) setupMigrations() error {
// Walk through the embedded files and read their contents
err := fs.WalkDir(_migrationFiles, ".", func(path string, d fs.DirEntry, err error) error {
err := fs.WalkDir(t.migrationFiles, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {
content, err := _migrationFiles.ReadFile(path)
content, err := t.migrationFiles.ReadFile(path)
if err != nil {
return err
}
@ -43,7 +38,7 @@ func setupMigrations() error {
name: filepath.Base(path),
query: string(content),
}
migrations = append(migrations, migration)
t.migrations = append(t.migrations, migration)
}
return nil
})
@ -55,6 +50,10 @@ func setupMigrations() error {
// Migrate updates the connected LibSqlDB to the latest schema based on the given migrations
func (t *LibSqlDB) Migrate() error {
if !t.useMigrations {
return fmt.Errorf("migrations not enabled")
}
// check if migration table exists
var migrationsCheck string
//goland:noinspection SqlResolve
@ -70,7 +69,7 @@ func (t *LibSqlDB) Migrate() error {
}
}
for _, migration := range migrations {
for _, migration := range t.migrations {
var migrationInHistory string
err = t.DB.QueryRow("SELECT name FROM migrations WHERE name = ?", migration.name).Scan(&migrationInHistory)
if err != nil {
@ -138,3 +137,11 @@ func WithReadYourWrites(readYourWrites bool) Options {
return nil
}
}
func WithMigrationFiles(migrationFiles embed.FS) Options {
return func(l *LibSqlDB) error {
l.useMigrations = true
l.migrationFiles = migrationFiles
return nil
}
}

View File

@ -22,15 +22,14 @@ type LibSqlDB struct {
syncInterval time.Duration // only used for embedded replica
encryptionKey string // only used for embedded replica
readYourWrites *bool // only used for embedded replica
useMigrations bool
migrationFiles embed.FS
migrations []Migrations
}
var syncInterval = 200 * time.Millisecond
func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*LibSqlDB, error) {
func NewLibSqlDB(primaryUrl string, opts ...Options) (*LibSqlDB, error) {
l := libSqlDefaults()
_migrationFiles = migrationFiles
for _, option := range opts {
err := option(l)
if err != nil {
@ -74,9 +73,11 @@ func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*
db := sql.OpenDB(connector)
err = setupMigrations()
if err != nil {
return nil, fmt.Errorf("error setting up migrations | %w", err)
if l.useMigrations {
err = l.setupMigrations()
if err != nil {
return nil, fmt.Errorf("error setting up migrations | %w", err)
}
}
l.DB = db

View File

@ -17,9 +17,9 @@ func main() {
// Open the database
tdb, err := libsqldb.NewLibSqlDB(
primaryUrl,
migrationFiles,
libsqldb.WithMigrationFiles(migrationFiles),
libsqldb.WithAuthToken(authToken),
libsqldb.WithLocalDBName("local.db"),
libsqldb.WithLocalDBName("local.db"), // will not be used for remote-only
)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to open db %s: %s", primaryUrl, err)

View File

@ -32,15 +32,6 @@ tdb, err := libsqldb.NewLibSqlDB(
## Why Use This Library?
I developed this library to streamline the process of setting up a database connection in Go, complete with built-in migration capabilities. During development, I encountered issues with using the embedded driver on Windows. As I researched, I discovered [others had similar issues](https://github.com/tursodatabase/go-libsql/issues/30). This wrapper solves that problem by automatically selecting the appropriate driver based on your operating system.
## How to Use
For a complete example, check out the examples/basic-usage directory in this repository.
Before running your application, make sure to set the following environment variables:
```bash
LIBSQL_AUTH_TOKEN
LIBSQL_DATABASE_URL
```
### Special Note for Windows Users
This library defaults to using the embedded driver for better performance and closer parity with production environments. However, due to the lack of support for embedded LibSQL on Windows, this library uses a remote driver when running on Windows. Special build tags are included to ensure seamless operation across platforms.

View File

@ -21,13 +21,14 @@ type LibSqlDB struct {
syncInterval time.Duration // only used for embedded replica
encryptionKey string // only used for embedded replica
readYourWrites *bool // only used for embedded replica
useMigrations bool
migrationFiles embed.FS
migrations []Migrations
}
func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*LibSqlDB, error) {
func NewLibSqlDB(primaryUrl string, opts ...Options) (*LibSqlDB, error) {
l := &LibSqlDB{}
_migrationFiles = migrationFiles
for _, option := range opts {
err := option(l)
if err != nil {
@ -45,14 +46,16 @@ func NewLibSqlDB(primaryUrl string, migrationFiles embed.FS, opts ...Options) (*
return nil, fmt.Errorf("error setting up LibSQL db | %w", err)
}
err = setupMigrations()
if err != nil {
return nil, fmt.Errorf("error setting up migrations | %w", err)
if l.useMigrations {
err = l.setupMigrations()
if err != nil {
return nil, fmt.Errorf("error setting up migrations | %w", err)
}
}
return &LibSqlDB{
DB: db,
}, nil
l.DB = db
return l, nil
}
func (t *LibSqlDB) Close() error {