Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,25 @@
[package]
name = "opengemini"
version = "0.0.1"
edition = "2021"
edition = "2024"
description = "Rust client for OpenGemini"
license = "Apache-2.0"
repository = "https://github.com/openGemini/opengemini-client-rust"
homepage = "https://github.com/openGemini/opengemini-client-rust"

[dependencies]
reqwest = { version = "0.12.7", features = ["json", "__rustls", "blocking", "gzip"] }
serde = { version = "1.0.208", features = ["derive"] }
serde_json = "1.0.125"
thiserror = "1.0.64"
tokio = "1.40.0"
log = "0.4.28"
reqwest = { version = "0.12.24", features = [
"json",
"__rustls",
"blocking",
"gzip",
] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
thiserror = "2.0.17"
tokio = "1.48.0"
zigzag = "0.1.0"

[dev-dependencies]
static_init = "1.0.4"
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

mod config;
mod error;
pub mod config;
pub mod error;
mod opengemini_client;
mod url_const;

Expand Down
90 changes: 7 additions & 83 deletions src/opengemini_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ impl Client {
}

pub fn ping(&self, idx: usize) -> Result<bool, ClientError> {
if idx >= self.endpoints.len() as usize {
if idx >= self.endpoints.len() {
return Err(ClientError::ValueError("Index out of range".to_string()));
}
let url: String = self.endpoints[idx].url.clone() + URL_PING;
match reqwest::blocking::get(url) {
Ok(response) => {
if response.status().is_success() {
return Ok(true);
Ok(true)
} else {
return Ok(false);
Ok(false)
}
}
Err(_) => Err(ClientError::ConnectionError),
Expand All @@ -82,10 +82,11 @@ impl Client {
todo!();
}

fn get_server_url(&self) -> Option<String> {
pub fn get_server_url(&self) -> Option<String> {
let current_index = self.prev_idx.load(Ordering::SeqCst);
let endpoint_count = self.endpoints.len() as i32;
let url = if endpoint_count > 0 {

if endpoint_count > 0 {
let url = self.endpoints[current_index as usize % endpoint_count as usize]
.url
.clone();
Expand All @@ -94,8 +95,7 @@ impl Client {
Some(url)
} else {
None
};
url
}
}
}

Expand All @@ -111,79 +111,3 @@ pub fn build_endpoints(addresses: Vec<Address>) -> Vec<Endpoint> {
})
.collect()
}

#[cfg(test)]
mod tests {
use std::time::Duration;

use crate::config::{AuthConfig, BatchConfig};

use super::*;

fn create_test_config() -> Config {
Config {
address: vec![Address {
host: "127.0.0.1".to_string(),
port: 8086,
}],
batch_config: BatchConfig {
batch_interval: Duration::from_secs(30),
batch_size: 100,
},
timeout: Duration::from_secs(30),
connect_timeout: Duration::from_secs(10),
gzip_enabled: true,
auth_config: AuthConfig {
username: "user".to_string(),
password: "password".to_string(),
token: None,
auth_type: 1,
},
}
}

#[test]
fn test_get_server_url() {
let addresses = vec![
Address {
host: "127.0.0.1".to_string(),
port: 8086,
},
Address {
host: "127.0.0.2".to_string(),
port: 8087,
},
];
let mut config = create_test_config();

config.address = addresses;

let client = Client::new(&config);

let url1 = client.get_server_url();
let url2 = client.get_server_url();

assert!(url1.is_some());
assert!(url2.is_some());
assert_ne!(url1, url2);
}

/// Tests the `ping` method of the `Client` struct.
///
/// This test sets up a `Client` with a single address and checks if the `ping` method
/// returns `Ok(true)` when the server is reachable.
///
/// Before running this test, make sure to start the server using the following Docker command:
/// ```sh
/// docker run -p 8086:8086 --name opengemini --rm opengeminidb/opengemini-server
/// ```
#[test]
fn test_ping_success() {
let config = create_test_config();
let client = Client::new(&config);

let result = client.ping(0);
assert!(result.is_ok());
assert_eq!(result.unwrap(), true);
}
}
8 changes: 4 additions & 4 deletions src/url_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

pub const URL_PING: &'static str = "/ping";
pub const URL_QUERY: &'static str = "/query";
pub const URL_STATUS: &'static str = "/status";
pub const URL_WRITE_OUTPUT: &'static str = "/write";
pub const URL_PING: &str = "/ping";
pub const URL_QUERY: &str = "/query";
pub const URL_STATUS: &str = "/status";
pub const URL_WRITE_OUTPUT: &str = "/write";
33 changes: 33 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash

set -e
DIR=$(realpath $0) && DIR=${DIR%/*}
cd $DIR
# set -x

PORT_LI="8086 8087"

stop() {
for i in $PORT_LI; do
docker stop opengemini-rust-client-test-$i || true
done
}

trap stop EXIT

boot() {
for i in $PORT_LI; do
docker run --rm -d -p $i:8086 --name opengemini-rust-client-test-$i opengeminidb/opengemini-server:latest || stop
done
for i in $PORT_LI; do
while ! nc -z localhost $i; do
echo "wait for port $i"
sleep 1
done
done
}

boot
sleep 3

RUST_LOG=debug RUST_BACKTRACE=1 cargo test --all-features -- --nocapture
63 changes: 63 additions & 0 deletions tests/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use opengemini::Client;
use opengemini::config::{Address, AuthConfig, BatchConfig, Config};
use std::time::Duration;

#[static_init::dynamic]
static CONFIG: Config = Config {
address: vec![Address {
host: "127.0.0.1".to_string(),
port: 8086,
}],
batch_config: BatchConfig {
batch_interval: Duration::from_secs(30),
batch_size: 100,
},
timeout: Duration::from_secs(30),
connect_timeout: Duration::from_secs(10),
gzip_enabled: true,
auth_config: AuthConfig {
username: "user".to_string(),
password: "password".to_string(),
token: None,
auth_type: 1,
},
};

#[test]
fn test_get_server_url() {
let mut config = CONFIG.clone();
config.address.push(Address {
host: "127.0.0.1".to_string(),
port: 8087,
});

let client = Client::new(&config);

let url1 = client.get_server_url();
let url2 = client.get_server_url();

assert!(url1.is_some());
assert!(url2.is_some());
assert_ne!(url1, url2);
}

/// Tests the `ping` method of the `Client` struct.
///
/// This test sets up a `Client` with a single address and checks if the `ping` method
/// returns `Ok(true)` when the server is reachable.
///
/// Before running this test, make sure to start the server using the following Docker command:
/// ```sh
/// docker run -p 8086:8086 --name opengemini --rm opengeminidb/opengemini-server
/// ```
#[test]
fn test_ping_success() {
let client = Client::new(&CONFIG);

let result = client.ping(0);
if result.is_err() {
log::info!("{:?}", &result);
}
assert!(result.is_ok());
assert!(result.unwrap());
}
Loading