summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortom barrett <spalf0@gmail.com>2019-04-01 10:54:28 -0500
committertom barrett <spalf0@gmail.com>2019-04-01 10:54:28 -0500
commit810c77ba30c65215c2d5e4b6f8a73f3b73e2b152 (patch)
tree3666053d51c598f701733231244104f536a4d24a
parent95b3508d2397b64c7c63bd3586e524998f194e36 (diff)
database backup and restore
-rw-r--r--Vagrantfile2
-rw-r--r--migrations/1_create_masses/up.sql4
-rw-r--r--src/bin/client.rs2
-rw-r--r--src/bin/server.rs52
-rw-r--r--src/constants.rs1
-rw-r--r--src/mass.rs2
-rw-r--r--src/math.rs3
-rw-r--r--tests/tests.rs17
8 files changed, 72 insertions, 11 deletions
diff --git a/Vagrantfile b/Vagrantfile
index efd37f1..d4c4268 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -1,5 +1,5 @@
Vagrant.configure("2") do |config|
- config.vm.box = "bento/debian-9.4"
+ config.vm.box = "bento/debian-9.6"
config.vm.provision :shell, path: "postgres/bootstrap.sh"
config.vm.network "forwarded_port", guest: 5432, host: 5432
config.ssh.forward_x11 = true
diff --git a/migrations/1_create_masses/up.sql b/migrations/1_create_masses/up.sql
index f666e09..1f10915 100644
--- a/migrations/1_create_masses/up.sql
+++ b/migrations/1_create_masses/up.sql
@@ -1,5 +1,5 @@
CREATE TABLE masses (
id SERIAL PRIMARY KEY,
- name VARCHAR NOT NULL,
- mass VARCHAR NOT NULL
+ name TEXT UNIQUE NOT NULL,
+ mass TEXT NOT NULL
)
diff --git a/src/bin/client.rs b/src/bin/client.rs
index a91c2dc..9f5fbfc 100644
--- a/src/bin/client.rs
+++ b/src/bin/client.rs
@@ -34,7 +34,7 @@ fn main() {
let server;
let mut name = String::new();
- let matches = App::new("space")
+ let matches = App::new("space client")
.subcommand(SubCommand::with_name("mining"))
.subcommand(SubCommand::with_name("engines"))
.subcommand(SubCommand::with_name("refinery"))
diff --git a/src/bin/server.rs b/src/bin/server.rs
index 881cc4d..708cd3e 100644
--- a/src/bin/server.rs
+++ b/src/bin/server.rs
@@ -1,14 +1,19 @@
extern crate space;
+use clap::{App, SubCommand};
+use diesel::pg::PgConnection;
+use diesel::prelude::*;
use std::collections::HashMap;
use std::io::Write;
use std::net::TcpListener;
-use std::thread::sleep;
+use std::thread::{sleep, spawn};
use std::time::{Duration, Instant};
use space::constants;
-use space::mass::Mass;
-use space::math::rand_name;
+use space::mass::{Mass, MassEntry};
+use space::math::{get_db_url, rand_name};
+use space::schema::masses::dsl::masses as db_masses;
+use space::schema::masses::dsl::name as name_column;
use space::server_connection::ServerConnection;
fn populate() -> HashMap<String, Mass> {
@@ -21,12 +26,44 @@ fn populate() -> HashMap<String, Mass> {
masses
}
+fn backup(masses: HashMap<String, Mass>) {
+ let connection = PgConnection::establish(&get_db_url()).expect("Cannot connect");
+ for (name, mass) in masses {
+ let mass_entry = mass.to_mass_entry(name.to_string());
+ diesel::insert_into(db_masses)
+ .values(&mass_entry)
+ .on_conflict(name_column)
+ .do_update()
+ .set(&mass_entry)
+ .execute(&connection)
+ .expect("Cannot backup");
+ }
+}
+
+fn restore() -> HashMap<String, Mass> {
+ let connection = PgConnection::establish(&get_db_url()).expect("Cannot connect");
+ db_masses
+ .load::<MassEntry>(&connection)
+ .expect("Cannot query, are you sure you can restore?")
+ .iter()
+ .map(|mass_entry| mass_entry.to_mass())
+ .collect()
+}
+
fn main() {
let listener = TcpListener::bind("localhost:6000").unwrap();
listener.set_nonblocking(true).unwrap();
- let mut masses = populate();
+ let matches = App::new("space server")
+ .subcommand(SubCommand::with_name("--restore"))
+ .get_matches();
+
+ let mut masses = match matches.subcommand_name() {
+ Some("--restore") => restore(),
+ _ => populate(),
+ };
+ let mut backup_countdown = constants::BACKUP_COUNTDOWN;
let mut connections: Vec<ServerConnection> = Vec::new();
for stream in listener.incoming() {
match stream {
@@ -64,11 +101,18 @@ fn main() {
masses.insert(key.to_string(), mass);
}
+ if backup_countdown == 0 {
+ let masses_clone = masses.clone();
+ spawn(move || backup(masses_clone));
+ backup_countdown = constants::BACKUP_COUNTDOWN;
+ }
+
if timer.elapsed().as_millis() < constants::LOOP_DURATION_MS.into() {
sleep(Duration::from_millis(
constants::LOOP_DURATION_MS - timer.elapsed().as_millis() as u64,
));
}
+ backup_countdown -= 1;
}
}
}
diff --git a/src/constants.rs b/src/constants.rs
index ab045bf..ece6a76 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -29,6 +29,7 @@ pub const CRUDE_MINERALS_SIZE: usize = 10;
pub const FLOAT_PRECISION: f64 = 0.001;
pub const LOOP_DURATION_MS: u64 = 100;
+pub const BACKUP_COUNTDOWN: usize = 10;
pub const POSTGRES_USERNAME: &str = "space";
pub const POSTGRES_PASSWORD: &str = "space";
diff --git a/src/mass.rs b/src/mass.rs
index aaf788f..9629e24 100644
--- a/src/mass.rs
+++ b/src/mass.rs
@@ -26,7 +26,7 @@ pub struct Mass {
pub effects: Effects,
}
-#[derive(Queryable, Insertable)]
+#[derive(Queryable, Insertable, Identifiable, AsChangeset, Debug)]
#[table_name = "db_masses"]
pub struct MassEntry {
pub id: Option<i32>,
diff --git a/src/math.rs b/src/math.rs
index 5ba7981..26220d2 100644
--- a/src/math.rs
+++ b/src/math.rs
@@ -2,9 +2,10 @@ extern crate rand;
use self::rand::distributions::Alphanumeric;
use self::rand::Rng;
+use std::iter::repeat;
+
use crate::constants;
use crate::modules::types::ModuleType;
-use std::iter::repeat;
pub fn rand_name() -> String {
repeat(())
diff --git a/tests/tests.rs b/tests/tests.rs
index 7d7449c..4c5c96b 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -535,7 +535,8 @@ mod tests {
.len();
let name = String::from("test");
- let mass = Mass::new_astroid();
+ let mut mass = Mass::new_astroid();
+
diesel::insert_into(db_masses)
.values(&mass.to_mass_entry(name.clone()))
.execute(&connection)
@@ -555,6 +556,20 @@ mod tests {
assert!(mass.position.x == db_mass[0].to_mass().1.position.x);
+ mass.process(&mut HashMap::new());
+
+ diesel::update(db_masses)
+ .set(mass.to_mass_entry(name.clone()))
+ .execute(&connection)
+ .expect("Cannot update");
+
+ let db_mass = db_masses
+ .filter(dsl::name.eq(name.clone()))
+ .load::<MassEntry>(&connection)
+ .expect("Cannot filter");
+
+ assert!(mass.position.x == db_mass[0].to_mass().1.position.x);
+
diesel::delete(db_masses.filter(dsl::name.eq(name)))
.execute(&connection)
.expect("Cannot delete");