use super::error::Error;
use super::result::Result;
use super::Handshake;
use js_sys::Object;
use std::sync::Arc;
use wasm_bindgen::{JsCast, JsValue};
use workflow_core::time::Duration;
use workflow_wasm::extensions::object::*;
#[derive(Default)]
pub struct Options {
pub receiver_channel_cap: Option<usize>,
pub sender_channel_cap: Option<usize>,
pub handshake: Option<Arc<dyn Handshake>>,
}
#[derive(Default, Clone, Debug)]
pub enum ConnectStrategy {
#[default]
Retry,
Fallback,
}
impl ConnectStrategy {
pub fn new(retry: bool) -> Self {
if retry {
ConnectStrategy::Retry
} else {
ConnectStrategy::Fallback
}
}
pub fn is_fallback(&self) -> bool {
matches!(self, ConnectStrategy::Fallback)
}
}
#[derive(Clone, Debug)]
pub struct ConnectOptions {
pub block_async_connect: bool,
pub strategy: ConnectStrategy,
pub url: Option<String>,
pub connect_timeout: Option<Duration>,
pub retry_interval: Option<Duration>,
}
pub const DEFAULT_CONNECT_TIMEOUT_MILLIS: u64 = 5_000;
pub const DEFAULT_CONNECT_RETRY_MILLIS: u64 = 5_000;
impl Default for ConnectOptions {
fn default() -> Self {
Self {
block_async_connect: true,
strategy: ConnectStrategy::Retry,
url: None,
connect_timeout: None,
retry_interval: None,
}
}
}
impl ConnectOptions {
pub fn fallback() -> Self {
Self {
block_async_connect: true,
strategy: ConnectStrategy::Fallback,
url: None,
connect_timeout: None,
retry_interval: None,
}
}
pub fn reconnect_defaults() -> Self {
Self {
block_async_connect: true,
strategy: ConnectStrategy::Retry,
url: None,
connect_timeout: None,
retry_interval: None,
}
}
pub fn passive_retry_with_defaults() -> Self {
Self {
block_async_connect: false,
strategy: ConnectStrategy::Retry,
url: None,
connect_timeout: None,
retry_interval: None,
}
}
pub fn connect_timeout(&self) -> Duration {
self.connect_timeout
.unwrap_or(Duration::from_millis(DEFAULT_CONNECT_TIMEOUT_MILLIS))
}
pub fn retry_interval(&self) -> Duration {
self.retry_interval
.unwrap_or(Duration::from_millis(DEFAULT_CONNECT_RETRY_MILLIS))
}
}
impl TryFrom<JsValue> for ConnectOptions {
type Error = Error;
fn try_from(args: JsValue) -> Result<Self> {
let options = if let Some(args) = args.dyn_ref::<Object>() {
let url = args.get_value("url")?.as_string();
let block_async_connect = args.get_value("block")?.as_bool().unwrap_or(true);
let strategy = ConnectStrategy::new(args.get_value("retry")?.as_bool().unwrap_or(true));
let timeout = args
.get_value("timeout")?
.as_f64()
.map(|f| Duration::from_millis(f as u64));
let retry_interval = args
.get_value("retry_interval")?
.as_f64()
.map(|f| Duration::from_millis(f as u64));
ConnectOptions {
block_async_connect,
strategy,
url,
connect_timeout: timeout,
retry_interval,
}
} else if let Some(retry) = args.as_bool() {
ConnectOptions {
block_async_connect: true,
strategy: ConnectStrategy::new(retry),
url: None,
connect_timeout: None,
retry_interval: None,
}
} else {
ConnectOptions::default()
};
Ok(options)
}
}