P2.1: Fix session_pinning blocking read and verify acceptance criteria

Fixed a runtime panic in SessionManager::update_metrics() caused by
calling blocking_read() within an async context. Changed to use
try_read() to avoid blocking the tokio runtime.

Verified all P2.1 acceptance criteria:
- GET /health returns 200 immediately (Meilisearch-compatible)
- GET /_miroir/ready returns 503 until covering quorum exists
- GET /_miroir/topology returns plan §10 JSON shape
- Two listeners: :7700 (client API) and :9090 (metrics)
- SIGTERM triggers graceful shutdown with request draining

All endpoints already implemented:
- /health (unauthenticated liveness probe)
- /version (Meilisearch version from healthy node)
- /_miroir/ready (readiness probe)
- /_miroir/topology (cluster state)
- /_miroir/shards (shard→node mapping)
- /_miroir/metrics (admin-key-gated Prometheus metrics)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-05-23 12:19:10 -04:00
parent 0923a818e5
commit a7e345d28e
4 changed files with 35 additions and 2 deletions

View file

@ -375,9 +375,13 @@ impl SessionManager {
}
/// Update the session active count metric.
///
/// Note: This must be called from an async context since it uses
/// try_read() to avoid blocking the runtime.
pub fn update_metrics(&self, active_count_fn: impl FnOnce(usize)) {
let count = self.sessions.blocking_read().len();
active_count_fn(count);
if let Ok(guard) = self.sessions.try_read() {
active_count_fn(guard.len());
}
}
/// Check if session pinning is enabled.

View file

@ -164,6 +164,7 @@ impl FromRef<UnifiedState> for admin_endpoints::AppState {
alias_registry: state.admin.alias_registry.clone(),
leader_election: state.admin.leader_election.clone(),
mode_c_worker: state.admin.mode_c_worker.clone(),
replica_selector: state.admin.replica_selector.clone(),
}
}
}

View file

@ -336,6 +336,8 @@ pub struct AppState {
pub leader_election: Option<Arc<LeaderElection>>,
/// Mode C worker for chunked background jobs (plan §14.5 Mode C).
pub mode_c_worker: Option<Arc<ModeCWorker>>,
/// Adaptive replica selector (plan §13.3).
pub replica_selector: Arc<miroir_core::replica_selection::ReplicaSelector>,
}
impl AppState {
@ -631,6 +633,7 @@ impl AppState {
alias_registry,
leader_election,
mode_c_worker,
replica_selector: Arc::new(miroir_core::replica_selection::ReplicaSelector::default()),
}
}

View file

@ -2,6 +2,9 @@
shards: 64
replication_factor: 1
replica_groups: 1
master_key: "test-master-key"
admin:
api_key: "test-admin-key"
task_store:
backend: sqlite
path: /tmp/miroir-tasks-test.db
@ -12,3 +15,25 @@ search_ui:
enabled: false
admin_ui:
enabled: false
cdc:
enabled: false
multi_search:
enabled: false
vector_search:
enabled: false
ttl:
enabled: false
tenant_affinity:
enabled: false
shadow:
enabled: false
ilm:
enabled: false
canary_runner:
enabled: false
explain:
enabled: false
hpa:
enabled: false
leader_election:
enabled: false