Skip to content

Commit

Permalink
feat(transport): wip endpoint rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
pashinov committed Oct 28, 2024
1 parent 502ed2b commit e65d4b9
Show file tree
Hide file tree
Showing 11 changed files with 410 additions and 115 deletions.
69 changes: 1 addition & 68 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
on: [push, pull_request]
on: [ push, pull_request ]

name: master

Expand All @@ -22,73 +22,6 @@ jobs:
with:
command: check

check-protos:
name: Check protos
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Install protobuf
run: sudo apt update && sudo apt-get -y install protobuf-compiler

- name: Generate Rust code from .proto files
run: cargo run -p gen-protos

- name: Check for uncommitted changes
run: git diff --exit-code

test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Run cargo test for nekoton
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features

- name: Run cargo test for nekoton-abi
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features --all-targets -p nekoton-abi

- name: Run cargo test for nekoton-derive
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features --all-targets -p nekoton-derive

- name: Run cargo test for nekoton-abi
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features --all-targets -p nekoton-abi

- name: Run cargo test for nekoton-utils
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features --all-targets -p nekoton-utils

lints:
name: Lints
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ anyhow = "1.0"
async-trait = "0.1"
everscale-crypto = { version = "0.2", features = ["tl-proto", "serde"] }
everscale-types = { version = "0.1.0-rc.6", features = ["tycho"] }
futures-util = "0.3"
parking_lot = { version = "0.12.1" }
rand = "0.8"
reqwest = { version = "0.12", features = ["json", "gzip", "rustls-tls"], default-features = false }
serde = "1.0"
serde_json = "1.0"
thiserror = "1.0"
tokio = { version = "1", default-features = false }

# local deps
Expand Down
5 changes: 4 additions & 1 deletion transport/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ license.workspace = true
anyhow = { workspace = true }
async-trait = { workspace = true }
everscale-types = { workspace = true }
futures-util = { workspace = true }
parking_lot = { workspace = true }
rand = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true }

# local deps
nekoton-core = { workspace = true }
serde = { version = "1.0.213", features = ["derive"] }
nekoton-utils = { workspace = true }
62 changes: 62 additions & 0 deletions transport/src/endpoint/jrpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use everscale_types::models::*;
use everscale_types::prelude::*;
use nekoton_core::transport::{ContractState, Transport};
use parking_lot::Mutex;

use crate::endpoint::Connection;
use crate::models::Timings;
use crate::LiveCheckResult;

#[derive(Clone)]
pub struct JrpcClient {
client: reqwest::Client,

Check warning on line 15 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Check

field `client` is never read

Check failure on line 15 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Lints

field `client` is never read
endpoint: Arc<String>,
was_dead: Arc<AtomicBool>,
stats: Arc<Mutex<Option<Timings>>>,
}

#[async_trait::async_trait]
impl Connection for JrpcClient {
fn new(endpoint: String, client: reqwest::Client) -> Self {
JrpcClient {
client,
endpoint: Arc::new(endpoint),
was_dead: Arc::new(AtomicBool::new(false)),
stats: Arc::new(Default::default()),
}
}

fn endpoint(&self) -> &str {
self.endpoint.as_str()
}

fn get_stats(&self) -> Option<Timings> {
self.stats.lock().clone()
}

fn set_stats(&self, stats: Option<Timings>) {
*self.stats.lock() = stats;
}

fn update_was_dead(&self, is_dead: bool) {
self.was_dead.store(is_dead, Ordering::Release);
}

async fn is_alive_inner(&self) -> LiveCheckResult {
todo!()
}
}

