Files
BigChef/utils/db.go

158 lines
4.9 KiB
Go

package utils
import (
"path/filepath"
"time"
logger "git.site.quack-lab.dev/dave/cylogger"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
gormlogger "gorm.io/gorm/logger"
)
// dbLogger is a scoped logger for the utils/db package.
var dbLogger = logger.Default.WithPrefix("utils/db")
type DB interface {
DB() *gorm.DB
Raw(sql string, args ...any) *gorm.DB
SaveFile(filePath string, fileData []byte) error
GetFile(filePath string) ([]byte, error)
GetAllFiles() ([]FileSnapshot, error)
RemoveAllFiles() error
}
type FileSnapshot struct {
Date time.Time `gorm:"primaryKey"`
FilePath string `gorm:"primaryKey"`
FileData []byte `gorm:"type:blob"`
}
type DBWrapper struct {
db *gorm.DB
}
var globalDB *DBWrapper
func GetDB() (DB, error) {
getDBLogger := dbLogger.WithPrefix("GetDB")
getDBLogger.Debug("Attempting to get database connection")
var err error
dbFile := filepath.Join("data.sqlite")
getDBLogger.Debug("Opening database file: %q", dbFile)
db, err := gorm.Open(sqlite.Open(dbFile), &gorm.Config{
// SkipDefaultTransaction: true,
PrepareStmt: true,
Logger: gormlogger.Default.LogMode(gormlogger.Silent),
})
if err != nil {
getDBLogger.Error("Failed to open database: %v", err)
return nil, err
}
getDBLogger.Debug("Database opened successfully, running auto migration")
if err := db.AutoMigrate(&FileSnapshot{}); err != nil {
getDBLogger.Error("Auto migration failed: %v", err)
return nil, err
}
getDBLogger.Debug("Auto migration completed")
globalDB = &DBWrapper{db: db}
getDBLogger.Debug("Database wrapper initialized")
return globalDB, nil
}
// Just a wrapper
func (db *DBWrapper) Raw(sql string, args ...any) *gorm.DB {
rawLogger := dbLogger.WithPrefix("Raw").WithField("sql", sql)
rawLogger.Debug("Executing raw SQL query with args: %v", args)
return db.db.Raw(sql, args...)
}
func (db *DBWrapper) DB() *gorm.DB {
dbLogger.WithPrefix("DB").Debug("Returning GORM DB instance")
return db.db
}
func (db *DBWrapper) FileExists(filePath string) (bool, error) {
fileExistsLogger := dbLogger.WithPrefix("FileExists").WithField("filePath", filePath)
fileExistsLogger.Debug("Checking if file exists in database")
var count int64
err := db.db.Model(&FileSnapshot{}).Where("file_path = ?", filePath).Count(&count).Error
if err != nil {
fileExistsLogger.Error("Error checking if file exists: %v", err)
return false, err
}
fileExistsLogger.Debug("File exists: %t", count > 0)
return count > 0, err
}
func (db *DBWrapper) SaveFile(filePath string, fileData []byte) error {
saveFileLogger := dbLogger.WithPrefix("SaveFile").WithField("filePath", filePath)
saveFileLogger.Debug("Attempting to save file to database")
saveFileLogger.Trace("File data length: %d", len(fileData))
exists, err := db.FileExists(filePath)
if err != nil {
saveFileLogger.Error("Error checking if file exists: %v", err)
return err
}
if exists {
saveFileLogger.Debug("File already exists, skipping save")
return nil
}
saveFileLogger.Debug("Creating new file snapshot in database")
err = db.db.Create(&FileSnapshot{
Date: time.Now(),
FilePath: filePath,
FileData: fileData,
}).Error
if err != nil {
saveFileLogger.Error("Failed to create file snapshot: %v", err)
} else {
saveFileLogger.Debug("File saved successfully to database")
}
return err
}
func (db *DBWrapper) GetFile(filePath string) ([]byte, error) {
getFileLogger := dbLogger.WithPrefix("GetFile").WithField("filePath", filePath)
getFileLogger.Debug("Getting file from database")
var fileSnapshot FileSnapshot
err := db.db.Model(&FileSnapshot{}).Where("file_path = ?", filePath).First(&fileSnapshot).Error
if err != nil {
// Downgrade not-found to warning to avoid noisy errors during first run
getFileLogger.Warning("Failed to get file from database: %v", err)
return nil, err
}
getFileLogger.Debug("File found in database")
getFileLogger.Trace("Retrieved file data length: %d", len(fileSnapshot.FileData))
return fileSnapshot.FileData, nil
}
func (db *DBWrapper) GetAllFiles() ([]FileSnapshot, error) {
getAllFilesLogger := dbLogger.WithPrefix("GetAllFiles")
getAllFilesLogger.Debug("Getting all files from database")
var fileSnapshots []FileSnapshot
err := db.db.Model(&FileSnapshot{}).Find(&fileSnapshots).Error
if err != nil {
getAllFilesLogger.Error("Failed to get all files from database: %v", err)
return nil, err
}
getAllFilesLogger.Debug("Found %d files in database", len(fileSnapshots))
getAllFilesLogger.Trace("File snapshots retrieved: %v", fileSnapshots)
return fileSnapshots, nil
}
func (db *DBWrapper) RemoveAllFiles() error {
removeAllFilesLogger := dbLogger.WithPrefix("RemoveAllFiles")
removeAllFilesLogger.Debug("Removing all files from database")
err := db.db.Exec("DELETE FROM file_snapshots").Error
if err != nil {
removeAllFilesLogger.Error("Failed to remove all files from database: %v", err)
} else {
removeAllFilesLogger.Debug("All files removed from database")
}
return err
}