ump-ngx 0.7.0

Collection of ump-ng extensions.
Documentation
//! Integration utilities for creating sqlsrv handlers.

use super::{r2d2, ConnPool, WrConn};


use threadpool::ThreadPool;

use ump_ng::ReplyContext;

// Re-export rusqlite from sqlsrv
pub use sqlsrv::rusqlite;

use rusqlite::Connection;

pub enum Error<E> {
  R2D2(r2d2::Error),
  App(E)
}


/// Given an [`ConnPool`] and a [`ReplyContext`], run a closure (presumably
/// performing read-only database operations).
///
/// Translates the closure's `Result<T, E>` into a `ReplyContext::reply()` on
/// `Ok` and `ReplyContext::fail()` on `Err`.
///
/// # Errors
/// [`r2d2::Error`] is returned if a read-only connection could not be
/// acquired from the connection pool.
pub fn proc_rodb_req<R, E, F>(
  cpool: &ConnPool,
  rctx: ReplyContext<R, E>,
  f: F
) -> Result<(), r2d2::Error>
where
  R: Send + 'static,
  E: std::error::Error + Send + 'static,
  F: FnOnce(&Connection) -> Result<R, E> + Send + 'static
{
  let roconn = cpool.reader()?;

  let res = match f(&roconn) {
    Ok(reply) => rctx.reply(reply),
    Err(e) => rctx.fail(e)
  };
  if let Err(e) = res {
    eprintln!("Reply message pass failed; {e}");
  }

  Ok(())
}

/// Process a requested read-only database message on a thread pool.
///
/// The read-only database connection will be acquired from the connection pool
/// `cpool`.  The tread will be launched on the thread pool `tpool`.
///
/// The closure `f` returns a `Result<T, E>`, where the `Ok(T)` case will pass
/// the `T` to the `rctx`'s [`reply()`](ReplyContext::reply), and `Err(E)` will
/// pass the `E` to [`fail()`](ReplyContext::fail).
///
/// # Errors
/// [`r2d2::Error`] is returned if a read-only connection could not be
/// acquired from the connection pool.
pub fn proc_rodb_req_thrd<R, E, F>(
  cpool: &ConnPool,
  tpool: &ThreadPool,
  rctx: ReplyContext<R, E>,
  f: F
) -> Result<(), r2d2::Error>
where
  R: Send + 'static,
  E: std::error::Error + Send + 'static,
  F: FnOnce(&Connection) -> Result<R, E> + Send + 'static
{
  let roconn = cpool.reader()?;

  tpool.execute(move || {
    let res = match f(&roconn) {
      Ok(reply) => rctx.reply(reply),
      Err(e) => rctx.fail(e)
    };
    if let Err(e) = res {
      eprintln!("Reply message pass failed; {e}");
    }
  });

  Ok(())
}

/// Process a requested read/write database message.
pub fn proc_rwdb_req<R, E, F>(cpool: &ConnPool, rctx: ReplyContext<R, E>, f: F)
where
  R: Send + 'static,
  E: std::error::Error + Send + 'static,
  F: FnOnce(&mut WrConn) -> Result<R, E> + Send + 'static
{
  let mut conn = cpool.writer();

  let res = match f(&mut conn) {
    Ok(reply) => rctx.reply(reply),
    Err(e) => rctx.fail(e)
  };
  if let Err(e) = res {
    eprintln!("Reply message pass failed; {e}");
  }
}

/// Process a requested read/write database message on a thread pool.
///
/// The read/write database connection will be acquired from the connection
/// pool `cpool`.  The tread will be launched on the thread pool `tpool`.
///
/// The closure `f` returns a `Result<T, E>`, where the `Ok(T)` case will pass
/// the `T` to the `rctx`'s [`reply()`](ReplyContext::reply), and `Err(E)` will
/// pass the `E` to [`fail()`](ReplyContext::fail).
pub fn proc_rwdb_req_thrd<R, E, F>(
  cpool: &ConnPool,
  tpool: &ThreadPool,
  rctx: ReplyContext<R, E>,
  f: F
) where
  R: Send + 'static,
  E: std::error::Error + Send + 'static,
  F: FnOnce(&mut WrConn) -> Result<R, E> + Send + 'static
{
  let mut rwconn = cpool.writer();

  tpool.execute(move || {
    let res = match f(&mut rwconn) {
      Ok(reply) => rctx.reply(reply),
      Err(e) => rctx.fail(e)
    };
    if let Err(e) = res {
      eprintln!("Reply message pass failed; {e}");
    }
  });
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :