Skip to content
This repository was archived by the owner on Jan 27, 2026. It is now read-only.

Commit 5e327ac

Browse files
committed
ability to list all nodes for orchestrator compute pool
1 parent 31870ad commit 5e327ac

5 files changed

Lines changed: 154 additions & 76 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Example demonstrating how to list nodes for a specific pool using the OrchestratorClient.
4+
"""
5+
6+
import os
7+
from primeprotocol import OrchestratorClient
8+
9+
def main():
10+
# Replace with your actual RPC URL and private key
11+
RPC_URL = "http://localhost:8545"
12+
PRIVATE_KEY = os.getenv("ORCHESTRATOR_PRIVATE_KEY")
13+
DISCOVERY_URLS = ["http://localhost:8089"] # Discovery service URLs
14+
15+
# Create orchestrator client
16+
orchestrator = OrchestratorClient(
17+
rpc_url=RPC_URL,
18+
private_key=PRIVATE_KEY,
19+
discovery_urls=DISCOVERY_URLS
20+
)
21+
22+
# Initialize the orchestrator (without P2P for this example)
23+
orchestrator.start()
24+
25+
# List nodes for a specific pool (example pool ID: 0)
26+
pool_id = 0
27+
pool_nodes = orchestrator.list_nodes_for_pool(pool_id)
28+
print(f"Nodes in pool {pool_id}: {len(pool_nodes)}")
29+
30+
# Print details of all nodes in the pool
31+
for i, node in enumerate(pool_nodes):
32+
print(f"\nNode {i+1}:")
33+
print(f" ID: {node.id}")
34+
print(f" Provider Address: {node.provider_address}")
35+
print(f" IP Address: {node.ip_address}")
36+
print(f" Port: {node.port}")
37+
print(f" Pool ID: {node.compute_pool_id}")
38+
print(f" Validated: {node.is_validated}")
39+
print(f" Active: {node.is_active}")
40+
if node.worker_p2p_id:
41+
print(f" Worker P2P ID: {node.worker_p2p_id}")
42+
43+
# Stop the orchestrator
44+
orchestrator.stop()
45+
46+
if __name__ == "__main__":
47+
main()
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use pyo3::prelude::*;
2+
use shared::models::node::DiscoveryNode;
3+
4+
/// Node details structure shared between validator and orchestrator
5+
#[pyclass]
6+
#[derive(Clone)]
7+
pub struct NodeDetails {
8+
#[pyo3(get)]
9+
pub id: String,
10+
#[pyo3(get)]
11+
pub provider_address: String,
12+
#[pyo3(get)]
13+
pub ip_address: String,
14+
#[pyo3(get)]
15+
pub port: u16,
16+
#[pyo3(get)]
17+
pub compute_pool_id: u32,
18+
#[pyo3(get)]
19+
pub is_validated: bool,
20+
#[pyo3(get)]
21+
pub is_active: bool,
22+
#[pyo3(get)]
23+
pub is_provider_whitelisted: bool,
24+
#[pyo3(get)]
25+
pub is_blacklisted: bool,
26+
#[pyo3(get)]
27+
pub worker_p2p_id: Option<String>,
28+
#[pyo3(get)]
29+
pub last_updated: Option<String>,
30+
#[pyo3(get)]
31+
pub created_at: Option<String>,
32+
}
33+
34+
impl From<DiscoveryNode> for NodeDetails {
35+
fn from(node: DiscoveryNode) -> Self {
36+
Self {
37+
id: node.node.id,
38+
provider_address: node.node.provider_address,
39+
ip_address: node.node.ip_address,
40+
port: node.node.port,
41+
compute_pool_id: node.node.compute_pool_id,
42+
is_validated: node.is_validated,
43+
is_active: node.is_active,
44+
is_provider_whitelisted: node.is_provider_whitelisted,
45+
is_blacklisted: node.is_blacklisted,
46+
worker_p2p_id: node.node.worker_p2p_id,
47+
last_updated: node.last_updated.map(|dt| dt.to_rfc3339()),
48+
created_at: node.created_at.map(|dt| dt.to_rfc3339()),
49+
}
50+
}
51+
}
52+
53+
#[pymethods]
54+
impl NodeDetails {
55+
/// Get compute specifications as a Python dictionary
56+
pub fn get_compute_specs(&self, py: Python) -> PyResult<PyObject> {
57+
// This method would need access to the original node data
58+
// For now, return None since we don't store compute specs in NodeDetails
59+
Ok(py.None())
60+
}
61+
62+
/// Get location information as a Python dictionary
63+
pub fn get_location(&self, py: Python) -> PyResult<PyObject> {
64+
// This method would need access to the original node data
65+
// For now, return None since we don't store location in NodeDetails
66+
Ok(py.None())
67+
}
68+
}

crates/prime-protocol-py/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use crate::common::NodeDetails;
12
use crate::orchestrator::OrchestratorClient;
23
use crate::validator::ValidatorClient;
34
use crate::worker::WorkerClient;
45
use pyo3::prelude::*;
56

7+
mod common;
68
mod constants;
79
mod error;
810
mod orchestrator;
@@ -17,5 +19,6 @@ fn primeprotocol(m: &Bound<'_, PyModule>) -> PyResult<()> {
1719
m.add_class::<WorkerClient>()?;
1820
m.add_class::<OrchestratorClient>()?;
1921
m.add_class::<ValidatorClient>()?;
22+
m.add_class::<NodeDetails>()?;
2023
Ok(())
2124
}

crates/prime-protocol-py/src/orchestrator/mod.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::common::NodeDetails;
12
use crate::p2p_handler::auth::AuthenticationManager;
23
use crate::p2p_handler::message_processor::{MessageProcessor, MessageProcessorConfig};
34
use crate::p2p_handler::{Message, MessageType, Service as P2PService};
@@ -12,6 +13,9 @@ use tokio::task::JoinHandle;
1213
use tokio_util::sync::CancellationToken;
1314
use url::Url;
1415

16+
// Add new imports for discovery functionality
17+
use shared::discovery::fetch_nodes_from_discovery_urls;
18+
1519
/// Prime Protocol Orchestrator Client - for managing and distributing tasks
1620
#[pyclass]
1721
pub struct OrchestratorClient {
@@ -24,13 +28,19 @@ pub struct OrchestratorClient {
2428
user_message_rx: Option<Arc<Mutex<Receiver<Message>>>>,
2529
message_processor_handle: Option<JoinHandle<()>>,
2630
peer_id: Option<PeerId>,
31+
// Discovery service URLs
32+
discovery_urls: Vec<String>,
2733
}
2834

2935
#[pymethods]
3036
impl OrchestratorClient {
3137
#[new]
32-
#[pyo3(signature = (rpc_url, private_key=None))]
33-
pub fn new(rpc_url: String, private_key: Option<String>) -> PyResult<Self> {
38+
#[pyo3(signature = (rpc_url, private_key=None, discovery_urls=vec!["http://localhost:8089".to_string()]))]
39+
pub fn new(
40+
rpc_url: String,
41+
private_key: Option<String>,
42+
discovery_urls: Vec<String>,
43+
) -> PyResult<Self> {
3444
let runtime = tokio::runtime::Builder::new_multi_thread()
3545
.enable_all()
3646
.build()
@@ -60,6 +70,7 @@ impl OrchestratorClient {
6070
user_message_rx: None,
6171
message_processor_handle: None,
6272
peer_id: None,
73+
discovery_urls,
6374
})
6475
}
6576

@@ -201,14 +212,28 @@ impl OrchestratorClient {
201212
Ok(())
202213
}
203214

204-
pub fn list_validated_nodes(&self) -> PyResult<Vec<String>> {
205-
// TODO: Implement orchestrator node listing
206-
Ok(vec![])
207-
}
215+
/// List nodes for a specific compute pool
216+
pub fn list_nodes_for_pool(&self, py: Python, pool_id: u32) -> PyResult<Vec<NodeDetails>> {
217+
let rt = self.get_or_create_runtime()?;
218+
219+
let wallet = self.wallet.as_ref().ok_or_else(|| {
220+
PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(
221+
"Wallet not initialized. Provide private_key when creating client.",
222+
)
223+
})?;
224+
225+
let discovery_urls = self.discovery_urls.clone();
226+
let route = format!("/api/pool/{}", pool_id);
227+
228+
let nodes = py.allow_threads(|| {
229+
rt.block_on(async {
230+
fetch_nodes_from_discovery_urls(&discovery_urls, &route, wallet)
231+
.await
232+
.map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))
233+
})
234+
})?;
208235

209-
pub fn list_nodes_from_chain(&self) -> PyResult<Vec<String>> {
210-
// TODO: Implement orchestrator node listing from chain
211-
Ok(vec![])
236+
Ok(nodes.into_iter().map(NodeDetails::from).collect())
212237
}
213238
}
214239

crates/prime-protocol-py/src/validator/mod.rs

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::common::NodeDetails;
12
use crate::p2p_handler::auth::AuthenticationManager;
23
use crate::p2p_handler::message_processor::{MessageProcessor, MessageProcessorConfig};
34
use crate::p2p_handler::{Message, MessageType, Service as P2PService};
@@ -17,75 +18,9 @@ use tokio::task::JoinHandle;
1718
use tokio_util::sync::CancellationToken;
1819
use url::Url;
1920

20-
/// Node details for validator operations
21-
#[pyclass]
22-
#[derive(Clone)]
23-
pub(crate) struct NodeDetails {
24-
#[pyo3(get)]
25-
pub id: String,
26-
#[pyo3(get)]
27-
pub provider_address: String,
28-
#[pyo3(get)]
29-
pub ip_address: String,
30-
#[pyo3(get)]
31-
pub port: u16,
32-
#[pyo3(get)]
33-
pub compute_pool_id: u32,
34-
#[pyo3(get)]
35-
pub is_validated: bool,
36-
#[pyo3(get)]
37-
pub is_active: bool,
38-
#[pyo3(get)]
39-
pub is_provider_whitelisted: bool,
40-
#[pyo3(get)]
41-
pub is_blacklisted: bool,
42-
#[pyo3(get)]
43-
pub worker_p2p_id: Option<String>,
44-
#[pyo3(get)]
45-
pub last_updated: Option<String>,
46-
#[pyo3(get)]
47-
pub created_at: Option<String>,
48-
}
49-
50-
impl From<DiscoveryNode> for NodeDetails {
51-
fn from(node: DiscoveryNode) -> Self {
52-
Self {
53-
id: node.node.id,
54-
provider_address: node.node.provider_address,
55-
ip_address: node.node.ip_address,
56-
port: node.node.port,
57-
compute_pool_id: node.node.compute_pool_id,
58-
is_validated: node.is_validated,
59-
is_active: node.is_active,
60-
is_provider_whitelisted: node.is_provider_whitelisted,
61-
is_blacklisted: node.is_blacklisted,
62-
worker_p2p_id: node.node.worker_p2p_id,
63-
last_updated: node.last_updated.map(|dt| dt.to_rfc3339()),
64-
created_at: node.created_at.map(|dt| dt.to_rfc3339()),
65-
}
66-
}
67-
}
68-
69-
#[pymethods]
70-
impl NodeDetails {
71-
/// Get compute specs as a Python dictionary
72-
pub fn get_compute_specs(&self, py: Python) -> PyResult<PyObject> {
73-
// This would need access to the original DiscoveryNode's compute_specs
74-
// For now returning None
75-
Ok(py.None())
76-
}
77-
78-
/// Get location as a Python dictionary
79-
pub fn get_location(&self, py: Python) -> PyResult<PyObject> {
80-
// This would need access to the original DiscoveryNode's location
81-
// For now returning None
82-
Ok(py.None())
83-
}
84-
}
85-
8621
/// Prime Protocol Validator Client - for validating nodes and tasks
8722
#[pyclass]
88-
pub(crate) struct ValidatorClient {
23+
pub struct ValidatorClient {
8924
runtime: Option<tokio::runtime::Runtime>,
9025
wallet: Option<Wallet>,
9126
discovery_urls: Vec<String>,

0 commit comments

Comments
 (0)