-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
177 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
wrap_comments = true | ||
imports_granularity = "Crate" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use anyhow::Result; | ||
use sqlx::PgPool; | ||
use tracing_subscriber::{EnvFilter, FmtSubscriber}; | ||
|
||
pub async fn init() -> Result<PgPool> { | ||
dotenv::dotenv().ok(); | ||
init_logging()?; | ||
connect().await | ||
} | ||
|
||
async fn connect() -> Result<PgPool> { | ||
let db = sqlx::PgPool::connect(&std::env::var("DATABASE_URL")?).await?; | ||
sqlx::migrate!().run(&db).await?; | ||
Ok(db) | ||
} | ||
|
||
fn init_logging() -> Result<()> { | ||
let subscriber = FmtSubscriber::builder() | ||
.with_env_filter(EnvFilter::from_default_env()) | ||
.finish(); | ||
tracing::subscriber::set_global_default(subscriber)?; | ||
Ok(()) | ||
} | ||
|
||
// Make `cagro check --examples` happy | ||
#[allow(dead_code)] | ||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use sqlx::{postgres::PgListener, PgPool}; | ||
use std::{sync::Arc, time::Duration}; | ||
use tokio::{ | ||
sync::{futures::Notified, Notify}, | ||
time::timeout, | ||
}; | ||
use tracing::trace; | ||
|
||
/// Waits for tasks table to change | ||
pub struct Waiter(Arc<Notify>); | ||
pub struct Subscription<'a>(Notified<'a>); | ||
|
||
const PG_NOTIFICATION_CHANNEL: &str = "pg_task_changed"; | ||
|
||
impl Waiter { | ||
/// Creates a waiter | ||
pub fn new() -> Self { | ||
let notify = Arc::new(Notify::new()); | ||
Self(notify) | ||
} | ||
|
||
/// Connects to the db and starts to listen to tasks table changes | ||
pub async fn listen(&self, db: PgPool) -> crate::Result<()> { | ||
let mut listener = PgListener::connect_with(&db) | ||
.await | ||
.map_err(crate::Error::WaiterListen)?; | ||
listener | ||
.listen(PG_NOTIFICATION_CHANNEL) | ||
.await | ||
.map_err(crate::Error::WaiterListen)?; | ||
|
||
let notify = self.0.clone(); | ||
tokio::spawn(async move { | ||
loop { | ||
listener.recv().await.unwrap(); | ||
notify.notify_waiters(); | ||
} | ||
}); | ||
Ok(()) | ||
} | ||
|
||
/// Subscribes for notifications. | ||
/// | ||
/// Awaiting on the result ends on the first notification after the | ||
/// subscription, even if it happens between the subscription and awaiting. | ||
pub fn subscribe(&self) -> Subscription<'_> { | ||
Subscription(self.0.notified()) | ||
} | ||
} | ||
|
||
impl<'a> Subscription<'a> { | ||
pub async fn wait_for(self, period: Duration) { | ||
trace!("⌛Waiting for the tasks table to change for {period:?}"); | ||
match timeout(period, self.0).await { | ||
Ok(_) => trace!("⚡The tasks table has changed"), | ||
Err(_) => trace!("⏰The waiting timeout has expired"), | ||
} | ||
} | ||
|
||
pub async fn wait_forever(self) { | ||
trace!("⌛Waiting for the tasks table to change"); | ||
self.0.await; | ||
trace!("⚡The tasks table has changed"); | ||
} | ||
} |
Oops, something went wrong.