use links_bindings_python::prelude::*;
use links_nonblocking::prelude::*;
use log::info;
use ouch_connect_nonblocking::prelude::*;
use pyo3::{prelude::*, types::PyDict};
use serde::Serialize;
use std::{num::NonZeroUsize, time::Duration};
use crate::{DEFAULT_CONNECT_TIMEOUT, DEFAULT_IO_TIMEOUT, DEFAULT_MAX_CONNECTIONS, DEFAULT_MAX_HBEAT_INTERVAL, DEFAULT_USR_PWD};
create_callback_for_messenger!(SvcOuchProtocolManual, SvcOuchProtocolManualCallback);
create_svc_sender!(SvcManual, SvcOuchSender, SvcOuchProtocolManual, SvcOuchProtocolManualCallback, "ouch_connect");
#[derive(Serialize)]
struct SvcManualConfig {
pub max_connections: NonZeroUsize,
pub io_timeout: f64,
pub name: String,
}
impl Default for SvcManualConfig {
fn default() -> Self {
Self {
max_connections: DEFAULT_MAX_CONNECTIONS,
io_timeout: DEFAULT_IO_TIMEOUT,
name: asserted_short_name!("SvcManual", SvcManual).to_owned(),
}
}
}
impl From<&PyDict> for SvcManualConfig {
fn from(py_dict: &PyDict) -> Self {
let default = Self::default();
let max_connections = py_dict.get_item("max_connections").unwrap().map_or(default.max_connections, |any| any.extract::<NonZeroUsize>().unwrap());
let io_timeout = py_dict.get_item("io_timeout").unwrap().map_or(default.io_timeout, |any| any.extract::<f64>().unwrap());
let name = py_dict.get_item("name").unwrap().map_or(default.name, |any| any.extract::<String>().unwrap());
Self { max_connections, io_timeout, name }
}
}
#[pymethods]
impl SvcManual {
#[new]
#[pyo3(signature = (host, callback, **kwargs))]
fn new(_py: Python<'_>, host: &str, callback: PyObject, kwargs: Option<&PyDict>) -> PyResult<Py<Self>> {
let config = kwargs.map_or(SvcManualConfig::default(), SvcManualConfig::from);
info!("{}: effective config: {} with kwargs: {:?}", asserted_short_name!("SvcManual", Self), serde_json::to_string(&config).unwrap(), kwargs);
let sender = {
let svc_callback = SvcOuchProtocolManualCallback::new_ref(callback.clone());
let protocol = SvcOuchProtocolManual::default();
let sender = _py.allow_threads(move || SvcOuch::bind(host, config.max_connections, svc_callback, protocol, Some(&config.name)))?.into_sender_with_spawned_recver();
let con_id = sender.con_id().clone();
Py::new(
_py,
Self {
sender: Some(sender).into(),
con_id,
io_timeout: Some(config.io_timeout),
},
)?
};
patch_callback_if_settable_sender!(_py, sender, callback, asserted_short_name!("SvcManual", Self));
Ok(sender)
}
#[classattr]
fn msg_samples() -> Vec<String> {
ouch_connect_nonblocking::prelude::svc_ouch_default_msgs().iter().map(|m| serde_json::to_string(m).unwrap()).collect::<Vec<_>>()
}
}
create_callback_for_messenger!(SvcOuchProtocolAuto, SvcOuchProtocolAutoCallback);
create_svc_sender!(SvcAuto, SvcOuchSenderRef, SvcOuchProtocolAuto, SvcOuchProtocolAutoCallback, "ouch_connect");
#[derive(Serialize)]
struct SvcAutoConfig {
pub username: String,
pub password: String,
pub session_id: String,
pub clt_max_hbeat_interval: f64,
pub svc_max_hbeat_interval: f64,
pub connect_timeout: f64,
pub max_connections: NonZeroUsize,
pub io_timeout: f64,
pub name: String,
}
impl Default for SvcAutoConfig {
fn default() -> Self {
Self {
username: DEFAULT_USR_PWD.to_owned(),
password: DEFAULT_USR_PWD.to_owned(),
session_id: "".to_owned(),
clt_max_hbeat_interval: DEFAULT_MAX_HBEAT_INTERVAL,
svc_max_hbeat_interval: DEFAULT_MAX_HBEAT_INTERVAL,
connect_timeout: DEFAULT_CONNECT_TIMEOUT,
max_connections: DEFAULT_MAX_CONNECTIONS,
io_timeout: DEFAULT_IO_TIMEOUT,
name: asserted_short_name!("SvcAuto", SvcAuto).to_owned(),
}
}
}
impl From<&PyDict> for SvcAutoConfig {
fn from(value: &PyDict) -> Self {
let default = Self::default();
let username = value.get_item("username").unwrap().map_or(default.username, |any| any.extract::<String>().unwrap());
let password = value.get_item("password").unwrap().map_or(default.password, |any| any.extract::<String>().unwrap());
let session_id = value.get_item("session_id").unwrap().map_or(default.session_id, |any| any.extract::<String>().unwrap());
let clt_max_hbeat_interval = value.get_item("clt_max_hbeat_interval").unwrap().map_or(default.clt_max_hbeat_interval, |any| any.extract::<f64>().unwrap());
let svc_max_hbeat_interval = value.get_item("svc_max_hbeat_interval").unwrap().map_or(default.svc_max_hbeat_interval, |any| any.extract::<f64>().unwrap());
let connect_timeout = value.get_item("connect_timeout").unwrap().map_or(default.connect_timeout, |any| any.extract::<f64>().unwrap());
let max_connections = value.get_item("max_connections").unwrap().map_or(default.max_connections, |any| any.extract::<NonZeroUsize>().unwrap());
let io_timeout = value.get_item("io_timeout").unwrap().map_or(default.io_timeout, |any| any.extract::<f64>().unwrap());
let name = value.get_item("name").unwrap().map_or(default.name, |any| any.extract::<String>().unwrap());
Self {
username,
password,
session_id,
clt_max_hbeat_interval,
svc_max_hbeat_interval,
connect_timeout,
max_connections,
io_timeout,
name,
}
}
}
#[pymethods]
impl SvcAuto {
#[new]
#[pyo3(signature = (host, callback, **kwargs))]
fn new(_py: Python<'_>, host: &str, callback: PyObject, kwargs: Option<&PyDict>) -> PyResult<Py<Self>> {
let config = kwargs.map_or(SvcAutoConfig::default(), SvcAutoConfig::from);
info!("{}: effective config: {} with kwargs: {:?}", asserted_short_name!("SvcAuto", Self), serde_json::to_string(&config).unwrap(), kwargs);
let sender = {
let callback = SvcOuchProtocolAutoCallback::new_ref(callback.clone());
let protocol = SvcOuchProtocolAuto::new(
UserName::from(config.username.as_str()),
Password::from(config.password.as_str()),
SessionId::from(config.session_id.as_str()),
Duration::from_secs_f64(config.io_timeout),
Duration::from_secs_f64(config.clt_max_hbeat_interval),
Duration::from_secs_f64(config.svc_max_hbeat_interval),
);
let sender = _py.allow_threads(move || SvcOuch::bind(host, config.max_connections, callback, protocol, Some(&config.name)))?.into_sender_with_spawned_recver_ref();
let con_id = sender.con_id().clone();
Py::new(
_py,
Self {
sender: Some(sender).into(),
con_id,
io_timeout: Some(config.io_timeout),
},
)?
};
patch_callback_if_settable_sender!(_py, sender, callback, asserted_short_name!("SvcAuto", Self));
Ok(sender)
}
#[classattr]
fn msg_samples() -> Vec<String> {
ouch_connect_nonblocking::prelude::svc_ouch_default_msgs().iter().map(|m| serde_json::to_string(m).unwrap()).collect::<Vec<_>>()
}
}