From 0323212d9da0a182b113540582df2dc3fa760710 Mon Sep 17 00:00:00 2001 From: JurajKubrican Date: Fri, 22 Aug 2025 18:27:43 +0200 Subject: [PATCH] real db migrations --- go.mod | 4 ++ go.sum | 9 ++++ .../000001_create_user_visits_table.down.sql | 4 ++ .../000001_create_user_visits_table.up.sql | 15 ++++++ src/migrations/manager.go | 52 +++++++++++++++++++ src/tracking/tracking-store.go | 14 +++-- 6 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 migrations/tracking/000001_create_user_visits_table.down.sql create mode 100644 migrations/tracking/000001_create_user_visits_table.up.sql create mode 100644 src/migrations/manager.go diff --git a/go.mod b/go.mod index c3f8ff6..6da7f2d 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/golang-migrate/migrate/v4 v4.18.3 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mileusna/useragent v1.3.5 // indirect @@ -27,6 +30,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect + go.uber.org/atomic v1.11.0 // indirect golang.org/x/crypto v0.40.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/sys v0.34.0 // indirect diff --git a/go.sum b/go.sum index e620551..0dc8aea 100644 --- a/go.sum +++ b/go.sum @@ -6,12 +6,19 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= +github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -50,6 +57,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= diff --git a/migrations/tracking/000001_create_user_visits_table.down.sql b/migrations/tracking/000001_create_user_visits_table.down.sql new file mode 100644 index 0000000..487c2ce --- /dev/null +++ b/migrations/tracking/000001_create_user_visits_table.down.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS idx_user_visits_path; +DROP INDEX IF EXISTS idx_user_visits_fingerprint; +DROP INDEX IF EXISTS idx_user_visits_timestamp; +DROP TABLE IF EXISTS user_visits; diff --git a/migrations/tracking/000001_create_user_visits_table.up.sql b/migrations/tracking/000001_create_user_visits_table.up.sql new file mode 100644 index 0000000..9e996a8 --- /dev/null +++ b/migrations/tracking/000001_create_user_visits_table.up.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS user_visits ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ip TEXT NOT NULL, + path TEXT NOT NULL, + method TEXT NOT NULL, + fingerprint TEXT, + user_agent TEXT, + referer TEXT, + accept_language TEXT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX IF NOT EXISTS idx_user_visits_timestamp ON user_visits(timestamp); +CREATE INDEX IF NOT EXISTS idx_user_visits_fingerprint ON user_visits(fingerprint); +CREATE INDEX IF NOT EXISTS idx_user_visits_path ON user_visits(path); diff --git a/src/migrations/manager.go b/src/migrations/manager.go new file mode 100644 index 0000000..d5b29c1 --- /dev/null +++ b/src/migrations/manager.go @@ -0,0 +1,52 @@ +package migrations + +import ( + "database/sql" + "fmt" + + "github.com/golang-migrate/migrate/v4" + "github.com/golang-migrate/migrate/v4/database/sqlite" + _ "github.com/golang-migrate/migrate/v4/source/file" +) + +type MigrationManager struct { + databases map[string]*sql.DB +} + +func NewMigrationManager() *MigrationManager { + return &MigrationManager{ + databases: make(map[string]*sql.DB), + } +} + +// RegisterDatabase registers a database connection for migrations +func (mm *MigrationManager) RegisterDatabase(name string, db *sql.DB) { + mm.databases[name] = db +} + +// RunMigrations runs migrations for a specific database +func (mm *MigrationManager) RunMigrations(dbName string) error { + db, exists := mm.databases[dbName] + if !exists { + return fmt.Errorf("database %s not registered", dbName) + } + + driver, err := sqlite.WithInstance(db, &sqlite.Config{}) + if err != nil { + return fmt.Errorf("failed to create database driver: %w", err) + } + + migrationPath := fmt.Sprintf("file://migrations/%s", dbName) + m, err := migrate.NewWithDatabaseInstance(migrationPath, "sqlite", driver) + if err != nil { + return fmt.Errorf("failed to create migration instance: %w", err) + } + + // Run migrations + if err := m.Up(); err != nil && err != migrate.ErrNoChange { + return fmt.Errorf("failed to run migrations: %w", err) + } + + fmt.Printf("Migrations completed successfully for database: %s\n", dbName) + return nil +} diff --git a/src/tracking/tracking-store.go b/src/tracking/tracking-store.go index 4f401f5..846b6da 100644 --- a/src/tracking/tracking-store.go +++ b/src/tracking/tracking-store.go @@ -6,6 +6,7 @@ import ( "time" "github.com/labstack/echo/v4" + "knet.sk/src/migrations" _ "modernc.org/sqlite" ) @@ -43,9 +44,16 @@ func StartTrackingService() *TrackingService { db.SetMaxIdleConns(1) trackingService = &TrackingService{db: db} - err = trackingService.initDB() - if err != nil { - panic(err) + + // Run migrations instead of manual table creation + migrationManager := migrations.NewMigrationManager() + migrationManager.RegisterDatabase("tracking", db) + if err := migrationManager.RunMigrations("tracking"); err != nil { + println("Warning: Migration failed:", err.Error()) + // Fallback to manual table creation for backward compatibility + if err := trackingService.initDB(); err != nil { + panic(err) + } } }