Harvest the latest metrics when `/metrics` is requested

Antonio Scandurra created

Now that we track active projects, if nothing happens to the store
during the activity timeout we would still serve some old metrics
that may not account for the staleness of a project.

This commit changes it so that we grab a mutable reference to the store
before serving the metrics, which has the side effect of updating
all the metrics.

Change summary

crates/collab/src/rpc.rs       | 9 ++++++---
crates/collab/src/rpc/store.rs | 1 -
2 files changed, 6 insertions(+), 4 deletions(-)

Detailed changes

crates/collab/src/rpc.rs 🔗

@@ -1670,10 +1670,10 @@ pub fn routes(server: Arc<Server>) -> Router<Body> {
         .layer(
             ServiceBuilder::new()
                 .layer(Extension(server.app_state.clone()))
-                .layer(middleware::from_fn(auth::validate_header))
-                .layer(Extension(server)),
+                .layer(middleware::from_fn(auth::validate_header)),
         )
         .route("/metrics", get(handle_metrics))
+        .layer(Extension(server))
 }
 
 pub async fn handle_websocket_request(
@@ -1707,7 +1707,10 @@ pub async fn handle_websocket_request(
     })
 }
 
-pub async fn handle_metrics() -> axum::response::Response {
+pub async fn handle_metrics(Extension(server): Extension<Arc<Server>>) -> axum::response::Response {
+    // We call `store_mut` here for its side effects of updating metrics.
+    server.store_mut().await;
+
     let encoder = prometheus::TextEncoder::new();
     let metric_families = prometheus::gather();
     match encoder.encode_to_string(&metric_families) {

crates/collab/src/rpc/store.rs 🔗

@@ -348,7 +348,6 @@ impl Store {
             .get_mut(&project_id)
             .ok_or_else(|| anyhow!("no such project"))?;
         if project.host_connection_id == connection_id {
-            project.last_activity = Some(Instant::now());
             let mut old_worktrees = mem::take(&mut project.worktrees);
             for worktree in worktrees {
                 if let Some(old_worktree) = old_worktrees.remove(&worktree.id) {