Connection Pool

Connection pool can only be used in blocking mode applications.

use std::{env, thread, sync::Arc};
use once_cell::sync::OnceCell;
use sibyl::*;

fn main() -> sibyl::Result<()> {
    static ORACLE : OnceCell<Environment> = OnceCell::new();
    let oracle = ORACLE.get_or_try_init(|| {
        Environment::new()
    })?;

    let dbname = env::var("DBNAME").expect("database name");
    let dbuser = env::var("DBUSER").expect("user name");
    let dbpass = env::var("DBPASS").expect("password");

    // Connection pool needs to establish an internal session with the database.
    // `dbuser` and `dbpass` here are for that session.
    let pool = oracle.create_connection_pool(&dbname, &dbuser, &dbpass, 0, 1, 4)?;
    // This pool has 0 available connections at this time, will create 1 connection
    // at a time when they are needed (session needs a connection to run and there
    // are no available connections in the pool), up to the maximum of 4 connections.
    let pool = Arc::new(pool);

    let mut workers = Vec::new();
    for i in 0..10 {
        let pool = pool.clone();
        let handle = thread::spawn(move || -> Result<()> {
            let dbuser = env::var(format!("DBUSER{}",i)).expect("user name");
            let dbpass = env::var(format!("DBPASS{}",i)).expect("password");
            // Here `dbuser` and `dbpass` are used to create a new database session.
            // While these sessions share pooled connections, they are entirely
            // "owned" by the threads that created them and as such might use
            // different users for authentication.
            let session = pool.get_session(&dbuser, &dbpass)?;
            // ...
            Ok(())
        }
        workers.push(handle);
    }
    for handle in workers {
        let _ = handle.join();
    }
    Ok(())
}