Skip to content

Commit d4abcbc

Browse files
authored
feat: separate mysql and mariadb (#49)
* feat: separate mysql and mariadb * feat: separate mysql and mariadb
1 parent 8bf6503 commit d4abcbc

14 files changed

Lines changed: 399 additions & 86 deletions

File tree

databases.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
{
1414
"name": "Test database 2 - MariaDB",
1515
"database": "mariadb",
16-
"type": "mysql",
16+
"type": "mariadb",
1717
"username": "mariadb",
1818
"password": "changeme",
1919
"port": 3306,
@@ -81,6 +81,16 @@
8181
"username": "default",
8282
"host": "db-valkey-auth",
8383
"generated_id": "16678561-ff7e-4c97-8c83-0adeff214681"
84+
},
85+
{
86+
"name": "Test database 12 - Mysql",
87+
"database": "mysqldb",
88+
"type": "mysql",
89+
"username": "mysqldb",
90+
"password": "changeme",
91+
"port": 3306,
92+
"host": "db-mysql",
93+
"generated_id": "16656124-ff7e-4c97-8c83-0adeff214681"
8494
}
8595
]
8696
}

docker-compose.yml

Lines changed: 96 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ services:
1111
# - ./databases.toml:/config/config.toml
1212
- cargo-registry:/usr/local/cargo/registry
1313
- cargo-git:/usr/local/cargo/git
14-
- /var/run/docker.sock:/var/run/docker.sock
15-
14+
# - /var/run/docker.sock:/var/run/docker.sock
1615
# - cargo-target:/app/target
1716
# - sqlite-data:/sqlite-data/workspace/data
1817
# - ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data
@@ -28,35 +27,50 @@ services:
2827
networks:
2928
- portabase
3029

31-
db-postgres:
32-
container_name: db-postgres
33-
image: postgres:17-alpine
30+
# db-postgres:
31+
# container_name: db-postgres
32+
# image: postgres:17-alpine
33+
# ports:
34+
# - "5436:5432"
35+
# volumes:
36+
# - postgres-data:/var/lib/postgresql/data
37+
# environment:
38+
# - POSTGRES_DB=devdb
39+
# - POSTGRES_USER=devuser
40+
# - POSTGRES_PASSWORD=changeme
41+
# networks:
42+
# - portabase
43+
44+
db-mariadb:
45+
container_name: db-mariadb
46+
image: mariadb:latest
3447
ports:
35-
- "5436:5432"
48+
- "3311:3306"
49+
environment:
50+
- MYSQL_DATABASE=mariadb
51+
- MYSQL_USER=mariadb
52+
- MYSQL_PASSWORD=changeme
53+
- MYSQL_RANDOM_ROOT_PASSWORD=yes
3654
volumes:
37-
- postgres-data:/var/lib/postgresql/data
55+
- mariadb-data:/var/lib/mysql
56+
networks:
57+
- portabase
58+
59+
db-mysql:
60+
container_name: db-mysql
61+
image: mysql:9.5
62+
ports:
63+
- "3312:3306"
3864
environment:
39-
- POSTGRES_DB=devdb
40-
- POSTGRES_USER=devuser
41-
- POSTGRES_PASSWORD=changeme
65+
- MYSQL_DATABASE=mysqldb
66+
- MYSQL_USER=mysqldb
67+
- MYSQL_PASSWORD=changeme
68+
- MYSQL_RANDOM_ROOT_PASSWORD=yes
69+
volumes:
70+
- mysql-data:/var/lib/mysql
4271
networks:
4372
- portabase
4473
#
45-
# db-mariadb:
46-
# container_name: db-mariadb
47-
# image: mariadb:latest
48-
# ports:
49-
# - "3311:3306"
50-
# environment:
51-
# - MYSQL_DATABASE=mariadb
52-
# - MYSQL_USER=mariadb
53-
# - MYSQL_PASSWORD=changeme
54-
# - MYSQL_RANDOM_ROOT_PASSWORD=yes
55-
# volumes:
56-
# - mariadb-data:/var/lib/mysql
57-
# networks:
58-
# - portabase
59-
#
6074
#
6175
# db-mongodb-auth:
6276
# container_name: db-mongodb-auth
@@ -105,67 +119,68 @@ services:
105119
# stdin_open: true
106120
# tty: true
107121

