Skip to content

Commit 9d83956

Browse files
committed
feat: Add sqlite as a storage backend
First throw at adding sqlite as storage backend for the syncserver and the tokenserver. There is probably some duplicated code between: - syncstorage-mysql and syncstorage-sqlite - tokenserver-db-mysql and tokenserver-db-sqlite tokenserver-db-sqlite probably contains Mysql-specific SQL that might break Sqlite when ran. Squashed commit of the following: commit 1047197 Author: Eragon <[email protected]> Date: Wed Mar 6 00:24:07 2024 +0100 fix: Fix default for tokenserver-db commit 5e2a745 Author: Eragon <[email protected]> Date: Sun Feb 11 22:00:46 2024 +0100 tokenserver-db defaults to use mysql as db backend commit a587787 Author: Eragon <[email protected]> Date: Sun Feb 11 21:47:55 2024 +0100 Run cargo fmt commit c8c1458 Author: Eragon <[email protected]> Date: Sun Feb 11 20:32:19 2024 +0100 Better logging of migrations commit e2b8563 Author: Eragon <[email protected]> Date: Tue Jan 30 00:36:11 2024 +0100 wip: At least it runs now commit bd24d7c Author: Eragon <[email protected]> Date: Mon Jan 22 11:20:38 2024 +0100 lll commit 07ba38f Author: Eragon <[email protected]> Date: Fri Jan 19 14:35:20 2024 +0100 wip: First throw at adding sqlite as a storage backend
1 parent 8faf728 commit 9d83956

File tree

58 files changed

+4888
-264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+4888
-264
lines changed

Cargo.lock

Lines changed: 283 additions & 170 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ members = [
99
"syncstorage-mysql",
1010
"syncstorage-settings",
1111
"syncstorage-spanner",
12+
"syncstorage-sqlite",
1213
"tokenserver-auth",
1314
"tokenserver-common",
1415
"tokenserver-db",
16+
"tokenserver-db-common",
17+
"tokenserver-db-mysql",
18+
"tokenserver-db-sqlite",
1519
"tokenserver-settings",
1620
"syncserver",
1721
]
@@ -23,6 +27,7 @@ authors = [
2327
"Ben Bangert <[email protected]>",
2428
"Phil Jenvey <[email protected]>",
2529
"Mozilla Services Engineering <[email protected]>",
30+
"Eragon <[email protected]>",
2631
]
2732
edition = "2021"
2833
license = "MPL-2.0"

