mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
refactor: extract runtime state backends
This commit is contained in:
@@ -8,6 +8,7 @@ description = "Tunnel proxy for Aether"
|
||||
aether-contracts.workspace = true
|
||||
aether-http.workspace = true
|
||||
aether-runtime.workspace = true
|
||||
aether-runtime-state.workspace = true
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
reqwest.workspace = true
|
||||
hyper = { version = "1", features = ["client", "http1", "http2"] }
|
||||
|
||||
@@ -6,10 +6,8 @@ use std::sync::{Arc, RwLock};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use aether_http::{jittered_delay_for_retry, HttpRetryConfig};
|
||||
use aether_runtime::{
|
||||
init_reloadable_service_tracing, wait_for_shutdown_signal, ConcurrencyGate,
|
||||
DistributedConcurrencyGate, RedisDistributedConcurrencyConfig,
|
||||
};
|
||||
use aether_runtime::{init_reloadable_service_tracing, wait_for_shutdown_signal, ConcurrencyGate};
|
||||
use aether_runtime_state::{RedisClientConfig, RuntimeSemaphoreConfig, RuntimeState};
|
||||
use arc_swap::ArcSwap;
|
||||
use tokio::sync::{watch, Mutex};
|
||||
use tokio::task::JoinHandle;
|
||||
@@ -225,12 +223,18 @@ pub async fn run(mut config: Config, servers: Vec<ServerEntry>) -> anyhow::Resul
|
||||
.distributed_stream_redis_url
|
||||
.clone()
|
||||
.expect("distributed stream redis url should be validated");
|
||||
let distributed_gate = DistributedConcurrencyGate::new_redis(
|
||||
"proxy_streams_distributed",
|
||||
limit,
|
||||
RedisDistributedConcurrencyConfig {
|
||||
let runtime = RuntimeState::redis(
|
||||
RedisClientConfig {
|
||||
url: redis_url,
|
||||
key_prefix: state.config.distributed_stream_redis_key_prefix.clone(),
|
||||
},
|
||||
Some(state.config.distributed_stream_command_timeout_ms),
|
||||
)
|
||||
.await?;
|
||||
let distributed_gate = runtime.semaphore(
|
||||
"proxy_streams_distributed",
|
||||
limit,
|
||||
RuntimeSemaphoreConfig {
|
||||
lease_ttl_ms: state.config.distributed_stream_lease_ttl_ms,
|
||||
renew_interval_ms: state.config.distributed_stream_renew_interval_ms,
|
||||
command_timeout_ms: Some(state.config.distributed_stream_command_timeout_ms),
|
||||
|
||||
@@ -4,10 +4,8 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
|
||||
use aether_runtime::{
|
||||
AdmissionPermit, ConcurrencyError, ConcurrencyGate, ConcurrencySnapshot,
|
||||
DistributedConcurrencyError, DistributedConcurrencyGate, DistributedConcurrencySnapshot,
|
||||
};
|
||||
use aether_runtime::{AdmissionPermit, ConcurrencyError, ConcurrencyGate, ConcurrencySnapshot};
|
||||
use aether_runtime_state::{RuntimeSemaphore, RuntimeSemaphoreError, RuntimeSemaphoreSnapshot};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::registration::client::AetherClient;
|
||||
@@ -27,7 +25,7 @@ pub struct AppState {
|
||||
/// Optional per-process stream admission gate.
|
||||
pub stream_gate: Option<Arc<ConcurrencyGate>>,
|
||||
/// Optional cross-instance stream admission gate.
|
||||
pub distributed_stream_gate: Option<Arc<DistributedConcurrencyGate>>,
|
||||
pub distributed_stream_gate: Option<Arc<RuntimeSemaphore>>,
|
||||
}
|
||||
|
||||
/// Per-server state: one instance per Aether server connection.
|
||||
@@ -103,10 +101,7 @@ impl AppState {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_distributed_stream_concurrency_gate(
|
||||
mut self,
|
||||
gate: Arc<DistributedConcurrencyGate>,
|
||||
) -> Self {
|
||||
pub fn with_distributed_stream_concurrency_gate(mut self, gate: Arc<RuntimeSemaphore>) -> Self {
|
||||
self.distributed_stream_gate = Some(gate);
|
||||
self
|
||||
}
|
||||
@@ -117,7 +112,7 @@ impl AppState {
|
||||
|
||||
pub async fn distributed_stream_concurrency_snapshot(
|
||||
&self,
|
||||
) -> Result<Option<DistributedConcurrencySnapshot>, DistributedConcurrencyError> {
|
||||
) -> Result<Option<RuntimeSemaphoreSnapshot>, RuntimeSemaphoreError> {
|
||||
match &self.distributed_stream_gate {
|
||||
Some(gate) => gate.snapshot().await.map(Some),
|
||||
None => Ok(None),
|
||||
@@ -150,10 +145,10 @@ impl AppState {
|
||||
let distributed = match &self.distributed_stream_gate {
|
||||
Some(gate) => Some(gate.try_acquire().await.map_err(|err| {
|
||||
match err {
|
||||
DistributedConcurrencyError::Saturated { gate, limit } => {
|
||||
RuntimeSemaphoreError::Saturated { gate, limit } => {
|
||||
ProxyAdmissionError::Saturated { gate, limit }
|
||||
}
|
||||
DistributedConcurrencyError::Unavailable {
|
||||
RuntimeSemaphoreError::Unavailable {
|
||||
gate,
|
||||
limit,
|
||||
message,
|
||||
@@ -162,7 +157,7 @@ impl AppState {
|
||||
limit,
|
||||
message,
|
||||
},
|
||||
DistributedConcurrencyError::InvalidConfiguration(message) => {
|
||||
RuntimeSemaphoreError::InvalidConfiguration(message) => {
|
||||
ProxyAdmissionError::Unavailable {
|
||||
gate: "proxy_streams_distributed",
|
||||
limit: self
|
||||
|
||||
@@ -1515,7 +1515,10 @@ mod tests {
|
||||
use std::sync::{Mutex, Once};
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use aether_runtime::{ConcurrencyGate, DistributedConcurrencyGate};
|
||||
use aether_runtime::ConcurrencyGate;
|
||||
use aether_runtime_state::{
|
||||
MemoryRuntimeStateConfig, RuntimeSemaphore, RuntimeSemaphoreConfig, RuntimeState,
|
||||
};
|
||||
use arc_swap::ArcSwap;
|
||||
use axum::body::Body;
|
||||
use axum::http::{header, HeaderMap, Response, StatusCode};
|
||||
@@ -2206,10 +2209,15 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn rejects_stream_when_distributed_admission_gate_is_saturated() {
|
||||
let gate = Arc::new(DistributedConcurrencyGate::new_in_memory(
|
||||
"proxy_streams_distributed",
|
||||
1,
|
||||
));
|
||||
let gate = Arc::new(
|
||||
RuntimeState::memory(MemoryRuntimeStateConfig::default())
|
||||
.semaphore(
|
||||
"proxy_streams_distributed",
|
||||
1,
|
||||
RuntimeSemaphoreConfig::default(),
|
||||
)
|
||||
.expect("distributed semaphore"),
|
||||
);
|
||||
let _permit = gate.try_acquire().await.expect("first permit");
|
||||
let state = sample_state(None, Some(gate));
|
||||
let server = sample_server(&state);
|
||||
@@ -2264,7 +2272,7 @@ mod tests {
|
||||
|
||||
fn sample_state(
|
||||
stream_gate: Option<Arc<ConcurrencyGate>>,
|
||||
distributed_stream_gate: Option<Arc<DistributedConcurrencyGate>>,
|
||||
distributed_stream_gate: Option<Arc<RuntimeSemaphore>>,
|
||||
) -> Arc<AppState> {
|
||||
ensure_rustls_provider();
|
||||
let config = Arc::new(sample_config());
|
||||
|
||||
Reference in New Issue
Block a user