108-
db-redis:
109-
image: redis:latest
110-
container_name: db-redis
111-
ports:
112-
- "6379:6379"
113-
volumes:
114-
- redis-data:/data
115-
command: [ "redis-server", "--appendonly", "yes" ]
116-
networks:
117-
- portabase
118-
119-
db-redis-auth:
120-
image: redis:latest
121-
container_name: db-redis-auth
122-
ports:
123-
- "6380:6379"
124-
volumes:
125-
- redis-data-auth:/data
126-
environment:
127-
- REDIS_PASSWORD=supersecurepassword
128-
command: [ "redis-server", "--requirepass", "supersecurepassword", "--appendonly", "yes" ]
129-
networks:
130-
- portabase
131-
132-
db-valkey:
133-
image: valkey/valkey
134-
container_name: db-valkey
135-
environment:
136-
- ALLOW_EMPTY_PASSWORD=yes
137-
ports:
138-
- '6381:6379'
139-
volumes:
140-
- valkey-data:/data
141-
networks:
142-
- portabase
143-
144-
db-valkey-auth:
145-
image: valkey/valkey
146-
container_name: db-valkey-auth
147-
command: >
148-
--requirepass "supersecurepassword"
149-
ports:
150-
- '6382:6379'
151-
volumes:
152-
- valkey-data-auth:/data
153-
networks:
154-
- portabase
122+
# db-redis:
123+
# image: redis:latest
124+
# container_name: db-redis
125+
# ports:
126+
# - "6379:6379"
127+
# volumes:
128+
# - redis-data:/data
129+
# command: [ "redis-server", "--appendonly", "yes" ]
130+
# networks:
131+
# - portabase
132+
#
133+
# db-redis-auth:
134+
# image: redis:latest
135+
# container_name: db-redis-auth
136+
# ports:
137+
# - "6380:6379"
138+
# volumes:
139+
# - redis-data-auth:/data
140+
# environment:
141+
# - REDIS_PASSWORD=supersecurepassword
142+
# command: [ "redis-server", "--requirepass", "supersecurepassword", "--appendonly", "yes" ]
143+
# networks:
144+
# - portabase
145+
#
146+
# db-valkey:
147+
# image: valkey/valkey
148+
# container_name: db-valkey
149+
# environment:
150+
# - ALLOW_EMPTY_PASSWORD=yes
151+
# ports:
152+
# - '6381:6379'
153+
# volumes:
154+
# - valkey-data:/data
155+
# networks:
156+
# - portabase
157+
#
158+
# db-valkey-auth:
159+
# image: valkey/valkey
160+
# container_name: db-valkey-auth
161+
# command: >
162+
# --requirepass "supersecurepassword"
163+
# ports:
164+
# - '6382:6379'
165+
# volumes:
166+
# - valkey-data-auth:/data
167+
# networks:
168+
# - portabase
155169

156170
volumes:
157171
cargo-registry:
158172
cargo-git:
159173
# cargo-target:
160-
postgres-data:
161-
# mariadb-data:
162-
# mongodb-data:
163-
# mongodb-data-auth:
164-
# sqlite-data:
165-
redis-data:
166-
redis-data-auth:
167-
valkey-data:
168-
valkey-data-auth:
174+
# postgres-data:
175+
mariadb-data:
176+
mysql-data:
177+
# mongodb-data:
178+
# mongodb-data-auth:
179+
# sqlite-data:
180+
# redis-data:
181+
# redis-data-auth:
182+
# valkey-data:
183+
# valkey-data-auth:
169184

170185
networks:
171186
portabase:

