mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
app-server: Only unload threads which were unused for some time (#17398)
Currently app-server may unload actively running threads once the last connection disconnects, which is not expected. Instead track when was the last active turn & when there were any subscribers the last time, also add 30 minute idleness/no subscribers timer to reduce the churn.
This commit is contained in:
committed by
GitHub
Unverified
parent
d905376628
commit
a5507b59c4
@@ -16,6 +16,7 @@ use std::sync::Weak;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::oneshot;
|
||||
use tokio::sync::watch;
|
||||
use tracing::error;
|
||||
|
||||
type PendingInterruptQueue = Vec<(
|
||||
@@ -159,6 +160,7 @@ pub(crate) async fn resolve_server_request_on_thread_listener(
|
||||
struct ThreadEntry {
|
||||
state: Arc<Mutex<ThreadState>>,
|
||||
connection_ids: HashSet<ConnectionId>,
|
||||
has_connections_watcher: watch::Sender<bool>,
|
||||
}
|
||||
|
||||
impl Default for ThreadEntry {
|
||||
@@ -166,10 +168,21 @@ impl Default for ThreadEntry {
|
||||
Self {
|
||||
state: Arc::new(Mutex::new(ThreadState::default())),
|
||||
connection_ids: HashSet::new(),
|
||||
has_connections_watcher: watch::channel(false).0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ThreadEntry {
|
||||
fn update_has_connections(&self) {
|
||||
let _ = self.has_connections_watcher.send_if_modified(|current| {
|
||||
let prev = *current;
|
||||
*current = !self.connection_ids.is_empty();
|
||||
prev != *current
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ThreadStateManagerInner {
|
||||
live_connections: HashSet<ConnectionId>,
|
||||
@@ -286,12 +299,14 @@ impl ThreadStateManager {
|
||||
}
|
||||
if let Some(thread_entry) = state.threads.get_mut(&thread_id) {
|
||||
thread_entry.connection_ids.remove(&connection_id);
|
||||
thread_entry.update_has_connections();
|
||||
}
|
||||
};
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn has_subscribers(&self, thread_id: ThreadId) -> bool {
|
||||
self.state
|
||||
.lock()
|
||||
@@ -319,6 +334,7 @@ impl ThreadStateManager {
|
||||
.insert(thread_id);
|
||||
let thread_entry = state.threads.entry(thread_id).or_default();
|
||||
thread_entry.connection_ids.insert(connection_id);
|
||||
thread_entry.update_has_connections();
|
||||
thread_entry.state.clone()
|
||||
};
|
||||
{
|
||||
@@ -344,12 +360,9 @@ impl ThreadStateManager {
|
||||
.entry(connection_id)
|
||||
.or_default()
|
||||
.insert(thread_id);
|
||||
state
|
||||
.threads
|
||||
.entry(thread_id)
|
||||
.or_default()
|
||||
.connection_ids
|
||||
.insert(connection_id);
|
||||
let thread_entry = state.threads.entry(thread_id).or_default();
|
||||
thread_entry.connection_ids.insert(connection_id);
|
||||
thread_entry.update_has_connections();
|
||||
true
|
||||
}
|
||||
|
||||
@@ -364,6 +377,7 @@ impl ThreadStateManager {
|
||||
for thread_id in &thread_ids {
|
||||
if let Some(thread_entry) = state.threads.get_mut(thread_id) {
|
||||
thread_entry.connection_ids.remove(&connection_id);
|
||||
thread_entry.update_has_connections();
|
||||
}
|
||||
}
|
||||
thread_ids
|
||||
@@ -377,4 +391,15 @@ impl ThreadStateManager {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn subscribe_to_has_connections(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> Option<watch::Receiver<bool>> {
|
||||
let state = self.state.lock().await;
|
||||
state
|
||||
.threads
|
||||
.get(&thread_id)
|
||||
.map(|thread_entry| thread_entry.has_connections_watcher.subscribe())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user