#[async_trait::async_trait]
impl Transport for JrpcClient {
async fn broadcast_message(&self, message: &DynCell) -> anyhow::Result<()> {

Check warning on line 55 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `message`

Check failure on line 55 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Lints

unused variable: `message`
todo!()
}

async fn get_contract_state(&self, address: &StdAddr) -> anyhow::Result<ContractState> {

Check warning on line 59 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Check

unused variable: `address`

Check failure on line 59 in transport/src/endpoint/jrpc.rs

View workflow job for this annotation

GitHub Actions / Lints

unused variable: `address`
todo!()
}
}
132 changes: 132 additions & 0 deletions transport/src/endpoint/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use crate::models::Timings;
use crate::LiveCheckResult;
use everscale_types::cell::DynCell;
use everscale_types::models::StdAddr;
use nekoton_core::transport::{ContractState, Transport};

mod jrpc;

#[derive(Clone)]
pub enum Endpoint {
Jrpc(jrpc::JrpcClient),
}

#[async_trait::async_trait]
impl Transport for Endpoint {
async fn broadcast_message(&self, message: &DynCell) -> anyhow::Result<()> {
match &self {
Endpoint::Jrpc(client) => client.broadcast_message(message).await,
}
}

async fn get_contract_state(&self, address: &StdAddr) -> anyhow::Result<ContractState> {
match &self {
Endpoint::Jrpc(client) => client.get_contract_state(address).await,
}
}
}

impl Eq for Endpoint {}

impl PartialEq<Self> for Endpoint {
fn eq(&self, other: &Self) -> bool {
self.endpoint() == other.endpoint()
}
}

impl PartialOrd<Self> for Endpoint {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Endpoint {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.eq(other) {
std::cmp::Ordering::Equal
} else {
let left_stats = self.get_stats();
let right_stats = other.get_stats();

match (left_stats, right_stats) {
(Some(left_stats), Some(right_stats)) => left_stats.cmp(&right_stats),
(None, Some(_)) => std::cmp::Ordering::Less,
(Some(_), None) => std::cmp::Ordering::Greater,
(None, None) => std::cmp::Ordering::Equal,
}
}
}
}

#[async_trait::async_trait]
pub trait Connection: Send + Sync {
fn new(endpoint: String, client: reqwest::Client) -> Self;

async fn is_alive(&self) -> bool {
let check_result = self.is_alive_inner().await;
let is_alive = check_result.as_bool();
self.update_was_dead(!is_alive);

match check_result {
LiveCheckResult::Live(stats) => self.set_stats(Some(stats)),
LiveCheckResult::Dummy => {}
LiveCheckResult::Dead => {}
}

is_alive
}

fn endpoint(&self) -> &str;

fn get_stats(&self) -> Option<Timings>;

fn set_stats(&self, stats: Option<Timings>);

fn update_was_dead(&self, is_dead: bool);

async fn is_alive_inner(&self) -> LiveCheckResult;
}

#[async_trait::async_trait]
impl Connection for Endpoint {
fn new(endpoint: String, client: reqwest::Client) -> Self {
// TODO: parse url to determine type of connection
Self::Jrpc(jrpc::JrpcClient::new(endpoint, client))
}

async fn is_alive(&self) -> bool {
match &self {
Endpoint::Jrpc(client) => client.is_alive().await,
}
}

fn endpoint(&self) -> &str {
match &self {
Endpoint::Jrpc(client) => client.endpoint(),
}
}

fn get_stats(&self) -> Option<Timings> {
match &self {
Endpoint::Jrpc(client) => client.get_stats(),
}
}

fn set_stats(&self, stats: Option<Timings>) {
match &self {
Endpoint::Jrpc(client) => client.set_stats(stats),
}
}

fn update_was_dead(&self, is_dead: bool) {
match &self {
Endpoint::Jrpc(client) => client.update_was_dead(is_dead),
}
}

async fn is_alive_inner(&self) -> LiveCheckResult {
match &self {
Endpoint::Jrpc(client) => client.is_alive_inner().await,
}
}
}
19 changes: 0 additions & 19 deletions transport/src/jrpc.rs

This file was deleted.

Loading

0 comments on commit e65d4b9

Please sign in to comment.