docker/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
4646
rm -rf /tmp/pg-x64 /tmp/pg-arm && \
4747
chmod +x /usr/lib/postgresql/*/bin/*
4848

49+
4950
# =========================
5051
# MongoDB client binaries
5152
# =========================

src/domain/factory.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::services::config::{DatabaseConfig, DbType};
99
use anyhow::Result;
1010
use std::path::{Path, PathBuf};
1111
use std::sync::Arc;
12+
use crate::domain::mariadb::database::MariaDBDatabase;
1213

1314
#[async_trait::async_trait]
1415
pub trait Database: Send + Sync {
@@ -28,7 +29,7 @@ impl DatabaseFactory {
2829
Arc::new(PostgresDatabase::new(cfg, format))
2930
}
3031
DbType::Mysql => Arc::new(MySQLDatabase::new(cfg)),
31-
DbType::Mariadb => Arc::new(MySQLDatabase::new(cfg)),
32+
DbType::Mariadb => Arc::new(MariaDBDatabase::new(cfg)),
3233
DbType::MongoDB => Arc::new(MongoDatabase::new(cfg)),
3334
DbType::Sqlite => Arc::new(SqliteDatabase::new(cfg)),
3435
DbType::Redis => Arc::new(RedisDatabase::new(cfg)),
@@ -43,7 +44,7 @@ impl DatabaseFactory {
4344
Arc::new(PostgresDatabase::new(cfg, format))
4445
}
4546
DbType::Mysql => Arc::new(MySQLDatabase::new(cfg)),
46-
DbType::Mariadb => Arc::new(MySQLDatabase::new(cfg)),
47+
DbType::Mariadb => Arc::new(MariaDBDatabase::new(cfg)),
4748
DbType::MongoDB => Arc::new(MongoDatabase::new(cfg)),
4849
DbType::Sqlite => Arc::new(SqliteDatabase::new(cfg)),
4950
DbType::Redis => Arc::new(RedisDatabase::new(cfg)),

src/domain/mariadb/backup.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use crate::domain::mariadb::connection::{select_mariadb_path, server_version};
2+
use crate::services::config::DatabaseConfig;
3+
use anyhow::{Context, Result};
4+
use std::collections::HashMap;
5+
use std::path::PathBuf;
6+
use std::process::Command;
7+
use tracing::{debug, error, info};
8+
9+
pub async fn run(
10+
cfg: DatabaseConfig,
11+
backup_dir: PathBuf,
12+
env: HashMap<String, String>,
13+
file_extension: &'static str,
14+
) -> Result<PathBuf> {
15+
tokio::task::spawn_blocking(move || -> Result<PathBuf> {
16+
debug!("Starting backup for database {}", cfg.name);
17+
18+
let version = match futures::executor::block_on(server_version(&cfg)) {
19+
Ok(v) => {
20+
debug!("Mariadb version detected: {}", v);
21+
v
22+
}
23+
Err(e) => {
24+
error!("Failed to get server version for {}: {:?}", cfg.name, e);
25+
return Err(e.into());
26+
}
27+
};
28+
29+
info!("Mariadb version found: {}", version);
30+
31+
let file_path = backup_dir.join(format!("{}{}", cfg.generated_id, file_extension));
32+
33+
let mariadb_dump = select_mariadb_path(&version).join("mariadb-dump");
34+
info!("Mariadb dump found: {}", mariadb_dump.display());
35+
36+
let output = Command::new("mariadb-dump")
37+
.arg("--host").arg(&cfg.host)
38+
.arg("--port").arg(cfg.port.to_string())
39+
.arg("--user").arg(&cfg.username)
40+
.arg("--routines")
41+
.arg("--events")
42+
.arg("--triggers")
43+
.arg("--single-transaction")
44+
.arg("--quick")
45+
.arg("--skip-lock-tables")
46+
.arg("--add-drop-database")
47+
.arg("--databases").arg(&cfg.database)
48+
.arg("--compress")
49+
.arg("--max-allowed-packet=512M")
50+
.arg("--net-buffer-length=16K")
51+
.arg("--default-character-set=utf8mb4")
52+
.arg("-r").arg(&file_path)
53+
.envs(env)
54+
.output()
55+
.with_context(|| format!("Failed to run mariadb-dump for {}", cfg.name))?;
56+
57+
58+
if !output.status.success() {
59+
let stderr = String::from_utf8_lossy(&output.stderr);
60+
anyhow::bail!("Mariadb backup failed for {}: {}", cfg.name, stderr);
61+
}
62+
63+
Ok(file_path)
64+
})
65+
.await?
66+
}

src/domain/mariadb/connection.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use std::path::PathBuf;
2+
use crate::services::config::DatabaseConfig;
3+
use anyhow::Result;
4+
use std::process::Command;
5+
6+
pub async fn server_version(cfg: &DatabaseConfig) -> Result<String> {
7+
let output = Command::new("mariadb")
8+
.arg("--host")
9+
.arg(&cfg.host)
10+
.arg("--port")
11+
.arg(cfg.port.to_string())
12+
.arg("--user")
13+
.arg(&cfg.username)
14+
.arg("-e")
15+
.arg("SELECT VERSION();")
16+
.env("MYSQL_PWD", &cfg.password)
17+
.output()?;
18+
19+
if !output.status.success() {
20+
let stderr = String::from_utf8_lossy(&output.stderr);
21+
anyhow::bail!("Version query failed: {}", stderr);
22+
}
23+
24+
let version = String::from_utf8_lossy(&output.stdout)
25+
.lines()
26+
.nth(1)
27+
.unwrap_or_default()
28+
.trim()
29+
.to_string();
30+
31+
Ok(version)
32+
}
33+
34+
35+
pub fn select_mariadb_path(version: &str) -> PathBuf {
36+
let mut parts = version.split('.');
37+
let major = parts.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(10);
38+
let minor = parts.next().and_then(|v| v.parse::<u32>().ok()).unwrap_or(0);
39+
40+
if major < 10 || (major == 10 && minor <= 6) {
41+
"/usr/local/mariadb-10.6/bin".into()
42+
} else {
43+
"/usr/local/mariadb-12.1/bin".into()
44+
}
45+
}

0 commit comments

Comments
 (0)