diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..8af59dd
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,2 @@
+[env]
+RUST_TEST_THREADS = "1"
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ca8335f..f1b240f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -57,30 +57,23 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- - name: check avoid-dev-deps
- uses: actions-rs/cargo@v1
- if: matrix.rust == 'nightly'
- with:
- command: check
- args: --all -Z avoid-dev-deps
-
- name: pg tests
uses: actions-rs/cargo@v1
with:
command: test
- args: --all --features pg,async_std -- --test-threads=1
+ args: --all --features pg -- --test-threads=1
- name: sqlite tests
uses: actions-rs/cargo@v1
with:
command: test
- args: --all --features sqlite,async_std
+ args: --all --features sqlite
- name: mysql tests
uses: actions-rs/cargo@v1
with:
command: test
- args: --all --features mysql,async_std -- --test-threads=1
+ args: --all --features mysql -- --test-threads=1
check_fmt_and_docs:
name: Checking fmt, clippy, and docs
diff --git a/Cargo.toml b/Cargo.toml
index b452a5d..3a21b0c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,25 +12,29 @@ keywords = ["sessions", "sqlx", "sqlite", "postgres", "mysql"]
categories = ["web-programming::http-server", "web-programming", "database"]
[package.metadata.docs.rs]
-features = ["pg", "sqlite", "mysql", "async_std"]
+features = ["pg", "sqlite", "mysql"]
[features]
-default = ["native-tls"]
+default = []
sqlite = ["sqlx/sqlite"]
pg = ["sqlx/postgres", "sqlx/json"]
native-tls = ["sqlx/runtime-async-std-native-tls"]
rustls = ["sqlx/runtime-async-std-rustls"]
-async_std = ["async-std"]
mysql = ["sqlx/mysql", "sqlx/json"]
[dependencies]
-async-session = "3.0.0"
-sqlx = { version = "0.6.2", features = ["chrono"] }
-async-std = { version = "1.12.0", optional = true }
+async-session = { git = "https://github.com/http-rs/async-session", branch = "overhaul-session-and-session-store", default-features = false }
+sqlx = { version = "0.6.2", features = ["time"] }
+log = "0.4.17"
+serde_json = "1.0.93"
+serde = "1.0.152"
+thiserror = "1.0.38"
+time = "0.3.18"
+base64 = "0.21.0"
[dev-dependencies]
async-std = { version = "1.12.0", features = ["attributes"] }
[dev-dependencies.sqlx]
version = "0.6.2"
-features = ["chrono", "runtime-async-std-native-tls"]
+features = ["runtime-async-std-native-tls"]
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..ffadb8a
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,17 @@
+/// Errors that can arise in the operation of the session stores
+/// included in this crate
+#[derive(thiserror::Error, Debug)]
+#[non_exhaustive]
+pub enum Error {
+ /// an error that comes from sqlx
+ #[error(transparent)]
+ SqlxError(#[from] sqlx::Error),
+
+ /// an error that comes from serde_json
+ #[error(transparent)]
+ SerdeJson(#[from] serde_json::Error),
+
+ /// an error that comes from base64
+ #[error(transparent)]
+ Base64(#[from] base64::DecodeError),
+}
diff --git a/src/lib.rs b/src/lib.rs
index 3fff7c2..ed73a55 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -54,3 +54,6 @@ pub use pg::PostgresSessionStore;
mod mysql;
#[cfg(feature = "mysql")]
pub use mysql::MySqlSessionStore;
+
+mod error;
+pub use error::Error;
diff --git a/src/mysql.rs b/src/mysql.rs
index 0edf82c..db768a5 100644
--- a/src/mysql.rs
+++ b/src/mysql.rs
@@ -1,19 +1,18 @@
-use async_session::{async_trait, chrono::Utc, log, serde_json, Result, Session, SessionStore};
+use async_session::{async_trait, Session, SessionStore};
use sqlx::{pool::PoolConnection, Executor, MySql, MySqlPool};
+use time::OffsetDateTime;
/// sqlx mysql session store for async-sessions
///
/// ```rust
-/// use async_sqlx_session::MySqlSessionStore;
+/// use async_sqlx_session::{MySqlSessionStore, Error};
/// use async_session::{Session, SessionStore};
/// use std::time::Duration;
///
-/// # fn main() -> async_session::Result { async_std::task::block_on(async {
+/// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
/// store.migrate().await?;
/// # store.clear_store().await?;
-/// # #[cfg(feature = "async_std")]
-/// store.spawn_cleanup_task(Duration::from_secs(60 * 60));
///
/// let mut session = Session::new();
/// session.insert("key", vec![1,2,3]);
@@ -36,9 +35,8 @@ impl MySqlSessionStore {
/// with [`with_table_name`](crate::MySqlSessionStore::with_table_name).
///
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::Result;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let pool = sqlx::MySqlPool::connect(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await.unwrap();
/// let store = MySqlSessionStore::from_client(pool)
/// .with_table_name("custom_table_name");
@@ -60,9 +58,8 @@ impl MySqlSessionStore {
/// [`new_with_table_name`](crate::MySqlSessionStore::new_with_table_name)
///
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::Result;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
/// store.migrate().await;
/// # Ok(()) }) }
@@ -80,9 +77,8 @@ impl MySqlSessionStore {
/// [`new_with_table_name`](crate::MySqlSessionStore::new_with_table_name)
///
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::Result;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new_with_table_name(&std::env::var("MYSQL_TEST_DB_URL").unwrap(), "custom_table_name").await?;
/// store.migrate().await;
/// # Ok(()) }) }
@@ -94,9 +90,8 @@ impl MySqlSessionStore {
/// Chainable method to add a custom table name. This will panic
/// if the table name is not `[a-zA-Z0-9_-]`.
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::Result;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?
/// .with_table_name("custom_name");
/// store.migrate().await;
@@ -104,9 +99,8 @@ impl MySqlSessionStore {
/// ```
///
/// ```should_panic
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::Result;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?
/// .with_table_name("johnny (); drop users;");
/// # Ok(()) }) }
@@ -134,9 +128,9 @@ impl MySqlSessionStore {
/// exactly-once modifications to the schema of the session table
/// on breaking releases.
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::{Result, SessionStore, Session};
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # use async_session::{SessionStore, Session};
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
/// # store.clear_store().await?;
/// store.migrate().await?;
@@ -176,55 +170,19 @@ impl MySqlSessionStore {
self.client.acquire().await
}
- /// Spawns an async_std::task that clears out stale (expired)
- /// sessions on a periodic basis. Only available with the
- /// async_std feature enabled.
- ///
- /// ```rust,no_run
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::{Result, SessionStore, Session};
- /// # use std::time::Duration;
- /// # fn main() -> Result { async_std::task::block_on(async {
- /// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
- /// store.migrate().await?;
- /// # let join_handle =
- /// store.spawn_cleanup_task(Duration::from_secs(1));
- /// let mut session = Session::new();
- /// session.expire_in(Duration::from_secs(0));
- /// store.store_session(session).await?;
- /// assert_eq!(store.count().await?, 1);
- /// async_std::task::sleep(Duration::from_secs(2)).await;
- /// assert_eq!(store.count().await?, 0);
- /// # join_handle.cancel().await;
- /// # Ok(()) }) }
- /// ```
- #[cfg(feature = "async_std")]
- pub fn spawn_cleanup_task(
- &self,
- period: std::time::Duration,
- ) -> async_std::task::JoinHandle<()> {
- let store = self.clone();
- async_std::task::spawn(async move {
- loop {
- async_std::task::sleep(period).await;
- if let Err(error) = store.cleanup().await {
- log::error!("cleanup error: {}", error);
- }
- }
- })
- }
-
/// Performs a one-time cleanup task that clears out stale
/// (expired) sessions. You may want to call this from cron.
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::{chrono::{Utc,Duration}, Result, SessionStore, Session};
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # use async_session::{SessionStore, Session};
+ /// # use std::time::Duration;
+ /// # use time::OffsetDateTime;
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
/// store.migrate().await?;
/// # store.clear_store().await?;
/// let mut session = Session::new();
- /// session.set_expiry(Utc::now() - Duration::seconds(5));
+ /// session.set_expiry(OffsetDateTime::now_utc() - Duration::from_secs(5));
/// store.store_session(session).await?;
/// assert_eq!(store.count().await?, 1);
/// store.cleanup().await?;
@@ -234,7 +192,7 @@ impl MySqlSessionStore {
pub async fn cleanup(&self) -> sqlx::Result<()> {
let mut connection = self.connection().await?;
sqlx::query(&self.substitute_table_name("DELETE FROM %%TABLE_NAME%% WHERE expires < ?"))
- .bind(Utc::now())
+ .bind(OffsetDateTime::now_utc())
.execute(&mut connection)
.await?;
@@ -245,10 +203,10 @@ impl MySqlSessionStore {
/// expired sessions
///
/// ```rust
- /// # use async_sqlx_session::MySqlSessionStore;
- /// # use async_session::{Result, SessionStore, Session};
+ /// # use async_sqlx_session::{MySqlSessionStore, Error};
+ /// # use async_session::{SessionStore, Session};
/// # use std::time::Duration;
- /// # fn main() -> Result { async_std::task::block_on(async {
+ /// # fn main() -> Result<(), Error> { async_std::task::block_on(async {
/// let store = MySqlSessionStore::new(&std::env::var("MYSQL_TEST_DB_URL").unwrap()).await?;
/// store.migrate().await?;
/// # store.clear_store().await?;
@@ -270,26 +228,34 @@ impl MySqlSessionStore {
#[async_trait]
impl SessionStore for MySqlSessionStore {
- async fn load_session(&self, cookie_value: String) -> Result