Skip to content
Merged
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.9.0](https://github.com/TrueLayer/ginepro/compare/ginepro-v0.8.2...ginepro-v0.8.1) - 2025-07-24

### Breaking changes
- Update to **tonic** 0.13
- Update to **tower** 0.5
- Update to **hickory-resolver** 0.25
- Update to **thiserror** 2

## [0.8.2](https://github.com/TrueLayer/ginepro/compare/ginepro-v0.8.2...ginepro-v0.8.1) - 2024-12-09

### Other
Expand Down
10 changes: 5 additions & 5 deletions ginepro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ginepro"
version = "0.8.2"
version = "0.9.0"
edition = "2021"
description = "A client-side gRPC channel implementation for tonic"
repository = "https://github.com/TrueLayer/ginepro"
Expand All @@ -13,12 +13,12 @@ readme = "../README.md"
anyhow = "1"
async-trait = "0.1"
http = "1"
thiserror = "1"
thiserror = "2"
tokio = { version = "1", features = ["full"] }
tonic = { version = "0.12", features = ["tls"] }
tower = { version = "0.4", default-features = false, features = ["discover"] }
tonic = { version = "0.13", features = ["tls-ring"] }
tower = { version = "0.5", default-features = false, features = ["discover"] }
tracing = "0.1"
hickory-resolver = { version = "0.24", features = ["tokio-runtime"] }
hickory-resolver = { version = "0.25", features = ["tokio"] }

[dev-dependencies]
proptest = "1"
Expand Down
2 changes: 1 addition & 1 deletion ginepro/examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let response = client.unary_echo(request).await?;

println!("RESPONSE={:?}", response);
println!("RESPONSE={response:?}");

Ok(())
}
8 changes: 3 additions & 5 deletions ginepro/examples/client_tls.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use ginepro::LoadBalancedChannel;
use tonic::transport::Certificate;
use tonic::transport::ClientTlsConfig;
use tonic::transport::{Certificate, ClientTlsConfig};

use shared_proto::pb::echo_client::EchoClient;
use shared_proto::pb::EchoRequest;
use shared_proto::pb::{echo_client::EchoClient, EchoRequest};
use tests::tls::TestSslCertificate;

#[tokio::main]
Expand All @@ -30,7 +28,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let response = client.unary_echo(request).await?;

println!("RESPONSE={:?}", response);
println!("RESPONSE={response:?}");

Ok(())
}
2 changes: 1 addition & 1 deletion ginepro/examples/resolution_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let response = client.unary_echo(request).await?;

println!("RESPONSE={:?}", response);
println!("RESPONSE={response:?}");

Ok(())
}
18 changes: 10 additions & 8 deletions ginepro/src/balanced_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ use anyhow::Context as _;
use http::Request;
use std::{
convert::TryInto,
net::SocketAddr,
task::{Context, Poll},
};
use tokio::time::Duration;
use tonic::client::GrpcService;
use tonic::transport::channel::Channel;
use tonic::{body::BoxBody, transport::ClientTlsConfig};
use tonic::transport::ClientTlsConfig;
use tonic::{body::Body, client::GrpcService};
use tower::Service;

// Determines the channel size of the channel we use
Expand Down Expand Up @@ -69,16 +70,16 @@ impl LoadBalancedChannel {
}
}

