From b8ed5b1cdfd3995d828e082f42cea00ab93c3dda Mon Sep 17 00:00:00 2001 From: Sebastian Hugentobler Date: Wed, 26 Jun 2024 16:14:58 +0200 Subject: [PATCH] search database has to be a file, as in-memory dbs are per connection --- Cargo.lock | 50 +++++++++++++++++++++++++++++++++++- Containerfile | 1 + calibre-db/Cargo.toml | 1 + calibre-db/src/data/error.rs | 11 +++++++- calibre-db/src/search.rs | 12 ++++++--- little-hesinde/Cargo.toml | 2 +- little-hesinde/src/lib.rs | 2 +- 7 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4e6cbb..1b0d58c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,6 +201,7 @@ dependencies = [ "r2d2_sqlite", "rusqlite", "serde", + "tempfile", "thiserror", "time", ] @@ -452,6 +453,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -464,6 +475,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + [[package]] name = "flate2" version = "1.0.30" @@ -887,9 +904,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "little-hesinde" -version = "0.2.1" +version = "0.2.3" dependencies = [ "calibre-db", "clap", @@ -1435,6 +1458,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "ryu" version = "1.0.17" @@ -1657,6 +1693,18 @@ dependencies = [ "futures-core", ] +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "tera" version = "1.19.1" diff --git a/Containerfile b/Containerfile index fbdb116..ae22d10 100644 --- a/Containerfile +++ b/Containerfile @@ -19,5 +19,6 @@ FROM scratch COPY --from=builder /app /app CMD ["/app", "--listen-address", "[::]:3000", "--", "/library"] +ENV TMPDIR=/ VOLUME ["/library"] EXPOSE 3000 diff --git a/calibre-db/Cargo.toml b/calibre-db/Cargo.toml index d7d4013..bb810e6 100644 --- a/calibre-db/Cargo.toml +++ b/calibre-db/Cargo.toml @@ -12,5 +12,6 @@ r2d2 = "0.8.10" r2d2_sqlite = "0.24.0" rusqlite = { version = "0.31.0", features = ["bundled", "time"] } serde = { workspace = true } +tempfile = "3.10.1" thiserror = { workspace = true } time = { workspace = true } diff --git a/calibre-db/src/data/error.rs b/calibre-db/src/data/error.rs index ea78a79..681b141 100644 --- a/calibre-db/src/data/error.rs +++ b/calibre-db/src/data/error.rs @@ -1,5 +1,8 @@ //! Error handling for calibre database access. +use std::io; + +use tempfile::PersistError; use thiserror::Error; use time::error::Parse; @@ -16,9 +19,15 @@ pub enum DataStoreError { /// Error connecting to the database. #[error("connection error")] ConnectionError(#[from] r2d2::Error), - /// Error wparsing a datetime from the database. + /// Error parsing a datetime from the database. #[error("failed to parse datetime")] DateTimeError(#[from] Parse), + /// Error creating the search database. + #[error("failed to create search database")] + SearchDbError(#[from] io::Error), + /// Error marking the search database as persistent. + #[error("failed to persist search database")] + PersistSearchDbError(#[from] PersistError), } /// Convert an SQLite error into a proper NoResults one if the query diff --git a/calibre-db/src/search.rs b/calibre-db/src/search.rs index d8dfda3..0d61d51 100644 --- a/calibre-db/src/search.rs +++ b/calibre-db/src/search.rs @@ -1,13 +1,14 @@ //! Provide search funcitonality for calibre. //! //! Because the calibre database can not be disturbed (it is treated as read-only) -//! it attaches an in-memory database and inserts the relevant data into a +//! it attaches a temporary database and inserts the relevant data into a //! virtual table leveraging fts5 (https://www.sqlite.org/fts5.html). Full-text search is run on //! that virtual table. use r2d2::{Pool, PooledConnection}; use r2d2_sqlite::SqliteConnectionManager; use rusqlite::named_params; +use tempfile::NamedTempFile; use crate::data::{book::Book, error::DataStoreError}; @@ -31,11 +32,16 @@ const SEARCH_INIT_QUERY: &str = "INSERT INTO search.fts(book_id, data) LEFT JOIN main.series AS s ON b2s.series = s.id GROUP BY b.id"; -/// Attach the fts in-memory database to the read-only calibre database. +/// Attach the fts temporary database to the read-only calibre database. pub(crate) fn attach(pool: &Pool) -> Result<(), DataStoreError> { let conn = pool.get()?; + let tmpfile = NamedTempFile::new()?; + let (_, path) = tmpfile.keep()?; - conn.execute("ATTACH DATABASE ':memory:' AS search", [])?; + conn.execute( + &format!("ATTACH DATABASE '{}' AS search", path.to_string_lossy()), + [], + )?; init(&conn)?; Ok(()) diff --git a/little-hesinde/Cargo.toml b/little-hesinde/Cargo.toml index 353f8a3..417ee5a 100644 --- a/little-hesinde/Cargo.toml +++ b/little-hesinde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "little-hesinde" -version = "0.2.1" +version = "0.2.3" edition = "2021" license = { workspace = true } authors = { workspace = true } diff --git a/little-hesinde/src/lib.rs b/little-hesinde/src/lib.rs index 708192f..95b1ebc 100644 --- a/little-hesinde/src/lib.rs +++ b/little-hesinde/src/lib.rs @@ -76,7 +76,7 @@ pub mod opds { pub mod templates; pub const APP_NAME: &str = "little-hesinde"; -pub const VERSION: &str = "0.2.1"; +pub const VERSION: &str = "0.2.3"; /// Internal marker data in lieu of a proper `Accept` header. #[derive(Debug, Clone, Copy)]