Makefile

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ PATH_TO_GRPC_CERT = ../server-syncstorage/local/lib/python2.7/site-packages/grpc
1313
SRC_ROOT = $(shell pwd)
1414
PYTHON_SITE_PACKGES = $(shell $(SRC_ROOT)/venv/bin/python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
1515

16+
clippy_sqlite:
17+
# Matches what's run in circleci
18+
cargo clippy --workspace --all-targets --no-default-features --features=syncstorage-db/sqlite,tokenserver-db/sqlite --features=py_verifier -- -D warnings
19+
1620
clippy_mysql:
1721
# Matches what's run in circleci
18-
cargo clippy --workspace --all-targets --no-default-features --features=syncstorage-db/mysql --features=py_verifier -- -D warnings
22+
cargo clippy --workspace --all-targets --no-default-features --features=syncstorage-db/mysql,tokenserver-db/mysql --features=py_verifier -- -D warnings
1923

2024
clippy_spanner:
2125
# Matches what's run in circleci
22-
cargo clippy --workspace --all-targets --no-default-features --features=syncstorage-db/spanner --features=py_verifier -- -D warnings
26+
cargo clippy --workspace --all-targets --no-default-features --features=syncstorage-db/spanner,tokenserver-db/mysql --features=py_verifier -- -D warnings
2327

2428
clean:
2529
cargo clean
@@ -53,23 +57,38 @@ run_mysql: python
5357
# See https://github.com/PyO3/pyo3/issues/1741 for discussion re: why we need to set the
5458
# below env var
5559
PYTHONPATH=$(PYTHON_SITE_PACKGES) \
56-
RUST_LOG=debug \
60+
RUST_LOG=debug \
5761
RUST_BACKTRACE=full \
58-
cargo run --no-default-features --features=syncstorage-db/mysql --features=py_verifier -- --config config/local.toml
62+
cargo run --no-default-features --features=syncstorage-db/mysql,tokenserver-db/mysql --features=py_verifier -- --config config/local.toml
63+
64+
run_sqlite: python
65+
PATH="./venv/bin:$(PATH)" \
66+
# See https://github.com/PyO3/pyo3/issues/1741 for discussion re: why we need to set the
67+
# below env var
68+
PYTHONPATH=$(PYTHON_SITE_PACKGES) \
69+
RUST_LOG=debug \
70+
RUST_BACKTRACE=full \
71+
cargo run --no-default-features --features=syncstorage-db/sqlite,tokenserver-db/sqlite --features=py_verifier -- --config config/local.toml
5972

6073
run_spanner: python
6174
GOOGLE_APPLICATION_CREDENTIALS=$(PATH_TO_SYNC_SPANNER_KEYS) \
6275
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=$(PATH_TO_GRPC_CERT) \
6376
# See https://github.com/PyO3/pyo3/issues/1741 for discussion re: why we need to set the
6477
# below env var
6578
PYTHONPATH=$(PYTHON_SITE_PACKGES) \
66-
PATH="./venv/bin:$(PATH)" \
79+
PATH="./venv/bin:$(PATH)" \
6780
RUST_LOG=debug \
6881
RUST_BACKTRACE=full \
69-
cargo run --no-default-features --features=syncstorage-db/spanner --features=py_verifier -- --config config/local.toml
82+
cargo run --no-default-features --features=syncstorage-db/spanner,tokenserver-db/mysql --features=py_verifier -- --config config/local.toml
7083

71-
test:
84+
test_mysql:
7285
SYNC_SYNCSTORAGE__DATABASE_URL=mysql://sample_user:sample_password@localhost/syncstorage_rs \
7386
SYNC_TOKENSERVER__DATABASE_URL=mysql://sample_user:sample_password@localhost/tokenserver_rs \
7487
RUST_TEST_THREADS=1 \
7588
cargo test --workspace
89+
90+
test_sqlite:
91+
SYNC_SYNCSTORAGE__DATABASE_URL=:memory: \
92+
SYNC_TOKENSERVER__DATABASE_URL=:memory: \
93+
RUST_TEST_THREADS=1 \
94+
cargo test --workspace

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Mozilla Sync Storage built with [Rust](https://rust-lang.org).
1212
- [Local Setup](#local-setup)
1313
- [MySQL](#mysql)
1414
- [Spanner](#spanner)
15+
- [Sqlite](#sqlite)
1516
- [Running via Docker](#running-via-docker)
1617
- [Connecting to Firefox](#connecting-to-firefox)
1718
- [Logging](#logging)
@@ -179,6 +180,15 @@ To run an application server that points to the local Spanner emulator:
179180
SYNC_SYNCSTORAGE__SPANNER_EMULATOR_HOST=localhost:9010 make run_spanner
180181
```
181182

183+
### Sqlite
184+
185+
Setting up the server with sqlite only requires a path to the database file,
186+
which will be created automatically:
187+
188+
`sqlite:path/syncdb.sqlite`
189+
190+
This requires at least sqlite v3.24.0 to be installed on the host system.
191+
182192
### Running via Docker
183193

184194
This requires access to [Google Cloud Rust (raw)](https://crates.io/crates/google-cloud-rust-raw/) crate. Please note that due to interdependencies, you will need to ensure that `grpcio` and `protobuf` match the version used by `google-cloud-rust-raw`.

config/local.example.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ human_logs = 1
55

66
# Example Syncstorage settings:
77
# Example MySQL DSN:
8-
syncstorage.database_url = "mysql://sample_user:sample_password@localhost/syncstorage_rs"
8+
#syncstorage.database_url = "mysql://sample_user:sample_password@localhost/syncstorage_rs"
99
# Example Spanner DSN:
1010
# database_url="spanner://projects/SAMPLE_GCP_PROJECT/instances/SAMPLE_SPANNER_INSTANCE/databases/SAMPLE_SPANNER_DB"
11+
# Example SQLite DSN:
12+
# database_url="sqlite://PATH_TO_FILE/FILE.sqlite"
13+
syncstorage.database_url = ":memory:"
14+
1115
# enable quota limits
1216
syncstorage.enable_quota = 0
1317
# set the quota limit to 2GB.
@@ -16,7 +20,8 @@ syncstorage.enabled = true
1620
syncstorage.limits.max_total_records = 1666 # See issues #298/#333
1721

1822
# Example Tokenserver settings:
19-
tokenserver.database_url = "mysql://sample_user:sample_password@localhost/tokenserver_rs"
23+
#tokenserver.database_url = "mysql://sample_user:sample_password@localhost/tokenserver_rs"
24+
tokenserver.database_url = ":memory:"
2025
tokenserver.enabled = true
2126
tokenserver.fxa_email_domain = "api-accounts.stage.mozaws.net"
2227
tokenserver.fxa_metrics_hash_secret = "INSERT_SECRET_KEY_HERE"
@@ -26,5 +31,5 @@ tokenserver.fxa_browserid_issuer = "https://api-accounts.stage.mozaws.net"
2631
tokenserver.fxa_browserid_server_url = "https://verifier.stage.mozaws.net/v2"
2732

2833
# cors settings
29-
# cors_allowed_origin = "localhost"
34+
cors_allowed_origin = "localhost"
3035
# cors_max_age = 86400

syncserver-db-common/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ http.workspace=true
1212
thiserror.workspace=true
1313

1414
deadpool = { git = "https://github.com/mozilla-services/deadpool", tag = "deadpool-v0.7.0" }
15-
diesel = { version = "1.4", features = ["mysql", "r2d2"] }
16-
diesel_migrations = { version = "1.4.0", features = ["mysql"] }
15+
diesel = { version = "1.4", features = ["mysql", "sqlite","r2d2"] }
16+
diesel_migrations = { version = "1.4.0", features = ["mysql", "sqlite"] }
1717
syncserver-common = { path = "../syncserver-common" }

syncserver-db-common/src/error.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use thiserror::Error;
88
/// Error specific to any MySQL database backend. These errors are not related to the syncstorage
99
/// or tokenserver application logic; rather, they are lower-level errors arising from diesel.
1010
#[derive(Debug)]
11-
pub struct MysqlError {
12-
kind: MysqlErrorKind,
11+
pub struct SqlError {
12+
kind: SqlErrorKind,
1313
pub status: StatusCode,
1414
pub backtrace: Backtrace,
1515
}
1616

1717
#[derive(Debug, Error)]
18-
enum MysqlErrorKind {
18+
enum SqlErrorKind {
1919
#[error("A database error occurred: {}", _0)]
2020
DieselQuery(#[from] diesel::result::Error),
2121

@@ -29,8 +29,8 @@ enum MysqlErrorKind {
2929
Migration(diesel_migrations::RunMigrationsError),
3030
}
3131

32-
impl From<MysqlErrorKind> for MysqlError {
33-
fn from(kind: MysqlErrorKind) -> Self {
32+
impl From<SqlErrorKind> for SqlError {
33+
fn from(kind: SqlErrorKind) -> Self {
3434
Self {
3535
kind,
3636
status: StatusCode::INTERNAL_SERVER_ERROR,
@@ -39,21 +39,17 @@ impl From<MysqlErrorKind> for MysqlError {
3939
}
4040
}
4141

42-
impl_fmt_display!(MysqlError, MysqlErrorKind);
42+
impl_fmt_display!(SqlError, SqlErrorKind);
4343

44-
from_error!(
45-
diesel::result::Error,
46-
MysqlError,
47-
MysqlErrorKind::DieselQuery
48-
);
44+
from_error!(diesel::result::Error, SqlError, SqlErrorKind::DieselQuery);
4945
from_error!(
5046
diesel::result::ConnectionError,
51-
MysqlError,
52-
MysqlErrorKind::DieselConnection
47+
SqlError,
48+
SqlErrorKind::DieselConnection
5349
);
54-
from_error!(diesel::r2d2::PoolError, MysqlError, MysqlErrorKind::Pool);
50+
from_error!(diesel::r2d2::PoolError, SqlError, SqlErrorKind::Pool);
5551
from_error!(
5652
diesel_migrations::RunMigrationsError,
57-
MysqlError,
58-
MysqlErrorKind::Migration
53+
SqlError,
54+
SqlErrorKind::Migration
5955
);

syncserver-db-common/src/test.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use diesel::{
22
mysql::MysqlConnection,
33
r2d2::{CustomizeConnection, Error as PoolError},
4+
sqlite::SqliteConnection,
45
Connection,
56
};
67

@@ -12,3 +13,9 @@ impl CustomizeConnection<MysqlConnection, PoolError> for TestTransactionCustomiz
1213
conn.begin_test_transaction().map_err(PoolError::QueryError)
1314
}
1415
}
16+
17+
impl CustomizeConnection<SqliteConnection, PoolError> for TestTransactionCustomizer {
18+
fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), PoolError> {
19+
conn.begin_test_transaction().map_err(PoolError::QueryError)
20+
}
21+
}

syncserver/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ no_auth = []
6565
py_verifier = ["tokenserver-auth/py"]
6666
mysql = ["syncstorage-db/mysql"]
6767
spanner = ["syncstorage-db/spanner"]
68+
sqlite = ["syncstorage-db/sqlite"]

syncserver/src/db/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pub mod mock;
44
pub mod mysql;
55
pub mod spanner;
6+
pub mod sqlite;
67
#[cfg(test)]
78
mod tests;
89
pub mod transaction;
@@ -35,6 +36,11 @@ pub async fn pool_from_settings(
3536
"spanner" => Box::new(
3637
spanner::pool::SpannerDbPool::new(settings, metrics, blocking_threadpool).await?,
3738
),
39+
"sqlite" => Box::new(sqlite::pool::SqliteDbPool::new(
40+
settings,
41+
metrics,
42+
blocking_threadpool,
43+
)?),
3844
_ => Err(DbErrorKind::InvalidUrl(settings.database_url.to_owned()))?,
3945
})
4046
}

0 commit comments

Comments
 (0)