Files
mining-client/internal/db/db.go
2025-12-01 15:45:05 +08:00

146 lines
4.0 KiB
Go

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
}