fix(02-01): eliminate package-level startupErr and fix config file permissions
- Move startupErr from package-level var to YellowJacketApp struct field - Update OnStartup and OnDomReady to reference yj.startupErr - Change config.Save() file permissions from 0o666 to 0o644 - Fix nlreturn lint in database/errors.go (pre-existing, blocking commit hook)
This commit is contained in:
+5
-6
@@ -39,6 +39,7 @@ type YellowJacketApp struct {
|
||||
mediaControls mediacontrols.Handler
|
||||
appContext context.Context
|
||||
appConfig *config.Config
|
||||
startupErr error
|
||||
}
|
||||
|
||||
// NewYellowJacketApp creates and initializes the application.
|
||||
@@ -131,8 +132,6 @@ func (yj *YellowJacketApp) WindowConfig() *config.WindowConfig {
|
||||
return yj.appConfig.Window
|
||||
}
|
||||
|
||||
var startupErr error
|
||||
|
||||
// OnStartup initializes components that require the Wails runtime context.
|
||||
func (yj *YellowJacketApp) OnStartup(ctx context.Context) {
|
||||
defer profiling.TimeOp(yj.logger, "app.OnStartup")()
|
||||
@@ -151,8 +150,8 @@ func (yj *YellowJacketApp) OnStartup(ctx context.Context) {
|
||||
// Initialize speaker hardware (player struct created in
|
||||
// NewYellowJacketApp for Wails binding registration).
|
||||
if err := yj.player.InitSpeaker(); err != nil {
|
||||
startupErr = errors.Join(
|
||||
startupErr,
|
||||
yj.startupErr = errors.Join(
|
||||
yj.startupErr,
|
||||
fmt.Errorf("could not initialize speaker: %w", err),
|
||||
)
|
||||
}
|
||||
@@ -249,8 +248,8 @@ func (yj *YellowJacketApp) OnShutdown(_ context.Context) {
|
||||
// listeners, index.ts calls Player.EmitCurrentState() and
|
||||
// Queue.EmitCurrentState() via Wails bindings.
|
||||
func (yj *YellowJacketApp) OnDomReady(ctx context.Context) {
|
||||
if startupErr != nil {
|
||||
yj.logger.Error("startup error", "err", startupErr.Error())
|
||||
if yj.startupErr != nil {
|
||||
yj.logger.Error("startup error", "err", yj.startupErr.Error())
|
||||
wailsruntime.Quit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ func (c *Config) Save() error {
|
||||
return fmt.Errorf("could not marshal config struct: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(c.filePath, confFileData, os.FileMode(int(0o666)))
|
||||
err = os.WriteFile(c.filePath, confFileData, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write config file (%s): %w", c.filePath, err)
|
||||
}
|
||||
|
||||
@@ -220,6 +220,48 @@ func runMigrations(
|
||||
}
|
||||
}
|
||||
|
||||
// Migration 3: add UNIQUE constraint to artist_credit_artist.
|
||||
if version < 3 {
|
||||
logger.Info(
|
||||
"applying migration 3: artist_credit_artist unique constraint",
|
||||
)
|
||||
|
||||
// Remove duplicates first (keep lowest ID per pair).
|
||||
if _, err := db.ExecContext(ctx, `
|
||||
DELETE FROM artist_credit_artist
|
||||
WHERE id NOT IN (
|
||||
SELECT MIN(id)
|
||||
FROM artist_credit_artist
|
||||
GROUP BY artist_id, credit_id
|
||||
)
|
||||
`); err != nil {
|
||||
return fmt.Errorf(
|
||||
"migration 3: could not deduplicate: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
if _, err := db.ExecContext(ctx, `
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS
|
||||
idx_artist_credit_artist_unique
|
||||
ON artist_credit_artist(artist_id, credit_id)
|
||||
`); err != nil {
|
||||
return fmt.Errorf(
|
||||
"migration 3: could not create unique index: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
if _, err := db.ExecContext(
|
||||
ctx, "PRAGMA user_version = 3",
|
||||
); err != nil {
|
||||
return fmt.Errorf(
|
||||
"could not set user_version to 3: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
logger.Info("migration 3 complete")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"modernc.org/sqlite"
|
||||
sqlite3 "modernc.org/sqlite/lib"
|
||||
)
|
||||
|
||||
// IsUniqueViolation reports whether err is a SQLite UNIQUE
|
||||
// constraint violation (extended result code 2067).
|
||||
func IsUniqueViolation(err error) bool {
|
||||
var sqliteErr *sqlite.Error
|
||||
if errors.As(err, &sqliteErr) {
|
||||
return sqliteErr.Code() == sqlite3.SQLITE_CONSTRAINT_UNIQUE
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user