impl Service<http::Request<BoxBody>> for LoadBalancedChannel {
type Response = http::Response<<Channel as GrpcService<BoxBody>>::ResponseBody>;
type Error = <Channel as GrpcService<BoxBody>>::Error;
type Future = <Channel as GrpcService<BoxBody>>::Future;
impl Service<http::Request<Body>> for LoadBalancedChannel {
type Response = http::Response<<Channel as GrpcService<Body>>::ResponseBody>;
type Error = <Channel as GrpcService<Body>>::Error;
type Future = <Channel as GrpcService<Body>>::Future;

fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
GrpcService::poll_ready(&mut self.0, cx)
}

fn call(&mut self, request: Request<BoxBody>) -> Self::Future {
fn call(&mut self, request: Request<Body>) -> Self::Future {
GrpcService::call(&mut self.0, request)
}
}
Expand Down Expand Up @@ -220,7 +221,8 @@ where
where
U: LookupService + Send + Sync + 'static + Sized,
{
let (channel, sender) = Channel::balance_channel(GRPC_REPORT_ENDPOINTS_CHANNEL_SIZE);
let (channel, sender) =
Channel::balance_channel::<SocketAddr>(GRPC_REPORT_ENDPOINTS_CHANNEL_SIZE);

let config = GrpcServiceProbeConfig {
service_definition: self
Expand Down
18 changes: 8 additions & 10 deletions ginepro/src/dns_resolver.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
//! Implements [`LookupService`] for dns.

use crate::{LookupService, ServiceDefinition};
use anyhow::Context;
use hickory_resolver::{system_conf, AsyncResolver, TokioAsyncResolver};
use std::collections::HashSet;
use std::net::SocketAddr;
use hickory_resolver::TokioResolver;
use std::{collections::HashSet, net::SocketAddr};

/// Implements [`LookupService`] by using DNS queries to lookup [`ServiceDefinition::hostname`].
pub struct DnsResolver {
/// The trust-dns resolver which contacts the dns service directly such
/// that we bypass os-specific dns caching.
dns: TokioAsyncResolver,
dns: TokioResolver,
}

impl DnsResolver {
/// Construct a new [`DnsResolver`] from env and system configuration, e.g `resolv.conf`.
pub async fn from_system_config() -> Result<Self, anyhow::Error> {
let (config, mut opts) = system_conf::read_system_conf()
.context("failed to read dns services from system configuration")?;
let mut builder = TokioResolver::builder_tokio()?;

// We do not want any caching on our side.
let opts = builder.options_mut();
opts.cache_size = 0;

let dns = AsyncResolver::tokio(config, opts);

Ok(Self { dns })
Ok(Self {
dns: builder.build(),
})
}
}

Expand Down
6 changes: 4 additions & 2 deletions ginepro/src/service_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use crate::{LookupService, ServiceDefinition};
use std::collections::HashSet;
use std::net::SocketAddr;
use tokio::sync::mpsc::Sender;
use tonic::transport::{channel::Endpoint, ClientTlsConfig};
use tower::discover::Change;
use tonic::transport::{
channel::{Change, Endpoint},
ClientTlsConfig,
};

#[derive(thiserror::Error, Debug)]
pub enum ProbeError {
Expand Down
4 changes: 2 additions & 2 deletions shared_proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ publish = false

[dependencies]
prost = "0.13"
tonic = "0.12"
tonic = "0.13"

[build-dependencies]
tonic-build = "0.12"
tonic-build = "0.13"
4 changes: 2 additions & 2 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ hyper = "1"
openssl = "0.10"
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1", features = ["net"] }
tonic = { version = "0.12", features = ["tls"] }
tonic = { version = "0.13", features = ["tls-ring"] }
tower-layer = "0.3"
tower-service = "0.3"
tracing = { version = "0.1", features = ["attributes", "log"] }
Expand All @@ -22,4 +22,4 @@ tracing = { version = "0.1", features = ["attributes", "log"] }
anyhow = "1"
async-trait = "0.1"
shared-proto = { path = "../shared_proto" }
tonic-health = "0.12"
tonic-health = "0.13"
17 changes: 9 additions & 8 deletions tests/src/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use std::{
use tokio::net::{TcpListener, TcpStream};
use tokio_stream::wrappers::TcpListenerStream;
use tonic::{
body::BoxBody,
body::Body,
server::NamedService,
service::Routes,
transport::{
server::{Router, Server},
ServerTlsConfig,
},
};
use tonic::{server::NamedService, service::Routes};
use tower_layer::Layer;
use tower_service::Service;

Expand Down Expand Up @@ -45,10 +46,11 @@ impl TestServer {
tls: Option<ServerTlsConfig>,
) -> Self
where
S: Service<Request<BoxBody>, Response = Response<BoxBody>, Error = Infallible>
S: Service<Request<Body>, Response = Response<Body>, Error = Infallible>
+ NamedService
+ Clone
+ Send
+ Sync
+ 'static,
S::Future: Send + 'static,
S::Error: Into<Box<dyn std::error::Error + Send + Sync>> + Send,
Expand Down Expand Up @@ -86,10 +88,9 @@ impl TestServer {
pub async fn start_with_router<L, T>(router: Router<L>, address: T) -> TestServer
where
L: Layer<Routes> + Send + 'static,
L::Service:
Service<Request<BoxBody>, Response = Response<BoxBody>> + Clone + Send + 'static,
<<L as Layer<Routes>>::Service as Service<Request<BoxBody>>>::Future: Send + 'static,
<<L as Layer<Routes>>::Service as Service<Request<BoxBody>>>::Error:
L::Service: Service<Request<Body>, Response = Response<Body>> + Clone + Send + 'static,
<<L as Layer<Routes>>::Service as Service<Request<Body>>>::Future: Send + 'static,
<<L as Layer<Routes>>::Service as Service<Request<Body>>>::Error:
Into<Box<dyn std::error::Error + Send + Sync>> + Send,
T: Into<Option<String>>,
{
Expand All @@ -116,7 +117,7 @@ impl TestServer {
let wait_start = Instant::now();
while let Err(e) = TcpStream::connect(listener_addr).await {
if wait_start.elapsed() > Duration::from_secs(10) {
panic!("Cannot connect to {}: {}", listener_addr, e);
panic!("Cannot connect to {listener_addr}: {e}");
}
tokio::task::yield_now().await;
}
Expand Down
Loading