mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-04 23:12:27 +02:00
staged m3u to xtream fix (#877)
* staged m3u to xtream fix * staged m3u to xtream fix * staged m3u to xtream fix * fixed race some conditions * fixed race some conditions * fixed race some conditions * fixed race some conditions * fixed race some conditions --------- Co-authored-by: euzu <euzu@proton.me>
This commit is contained in:
@@ -6052,7 +6052,7 @@ async fn grace_context_is_populated_when_grace_strategy_is_actually_granted() {
|
||||
async fn evaluate_remaining_strategies_evicts_after_used_grace() {
|
||||
// Strategies: [GraceHoldStream, EvictUserOldest]
|
||||
// Grace was used at index 0, so only EvictUserOldest (index 1) is evaluated.
|
||||
// Eviction frees the slot -> Allowed.
|
||||
// The new request stays retryable while the evicted stream still owns its provider slot.
|
||||
let strategies = vec![AdmissionStrategy::GraceHoldStream, AdmissionStrategy::EvictUserOldest];
|
||||
let grace_context = GraceResolutionContext { strategy_index: 0, strategies: strategies.into(), kind: None };
|
||||
|
||||
@@ -6073,6 +6073,9 @@ async fn evaluate_remaining_strategies_evicts_after_used_grace() {
|
||||
recent_eviction_reentry_ttl: std::time::Duration::from_millis(1500),
|
||||
admission_strategies: Some(vec![AdmissionStrategy::GraceHoldStream, AdmissionStrategy::EvictUserOldest]),
|
||||
});
|
||||
let provider_config = create_test_provider_app_config();
|
||||
app_state.app_config.sources.store(provider_config.sources.load_full());
|
||||
app_state.active_provider.update_config(&app_state.app_config);
|
||||
|
||||
let addr1: SocketAddr = "127.0.0.1:55701".parse().unwrap_or_else(|_| unreachable!());
|
||||
let addr2: SocketAddr = "10.0.0.5:55702".parse().unwrap_or_else(|_| unreachable!());
|
||||
@@ -6121,23 +6124,71 @@ async fn evaluate_remaining_strategies_evicts_after_used_grace() {
|
||||
.await
|
||||
.expect("stream should be created");
|
||||
|
||||
let result = evaluate_remaining_strategies_after_grace(
|
||||
&app_state.admission_ctx(),
|
||||
AdmissionRequest {
|
||||
username: "remaining-evict",
|
||||
max_connections: 1,
|
||||
soft_connections: 0,
|
||||
client_ip: &fingerprint2.client_ip,
|
||||
request_addr: &fingerprint2.addr,
|
||||
use_session_admission: true,
|
||||
session_token: Some("tok-new"),
|
||||
activate_unbound_session: true,
|
||||
eviction_reentry_guard: EvictionReentryGuard::Session("tok-new"),
|
||||
},
|
||||
&grace_context,
|
||||
Some(crate::api::model::ConnectionKind::Normal),
|
||||
let provider_handle = app_state
|
||||
.active_provider
|
||||
.acquire_connection_with_grace_for_session(
|
||||
&"provider_1".intern(),
|
||||
&addr1,
|
||||
false,
|
||||
0,
|
||||
crate::api::model::ConnectionKind::Normal,
|
||||
Some("tok-counted"),
|
||||
)
|
||||
.expect("old stream should occupy the only provider slot");
|
||||
assert!(app_state.active_provider.register_body_owner(provider_handle.allocation_id));
|
||||
let close_rx = app_state.connection_manager.register_close_socket(addr1);
|
||||
let manager = Arc::clone(&app_state.connection_manager);
|
||||
let provider = Arc::clone(&app_state.active_provider);
|
||||
let release_body = Arc::new(tokio::sync::Notify::new());
|
||||
let release_body_after_timeout = Arc::clone(&release_body);
|
||||
let close_task = tokio::spawn(async move {
|
||||
assert_eq!(close_rx.await.expect("kick close signal"), shared::model::DisconnectReason::ClientKicked);
|
||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||
manager.release_provider_deferred(&addr1).await;
|
||||
assert_eq!(provider.get_provider_connections_count(), 1, "body owner still holds provider capacity");
|
||||
release_body_after_timeout.notified().await;
|
||||
provider.release_handle(&provider_handle);
|
||||
provider_handle.completion_token.as_ref().expect("body completion token").cancel();
|
||||
manager.unregister_close_socket(&addr1);
|
||||
});
|
||||
|
||||
let request = || AdmissionRequest {
|
||||
username: "remaining-evict",
|
||||
max_connections: 1,
|
||||
soft_connections: 0,
|
||||
client_ip: &fingerprint2.client_ip,
|
||||
request_addr: &fingerprint2.addr,
|
||||
use_session_admission: true,
|
||||
session_token: Some("tok-new"),
|
||||
activate_unbound_session: true,
|
||||
eviction_reentry_guard: EvictionReentryGuard::Session("tok-new"),
|
||||
};
|
||||
let result = tokio::time::timeout(
|
||||
std::time::Duration::from_secs(5),
|
||||
evaluate_remaining_strategies_after_grace(
|
||||
&app_state.admission_ctx(),
|
||||
request(),
|
||||
&grace_context,
|
||||
Some(crate::api::model::ConnectionKind::Normal),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.expect("admission must remain retryable while the provider slot is held");
|
||||
|
||||
assert_eq!(result.admission.permission(), UserConnectionPermission::Exhausted);
|
||||
assert_eq!(app_state.active_provider.get_provider_connections_count(), 1);
|
||||
|
||||
let retry = tokio::time::timeout(
|
||||
std::time::Duration::from_secs(5),
|
||||
resolve_admission_with_strategies(&app_state.admission_ctx(), request()),
|
||||
)
|
||||
.await
|
||||
.expect("retry must remain bounded while the provider slot is held");
|
||||
assert_eq!(retry.admission.permission(), UserConnectionPermission::Exhausted);
|
||||
|
||||
release_body.notify_one();
|
||||
close_task.await.expect("old transport cleanup");
|
||||
let result = resolve_admission_with_strategies(&app_state.admission_ctx(), request()).await;
|
||||
|
||||
assert_eq!(
|
||||
result.admission.permission(),
|
||||
@@ -6145,6 +6196,23 @@ async fn evaluate_remaining_strategies_evicts_after_used_grace() {
|
||||
"EvictUserOldest should free the slot"
|
||||
);
|
||||
assert!(result.grace_context.is_none(), "no grace context on eviction success");
|
||||
assert_eq!(
|
||||
app_state.active_provider.get_provider_connections_count(),
|
||||
0,
|
||||
"admission must not return while the evicted stream still owns the provider slot"
|
||||
);
|
||||
let replacement = app_state.active_provider.acquire_connection_with_grace_for_session(
|
||||
&"provider_1".intern(),
|
||||
&addr2,
|
||||
false,
|
||||
0,
|
||||
crate::api::model::ConnectionKind::Normal,
|
||||
Some("tok-new"),
|
||||
);
|
||||
assert!(replacement.is_some(), "newly admitted stream must acquire the freed provider slot");
|
||||
if let Some(replacement) = replacement {
|
||||
app_state.active_provider.release_handle(&replacement);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user