Skip to content

Commit

Permalink
Change the way permanodes are handled (#1980)
Browse files Browse the repository at this point in the history
* Change the way permanodes are handled

* Rename, add comments

* Add primary_node methods to ClientBuilder

* Fix wasm

* Fix default, import

* Remove unused code

* Fix get_permanode_info, update INode interface

* Review suggestions, fix python binding

* Move clone to another place

* Refactor nodes conversion to please pylint

* Reorder

* Simplify logic

---------

Co-authored-by: DaughterOfMars <[email protected]>
Co-authored-by: /alex/ <[email protected]>
  • Loading branch information
3 people authored Feb 16, 2024
1 parent 7671804 commit 10fa7b3
Show file tree
Hide file tree
Showing 19 changed files with 303 additions and 263 deletions.
6 changes: 2 additions & 4 deletions bindings/nodejs/lib/types/client/client-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import type { IMqttBrokerOptions, INetworkInfo, INode } from './network';

/** Options for the client builder */
export interface IClientOptions {
/** Node which will be tried first for all requests */
primaryNode?: string | INode;
/** Nodes which will be tried first for all requests */
primaryNodes?: Array<string | INode>;
/** A list of nodes. */
nodes?: Array<string | INode>;
/** A list of permanodes. */
permanodes?: Array<string | INode>;
/** If the node health status should be ignored */
ignoreNodeHealth?: boolean;
/** Interval in which nodes will be checked for their sync status and the NetworkInfo gets updated */
Expand Down
2 changes: 2 additions & 0 deletions bindings/nodejs/lib/types/client/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export interface INode {
auth?: IAuth;
/** Whether the node is disabled or not. */
disabled?: boolean;
/** Whether the node is a permanode or not. */
permanode?: boolean;
}

/**
Expand Down
38 changes: 22 additions & 16 deletions bindings/python/iota_sdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ class Client(NodeCoreAPI, NodeIndexerAPI, HighLevelAPI, ClientUtils):
# pylint: disable=unused-argument
def __init__(
self,
nodes: Optional[Union[str, List[str]]] = None,
primary_node: Optional[str] = None,
permanode: Optional[str] = None,
primary_nodes: Optional[Union[Union[str, Node],
List[Union[str, Node]]]] = None,
nodes: Optional[Union[Union[str, Node],
List[Union[str, Node]]]] = None,
ignore_node_health: Optional[bool] = None,
api_timeout: Optional[timedelta] = None,
node_sync_interval: Optional[timedelta] = None,
Expand All @@ -48,12 +49,10 @@ def __init__(
"""Initialize the IOTA Client.
**Arguments**
primary_nodes :
Nodes which will be tried first for all requests.
nodes :
A single Node URL or an array of URLs.
primary_node :
Node which will be tried first for all requests.
permanode :
Permanode URL.
ignore_node_health :
If the node health should be ignored.
api_timeout :
Expand All @@ -80,15 +79,8 @@ def __init__(
if "client_handle" in client_config:
del client_config["client_handle"]

if isinstance(nodes, list):
nodes = [node.to_dict() if isinstance(node, Node)
else node for node in nodes]
elif nodes:
if isinstance(nodes, Node):
nodes = [nodes.to_dict()]
else:
nodes = [nodes]
client_config['nodes'] = nodes
client_config['primary_nodes'] = convert_nodes(primary_nodes)
client_config['nodes'] = convert_nodes(nodes)

client_config = {
k: v for k,
Expand Down Expand Up @@ -313,3 +305,17 @@ def clear_mqtt_listeners(self, topics: List[str]):
return self._call_method('clearListeners', {
'topics': topics
})


def convert_nodes(
nodes: Optional[Union[Union[str, Node], List[Union[str, Node]]]] = None):
"""Helper function to convert provided nodes to a list for the client options.
"""
if isinstance(nodes, list):
return [node.to_dict() if isinstance(node, Node)
else node for node in nodes]
if isinstance(nodes, Node):
return [nodes.to_dict()]
if nodes is not None:
return [nodes]
return None
9 changes: 3 additions & 6 deletions bindings/python/iota_sdk/types/client_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ class ClientOptions:
"""Client options.
Attributes:
primary_node (str):
Node which will be tried first for all requests.
primary_nodes (List[str]):
Nodes which will be tried first for all requests.
nodes (List[str]):
Array of Node URLs.
permanode (str):
Permanode URL.
ignore_node_health (bool):
If the node health should be ignored.
node_sync_interval (Duration):
Expand All @@ -75,9 +73,8 @@ class ClientOptions:
max_parallel_api_requests (int):
The maximum parallel API requests.
"""
primary_node: Optional[str] = None
primary_nodes: Optional[List[str]] = None
nodes: Optional[List[str]] = None
permanodes: Optional[List[str]] = None
ignore_node_health: Optional[bool] = None
node_sync_interval: Optional[Duration] = None
quorum: Optional[bool] = None
Expand Down
5 changes: 4 additions & 1 deletion bindings/python/iota_sdk/types/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,24 @@ class Node:
username: A username for basic authentication.
password: A password for basic authentication.
disabled: Whether the node should be used for API requests or not.
permanode: Whether the node is a permanode or not.
"""

url: Optional[str] = None
jwt: Optional[str] = None
username: Optional[str] = None
password: Optional[str] = None
disabled: Optional[bool] = None
permanode: Optional[bool] = None

def to_dict(self) -> dict:
"""Custom dict conversion.
"""

res = {
'url': self.url,
'disabled': self.disabled
'disabled': self.disabled,
'permanode': self.permanode
}
if self.jwt is not None or self.username is not None or self.password is not None:
auth = res['auth'] = {}
Expand Down
26 changes: 11 additions & 15 deletions sdk/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

//! Builder of the Client Instance
use std::{collections::HashMap, sync::Arc, time::Duration};
use std::{collections::HashSet, sync::Arc, time::Duration};

use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -81,18 +81,14 @@ impl ClientBuilder {
pub fn from_json(mut self, client_config: &str) -> Result<Self> {
self = serde_json::from_str::<Self>(client_config)?;
// validate URLs
if let Some(node_dto) = &self.node_manager_builder.primary_node {
for node_dto in &self.node_manager_builder.primary_nodes {
let node: Node = node_dto.into();
validate_url(node.url)?;
}
for node_dto in &self.node_manager_builder.nodes {
let node: Node = node_dto.into();
validate_url(node.url)?;
}
for node_dto in &self.node_manager_builder.permanodes {
let node: Node = node_dto.into();
validate_url(node.url)?;
}
Ok(self)
}

Expand All @@ -102,15 +98,15 @@ impl ClientBuilder {
Ok(self)
}

/// Adds an IOTA node by its URL to be used as primary node, with optional jwt and or basic authentication
pub fn with_primary_node(mut self, url: &str, auth: Option<NodeAuth>) -> Result<Self> {
self.node_manager_builder = self.node_manager_builder.with_primary_node(url, auth)?;
// Adds a node as primary node.
pub fn with_primary_node(mut self, node: Node) -> Result<Self> {
self.node_manager_builder = self.node_manager_builder.with_primary_node(node)?;
Ok(self)
}

/// Adds a permanode by its URL, with optional jwt and or basic authentication
pub fn with_permanode(mut self, url: &str, auth: Option<NodeAuth>) -> Result<Self> {
self.node_manager_builder = self.node_manager_builder.with_permanode(url, auth)?;
/// Adds a list of IOTA nodes by their URLs to the primary nodes list.
pub fn with_primary_nodes(mut self, urls: &[&str]) -> Result<Self> {
self.node_manager_builder = self.node_manager_builder.with_primary_nodes(urls)?;
Ok(self)
}

Expand Down Expand Up @@ -195,7 +191,7 @@ impl ClientBuilder {
let ignore_node_health = self.node_manager_builder.ignore_node_health;
let nodes = self
.node_manager_builder
.primary_node
.primary_nodes
.iter()
.chain(self.node_manager_builder.nodes.iter())
.map(|node| node.clone().into())
Expand All @@ -205,7 +201,7 @@ impl ClientBuilder {
let (mqtt_event_tx, mqtt_event_rx) = tokio::sync::watch::channel(MqttEvent::Connected);

let client_inner = Arc::new(ClientInner {
node_manager: RwLock::new(self.node_manager_builder.build(HashMap::new())),
node_manager: RwLock::new(self.node_manager_builder.build(HashSet::new())),
network_info: RwLock::new(self.network_info),
api_timeout: RwLock::new(self.api_timeout),
#[cfg(feature = "mqtt")]
Expand Down Expand Up @@ -246,7 +242,7 @@ impl ClientBuilder {

let client = Client {
inner: Arc::new(ClientInner {
node_manager: RwLock::new(self.node_manager_builder.build(HashMap::new())),
node_manager: RwLock::new(self.node_manager_builder.build(HashSet::new())),
network_info: RwLock::new(self.network_info),
api_timeout: RwLock::new(self.api_timeout),
#[cfg(feature = "mqtt")]
Expand Down
Loading

0 comments on commit 10fa7b3

Please sign in to comment.