refactor(relay): address revalidation review

Restore CommunityDisconnectReason near the top of state.rs and document scan deadline and reconnect-load limitations. Authorization behavior is unchanged.

Signed-off-by: seiler <seiler@squareup.com>
Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit a4d1ab288d761d44eba25cc62d25b7d2858788dc)
Signed-off-by: Brad Seiler <seiler@squareup.com>
This commit is contained in:
seiler
2026-10-06 15:12:19 +00:00
committed by Brad Seiler
parent b4b10690e4
commit d9358912ef
2 changed files with 14 additions and 41 deletions

View File

@@ -336,6 +336,12 @@ recovers performs the ordinary admission checks. The worker shares graceful
shutdown cancellation and has no migration or rollout flag; all relay pods
must run this code for the bound to hold deployment-wide.
Targets are ordered deterministically within each scan, so repeated deadline
hits can leave the same tail targets unqueried and fail-close them after grace.
This path does not rotate scan order or jitter authorization-driven closes; if
writer saturation lasts beyond grace, many sockets on a pod can close together
and create a reconnect herd.
### Step 5: Cleanup
On disconnect (any cause):

View File

@@ -52,6 +52,8 @@ pub(crate) enum CommunityDisconnectReason {
AuthorizationDenied,
/// The authenticated pubkey lost access to the community (e.g. a ban).
AccessRevoked,
/// The relay could not re-establish the socket's access decision.
AuthorizationUnavailable,
}
impl CommunityDisconnectReason {
@@ -69,6 +71,12 @@ impl CommunityDisconnectReason {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("authorization denied"),
})),
Self::AuthorizationUnavailable => {
WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("authorization unavailable"),
}))
}
Self::AccessRevoked => WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("access revoked"),
@@ -6786,44 +6794,3 @@ pub(crate) struct LiveAuthorizationSession {
/// Most recent successful authoritative access check.
pub last_checked_at: TokioInstant,
}
/// Why a community-bound socket is being asked to stop.
///
/// Only deletion is externally attributed today. Ordinary lifecycle exits keep
/// using cancellation alone and therefore retain the existing bare-close
/// behavior.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum CommunityDisconnectReason {
CommunityDeleted,
/// NIP-FI: the connection's proven pubkey was added to the deny set.
AuthorizationDenied,
/// The authenticated pubkey lost access to the community (e.g. a ban).
AccessRevoked,
/// The relay could not re-establish the socket's access decision.
AuthorizationUnavailable,
}
impl CommunityDisconnectReason {
pub(crate) fn close_message(self) -> WsMessage {
match self {
Self::CommunityDeleted => WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("community deleted"),
})),
Self::AuthorizationDenied => WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("authorization denied"),
})),
Self::AccessRevoked => WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("access revoked"),
})),
Self::AuthorizationUnavailable => {
WsMessage::Close(Some(axum::extract::ws::CloseFrame {
code: axum::extract::ws::close_code::POLICY,
reason: WsUtf8Bytes::from_static("authorization unavailable"),
}))
}
}
}
}