mirror of
https://github.com/ditatompel/xmr-remote-nodes.git
synced 2024-11-16 17:07:36 +00:00
274 lines
7.2 KiB
Go
274 lines
7.2 KiB
Go
package database
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
)
|
|
|
|
type migrateFn func(*DB) error
|
|
|
|
var dbMigrate = [...]migrateFn{v1, v2, v3}
|
|
|
|
func MigrateDb(db *DB) error {
|
|
version := getSchemaVersion(db)
|
|
if version < 0 {
|
|
return fmt.Errorf("[DB] can't get database schema version")
|
|
} else if version == 0 {
|
|
slog.Warn("[DB] No database schema version found, creating schema version 1")
|
|
} else {
|
|
slog.Info(fmt.Sprintf("[DB] Current database schema version: %d", version))
|
|
}
|
|
|
|
for ; version < len(dbMigrate); version++ {
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
migrateFn := dbMigrate[version]
|
|
slog.Info(fmt.Sprintf("[DB] Migrating database schema version %d", version+1))
|
|
|
|
if err := migrateFn(db); err != nil {
|
|
if err := tx.Rollback(); err != nil {
|
|
return err
|
|
}
|
|
return err
|
|
}
|
|
if err := setSchemaVersion(db, version+1); err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func getSchemaVersion(db *DB) int {
|
|
_, err := db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS tbl_schema_ver (
|
|
version INT(5) UNSIGNED NOT NULL
|
|
)`)
|
|
if err != nil {
|
|
return -1
|
|
}
|
|
version := 0
|
|
if err := db.Get(&version, `SELECT version FROM tbl_schema_ver`); err != nil {
|
|
return -1
|
|
}
|
|
return version
|
|
}
|
|
|
|
func setSchemaVersion(db *DB, version int) error {
|
|
_, err := db.Exec(`DELETE FROM tbl_schema_ver`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = db.Exec(`INSERT INTO tbl_schema_ver (version) VALUES (?)`, version)
|
|
return err
|
|
}
|
|
|
|
func v1(db *DB) error {
|
|
slog.Debug("[DB] Migrating database schema version 1")
|
|
|
|
// table: tbl_cron
|
|
slog.Debug("[DB] Creating table: tbl_cron")
|
|
_, err := db.Exec(`
|
|
CREATE TABLE tbl_cron (
|
|
id INT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
title VARCHAR(255) NOT NULL DEFAULT '',
|
|
slug VARCHAR(255) NOT NULL DEFAULT '',
|
|
description VARCHAR(255) NOT NULL DEFAULT '',
|
|
run_every INT(8) UNSIGNED NOT NULL DEFAULT 60 COMMENT 'in seconds',
|
|
last_run INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
next_run INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
run_time FLOAT(7,3) UNSIGNED NOT NULL DEFAULT 0.000,
|
|
cron_state TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
|
is_enabled TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
|
PRIMARY KEY (id)
|
|
)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
slog.Debug("[DB] Adding default cron jobs to table: tbl_cron")
|
|
_, err = db.Exec(`
|
|
INSERT INTO tbl_cron (
|
|
title,
|
|
slug,
|
|
description,
|
|
run_every
|
|
) VALUES (
|
|
'Delete old probe logs',
|
|
'delete_old_probe_logs',
|
|
'Delete old probe log from the database',
|
|
120
|
|
);`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// table: tbl_node
|
|
slog.Debug("[DB] Creating table: tbl_node")
|
|
_, err = db.Exec(`
|
|
CREATE TABLE tbl_node (
|
|
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
protocol VARCHAR(6) NOT NULL DEFAULT 'http' COMMENT 'http | https',
|
|
hostname VARCHAR(255) NOT NULL,
|
|
port INT(6) UNSIGNED NOT NULL DEFAULT 0,
|
|
is_tor TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
|
is_available TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
|
nettype VARCHAR(100) NOT NULL COMMENT 'mainnet | stagenet | testnet',
|
|
height BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
adjusted_time BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
database_size BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
difficulty BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
version VARCHAR(200) NOT NULL DEFAULT '',
|
|
uptime float(5,2) UNSIGNED NOT NULL DEFAULT 0.00,
|
|
estimate_fee INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
ip_addr VARCHAR(200) NOT NULL,
|
|
asn INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
asn_name VARCHAR(255) NOT NULL DEFAULT '',
|
|
country VARCHAR(100) NOT NULL DEFAULT '',
|
|
country_name VARCHAR(255) NOT NULL DEFAULT '',
|
|
city VARCHAR(255) NOT NULL DEFAULT '',
|
|
lat FLOAT NOT NULL DEFAULT 0 COMMENT 'latitude',
|
|
lon FLOAT NOT NULL DEFAULT 0 COMMENT 'longitude',
|
|
date_entered INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
last_checked INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
last_check_status TEXT DEFAULT NULL,
|
|
cors_capable TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (id)
|
|
)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// NOTE: If you need list of public nodes (for example to seed `tbl_node`
|
|
// data for integration test), you can use `public_nodes` command from
|
|
// `monero-wallet-cli` app. Eg testnet public nodes:
|
|
// echo "public_nodes" | monero-wallet-cli --testnet --wallet-file=wallet --daemon-address=testnet.xmr.ditatompel.com:443 --password-file=pass_file
|
|
|
|
// table: tbl_prober
|
|
slog.Debug("[DB] Creating table: tbl_prober")
|
|
_, err = db.Exec(`
|
|
CREATE TABLE tbl_prober (
|
|
id INT(9) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
name VARCHAR(255) NOT NULL,
|
|
api_key VARCHAR(36) NOT NULL,
|
|
last_submit_ts INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (id)
|
|
)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Debug("[DB] Adding unique key to table: tbl_prober")
|
|
_, err = db.Exec(`ALTER TABLE tbl_prober ADD UNIQUE KEY (api_key)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// table: tbl_probe_log
|
|
slog.Debug("[DB] Creating table: tbl_probe_log")
|
|
_, err = db.Exec(`
|
|
CREATE TABLE tbl_probe_log (
|
|
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
node_id INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
prober_id INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
is_available TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
|
height BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
adjusted_time BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
database_size BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
difficulty BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
|
estimate_fee INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
date_checked INT(11) UNSIGNED NOT NULL DEFAULT 0,
|
|
failed_reason TEXT NOT NULL DEFAULT '',
|
|
fetch_runtime FLOAT(5,2) UNSIGNED NOT NULL DEFAULT 0.00,
|
|
PRIMARY KEY (id)
|
|
)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
slog.Debug("[DB] Adding key to table: tbl_probe_log")
|
|
_, err = db.Exec(`ALTER TABLE tbl_probe_log ADD KEY (node_id)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func v2(db *DB) error {
|
|
slog.Debug("[DB] Migrating database schema version 2")
|
|
|
|
// table: tbl_fee
|
|
slog.Debug("[DB] Creating table: tbl_fee")
|
|
_, err := db.Exec(`
|
|
CREATE TABLE tbl_fee (
|
|
nettype VARCHAR(100) NOT NULL DEFAULT '',
|
|
estimate_fee INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
node_count INT(9) UNSIGNED NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (nettype)
|
|
)`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
slog.Debug("[DB] Adding default fee to table: tbl_fee")
|
|
_, err = db.Exec(`
|
|
INSERT INTO tbl_fee (
|
|
nettype,
|
|
estimate_fee,
|
|
node_count
|
|
) VALUES (
|
|
'mainnet',
|
|
0,
|
|
0
|
|
), (
|
|
'stagenet',
|
|
0,
|
|
0
|
|
), (
|
|
'testnet',
|
|
0,
|
|
0
|
|
);`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.Debug("[DB] Adding majority fee cron jobs to table: tbl_cron")
|
|
_, err = db.Exec(`
|
|
INSERT INTO tbl_cron (
|
|
title,
|
|
slug,
|
|
description,
|
|
run_every
|
|
) VALUES (
|
|
'Calculate majority fee',
|
|
'calculate_majority_fee',
|
|
'Calculate majority Monero fee',
|
|
300
|
|
);`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func v3(db *DB) error {
|
|
slog.Debug("[DB] Migrating database schema version 3")
|
|
|
|
// table: tbl_node
|
|
slog.Debug("[DB] Adding additional columns to tbl_node")
|
|
_, err := db.Exec(`
|
|
ALTER TABLE tbl_node
|
|
ADD COLUMN ipv6_only TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER cors_capable,
|
|
ADD COLUMN ip_addresses TEXT NOT NULL DEFAULT '' AFTER cors_capable;`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|