package db import ( message "client/internal/msg" "database/sql" "fmt" "log" _ "github.com/mattn/go-sqlite3" // Import the sqlite3 driver ) type SQLiteServer struct { DB *sql.DB } // NewSQLiteServer creates a new SQLite server instance with an open database connection func NewSQLiteServer() *SQLiteServer { // Open (or create) the SQLite database db, err := sql.Open("sqlite3", "./mining_task.db") if err != nil { log.Fatal(err) return nil } // Create an SQLiteServer instance with the database connection s := &SQLiteServer{ DB: db, } // Initialize the 'task' table if err := s.initTaskTable(); err != nil { log.Fatal(err) return nil } return s } // initTaskTable creates the 'task' table if it doesn't already exist func (s *SQLiteServer) initTaskTable() error { // SQL statement to create the 'task' table if it doesn't exist str := ` CREATE TABLE IF NOT EXISTS task ( id INTEGER PRIMARY KEY AUTOINCREMENT, coin TEXT, algo TEXT, pool TEXT, wallet_mining TEXT, pool_url TEXT, wallet_address TEXT, pool_user TEXT, worker_id TEXT, end_timestamp INTEGER, state INTEGER );` // Execute the query to create the table _, err := s.DB.Exec(str) if err != nil { return fmt.Errorf("failed to create table: %w", err) } return nil } // Close closes the database connection manually when done with it func (s *SQLiteServer) Close() error { // Close the database connection if err := s.DB.Close(); err != nil { return fmt.Errorf("failed to close database: %w", err) } return nil } // LoadMiningTask loads a mining task from the database func (s *SQLiteServer) LoadMiningTask() (bool, message.ConfigurationMiningMsg) { str := "SELECT coin, algo, pool, wallet_mining, pool_url, wallet_address, pool_user, worker_id, end_timestamp FROM task WHERE state = ?;" params := []any{0} // Query the database rows, err := s.DB.Query(str, params...) if err != nil { log.Fatal(err) } defer rows.Close() // Check if exactly one row is returned var task message.ConfigurationMiningMsg if rows.Next() { // Scan the row into the task structure err := rows.Scan(&task.Coin, &task.Algo, &task.Pool, &task.WalletMining, &task.PoolUrl, &task.WalletAddress, &task.PoolUser, &task.WorkerID, &task.EndTimestamp) if err != nil { log.Fatal(err) } // Check if there's more than one row if rows.Next() { // If there are multiple rows, return false with an empty structure return false, message.ConfigurationMiningMsg{} } // If exactly one row is found, return true with the data return true, task } // No rows found, return false with an empty structure return false, message.ConfigurationMiningMsg{} } // InsertMiningTask inserts a new mining task into the database func (s *SQLiteServer) InsertMiningTask(msg message.ConfigurationMiningMsg) error { // SQL INSERT statement str := ` INSERT INTO task (coin, algo, pool, wallet_mining, pool_url, wallet_address, pool_user, worker_id, end_timestamp, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?); ` // Set the state to 0 by default (active or pending) state := 0 // Execute the query _, err := s.DB.Exec(str, msg.Coin, msg.Algo, msg.Pool, msg.WalletMining, msg.PoolUrl, msg.WalletAddress, msg.PoolUser, msg.WorkerID, msg.EndTimestamp, state) if err != nil { return fmt.Errorf("failed to insert mining task: %w", err) } return nil } // FinishMiningTask updates the state of a mining task to 'finished' (state = 1) func (s *SQLiteServer) FinishMiningTask(msg message.ConfigurationMiningMsg) error { // SQL UPDATE statement, matching all fields str := ` UPDATE task SET state = 1 WHERE coin = ? AND algo = ? AND pool = ? AND wallet_mining = ? AND pool_url = ? AND wallet_address = ? AND pool_user = ? AND worker_id = ? AND end_timestamp = ?; ` // Execute the query _, err := s.DB.Exec(str, msg.Coin, msg.Algo, msg.Pool, msg.WalletMining, msg.PoolUrl, msg.WalletAddress, msg.PoolUser, msg.WorkerID, msg.EndTimestamp) if err != nil { return fmt.Errorf("failed to finish mining task: %w", err) } return nil }