use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread::JoinHandle;

use chrono::{DateTime, Utc};
use tokio::sync::oneshot;
use tranquil_db_traits::DbScope;
use tranquil_db_traits::{
    AccountSearchResult, AccountStatus, AdminAccountInfo, ApplyCommitError, ApplyCommitInput,
    ApplyCommitResult, Backlink, CommitEventData, CommsChannel, CommsType,
    CompletePasskeySetupInput, CreateAccountError, CreateDelegatedAccountInput,
    CreatePasskeyAccountInput, CreatePasswordAccountInput, CreatePasswordAccountResult,
    CreateSsoAccountInput, DbError, DelegationActionType, DeletionRequest,
    DeletionRequestWithToken, DidWebOverrides, ImportBlock, ImportRecord, ImportRepoError,
    InviteCodeError, InviteCodeInfo, InviteCodeRow, InviteCodeSortOrder, InviteCodeUse,
    MigrationReactivationError, MigrationReactivationInput, NotificationHistoryRow,
    NotificationPrefs, OAuthTokenWithUser, PasswordResetResult, PlcTokenInfo, QueuedComms,
    ReactivatedAccountInfo, RecoverPasskeyAccountInput, RecoverPasskeyAccountResult,
    RefreshSessionResult, ReservedSigningKey, ReservedSigningKeyFull, ScheduledDeletionAccount,
    ScopePreference, SequenceNumber, SequencedEvent, SessionId, StoredBackupCode, StoredPasskey,
    TokenFamilyId, TotpRecord, TotpRecordState, User2faStatus, UserAuthInfo, UserCommsPrefs,
    UserConfirmSignup, UserDidWebInfo, UserEmailInfo, UserForDeletion, UserForDidDoc,
    UserForDidDocBuild, UserForPasskeyRecovery, UserForPasskeySetup, UserForRecovery,
    UserForVerification, UserIdAndHandle, UserIdAndPasswordHash, UserIdHandleEmail,
    UserInfoForAuth, UserKeyInfo, UserKeyWithId, UserLegacyLoginPref, UserLoginCheck,
    UserLoginFull, UserLoginInfo, UserNeedingRecordBlobsBackfill, UserPasswordInfo,
    UserResendVerification, UserResetCodeInfo, UserRow, UserSessionInfo, UserStatus,
    UserVerificationInfo, UserWithKey, UserWithoutBlocks, ValidatedInviteCode,
    WebauthnChallengeType,
};
use tranquil_oauth::{AuthorizedClientData, DeviceData, RequestData, TokenData};
use tranquil_types::{
    AtUri, AuthorizationCode, CidLink, ClientId, DPoPProofId, DeviceId, Did, Handle, InviteCode,
    Nsid, RefreshToken, RequestId, Rkey, Tid, TokenId,
};
use uuid::Uuid;

use super::MetastoreError;
use super::commit_ops::CommitOps;
use super::event_ops::EventOps;
use super::infra_ops::InfraOps;
use super::keys::UserHash;
use super::record_ops::ListRecordsQuery;
use super::user_hash::UserHashMap;
use crate::blockstore::TranquilBlockStore;
use crate::clock::SystemClock;
use crate::eventlog::EventLogBridge;
use crate::io::{RealIO, StorageIO};
use crate::metastore::Metastore;

type Tx<T> = oneshot::Sender<Result<T, DbError>>;

fn reserve_invite(infra: &InfraOps, code: Option<&InviteCode>) -> Result<(), CreateAccountError> {
    match code {
        Some(code) => infra.reserve_invite_code(code).map_err(|e| match e {
            InviteCodeError::DatabaseError(e) => CreateAccountError::Database(e.to_string()),
            _ => CreateAccountError::InviteCodeUnavailable,
        }),
        None => Ok(()),
    }
}

fn record_invite_use(
    infra: &InfraOps,
    code: Option<&InviteCode>,
    user_id: Uuid,
) -> Result<(), CreateAccountError> {
    match code {
        Some(code) => {
            let validated = ValidatedInviteCode::new_validated(code);
            infra
                .record_invite_code_use(&validated, user_id)
                .map_err(|e| CreateAccountError::Database(e.to_string()))
        }
        None => Ok(()),
    }
}

fn refund_invite(infra: &InfraOps, code: Option<&InviteCode>) {
    if let Some(code) = code
        && let Err(e) = infra.refund_invite_code(code)
    {
        tracing::error!("failed to refund invite code after account creation failed: {e:?}");
    }
}

fn finalize_account<T>(
    infra: &InfraOps,
    code: Option<&InviteCode>,
    created: Result<T, CreateAccountError>,
    after: impl FnOnce(&T) -> Result<Uuid, CreateAccountError>,
) -> Result<T, CreateAccountError> {
    match created {
        Ok(result) => {
            let user_id = after(&result)?;
            record_invite_use(infra, code, user_id)?;
            Ok(result)
        }
        Err(e) => {
            refund_invite(infra, code);
            Err(e)
        }
    }
}

fn metastore_to_db(e: MetastoreError) -> DbError {
    match e {
        MetastoreError::Fjall(e) => DbError::Query(e.to_string()),
        MetastoreError::Lsm(e) => DbError::Query(e.to_string()),
        MetastoreError::VersionMismatch { expected, found } => DbError::Query(format!(
            "format version mismatch: expected {expected}, found {found}"
        )),
        MetastoreError::CorruptData(msg) => DbError::CorruptData(msg),
        MetastoreError::InvalidInput(msg) => DbError::Query(msg.to_string()),
        MetastoreError::UserHashCollision {
            hash,
            existing_uuid,
            new_uuid,
        } => DbError::Constraint(format!(
            "user hash collision: {hash} maps to both {existing_uuid} and {new_uuid}"
        )),
        MetastoreError::UniqueViolation(constraint) => {
            DbError::Constraint(format!("unique constraint violated: {constraint}"))
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Routing {
    Sharded(u64),
    Global,
}

fn uuid_to_routing(user_hashes: &UserHashMap, user_id: &Uuid) -> Routing {
    match user_hashes.get(user_id) {
        Some(h) => Routing::Sharded(h.raw()),
        None => Routing::Sharded(user_id.as_u128() as u64),
    }
}

fn did_to_routing(did: &str) -> Routing {
    Routing::Sharded(UserHash::from_did(did).raw())
}

fn cid_to_routing(cid: &CidLink) -> Routing {
    use siphasher::sip::SipHasher24;
    use std::hash::{Hash, Hasher};
    let mut hasher = SipHasher24::new();
    cid.as_str().hash(&mut hasher);
    Routing::Sharded(hasher.finish())
}

pub enum MetastoreRequest {
    Repo(RepoRequest),
    Record(RecordRequest),
    UserBlock(UserBlockRequest),
    Event(EventRequest),
    Commit(Box<CommitRequest>),
    Backlink(BacklinkRequest),
    Blob(BlobRequest),
    Delegation(DelegationRequest),
    Sso(SsoRequest),
    Session(SessionRequest),
    Infra(InfraRequest),
    OAuth(OAuthRequest),
    User(UserRequest),
}

impl MetastoreRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::Repo(r) => r.routing(user_hashes),
            Self::Record(r) => r.routing(user_hashes),
            Self::UserBlock(r) => r.routing(user_hashes),
            Self::Event(r) => r.routing(),
            Self::Commit(r) => r.routing(user_hashes),
            Self::Backlink(r) => r.routing(user_hashes),
            Self::Blob(r) => r.routing(user_hashes),
            Self::Delegation(r) => r.routing(),
            Self::Sso(r) => r.routing(),
            Self::Session(r) => r.routing(user_hashes),
            Self::Infra(r) => r.routing(user_hashes),
            Self::OAuth(r) => r.routing(),
            Self::User(r) => r.routing(user_hashes),
        }
    }
}

pub enum RepoRequest {
    CreateRepoFull {
        user_id: Uuid,
        did: Did,
        handle: Handle,
        repo_root_cid: CidLink,
        repo_rev: Tid,
        tx: Tx<()>,
    },
    UpdateRepoRoot {
        user_id: Uuid,
        repo_root_cid: CidLink,
        repo_rev: Tid,
        tx: Tx<()>,
    },
    UpdateRepoRev {
        user_id: Uuid,
        repo_rev: Tid,
        tx: Tx<()>,
    },
    DeleteRepo {
        user_id: Uuid,
        tx: Tx<()>,
    },
    GetRepoRootForUpdate {
        user_id: Uuid,
        tx: Tx<Option<CidLink>>,
    },
    GetRepo {
        user_id: Uuid,
        tx: Tx<Option<tranquil_db_traits::RepoInfo>>,
    },
    GetRepoRootByDid {
        did: Did,
        tx: Tx<Option<CidLink>>,
    },
    CountRepos {
        tx: Tx<i64>,
    },
    GetReposWithoutRev {
        tx: Tx<Vec<tranquil_db_traits::RepoWithoutRev>>,
    },
    GetRepoRootCidByUserId {
        user_id: Uuid,
        tx: Tx<Option<CidLink>>,
    },
    GetAccountWithRepo {
        did: Did,
        tx: Tx<Option<tranquil_db_traits::RepoAccountInfo>>,
    },
    ListReposPaginated {
        cursor_user_hash: Option<u64>,
        limit: usize,
        tx: Tx<Vec<tranquil_db_traits::RepoListItem>>,
    },
    UpdateRepoStatus {
        did: Did,
        takedown: Option<bool>,
        takedown_ref: Option<String>,
        deactivated: Option<bool>,
        tx: Tx<()>,
    },
}

impl RepoRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::CreateRepoFull { did, .. } => did_to_routing(did),
            Self::UpdateRepoRoot { user_id, .. }
            | Self::UpdateRepoRev { user_id, .. }
            | Self::DeleteRepo { user_id, .. }
            | Self::GetRepoRootForUpdate { user_id, .. }
            | Self::GetRepo { user_id, .. }
            | Self::GetRepoRootCidByUserId { user_id, .. } => uuid_to_routing(user_hashes, user_id),
            Self::GetRepoRootByDid { did, .. }
            | Self::GetAccountWithRepo { did, .. }
            | Self::UpdateRepoStatus { did, .. } => did_to_routing(did),
            Self::CountRepos { .. }
            | Self::GetReposWithoutRev { .. }
            | Self::ListReposPaginated { .. } => Routing::Global,
        }
    }
}

pub enum RecordRequest {
    UpsertRecords {
        repo_id: Uuid,
        collections: Vec<Nsid>,
        rkeys: Vec<Rkey>,
        record_cids: Vec<CidLink>,
        repo_rev: Tid,
        tx: Tx<()>,
    },
    DeleteRecords {
        repo_id: Uuid,
        collections: Vec<Nsid>,
        rkeys: Vec<Rkey>,
        tx: Tx<()>,
    },
    DeleteAllRecords {
        repo_id: Uuid,
        tx: Tx<()>,
    },
    GetRecordCid {
        repo_id: Uuid,
        collection: Nsid,
        rkey: Rkey,
        tx: Tx<Option<CidLink>>,
    },
    ListRecords {
        repo_id: Uuid,
        collection: Nsid,
        cursor: Option<Rkey>,
        limit: i64,
        reverse: bool,
        rkey_start: Option<Rkey>,
        rkey_end: Option<Rkey>,
        tx: Tx<Vec<tranquil_db_traits::RecordInfo>>,
    },
    GetAllRecords {
        repo_id: Uuid,
        tx: Tx<Vec<tranquil_db_traits::FullRecordInfo>>,
    },
    ListCollections {
        repo_id: Uuid,
        tx: Tx<Vec<Nsid>>,
    },
    CountRecords {
        repo_id: Uuid,
        tx: Tx<i64>,
    },
    CountAllRecords {
        tx: Tx<i64>,
    },
    GetRecordByCid {
        cid: CidLink,
        tx: Tx<Option<tranquil_db_traits::RecordWithTakedown>>,
    },
    ReferencedRecordCids {
        repo_id: Uuid,
        cids: Vec<CidLink>,
        excluded_keys: Vec<(Nsid, Rkey)>,
        tx: Tx<Vec<CidLink>>,
    },
    SetRecordTakedown {
        cid: CidLink,
        takedown_ref: Option<String>,
        scope_user: Option<Uuid>,
        tx: Tx<()>,
    },
}

impl RecordRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::UpsertRecords { repo_id, .. }
            | Self::DeleteRecords { repo_id, .. }
            | Self::DeleteAllRecords { repo_id, .. }
            | Self::GetRecordCid { repo_id, .. }
            | Self::ListRecords { repo_id, .. }
            | Self::GetAllRecords { repo_id, .. }
            | Self::ListCollections { repo_id, .. }
            | Self::CountRecords { repo_id, .. }
            | Self::ReferencedRecordCids { repo_id, .. } => uuid_to_routing(user_hashes, repo_id),
            Self::CountAllRecords { .. } | Self::GetRecordByCid { .. } => Routing::Global,
            Self::SetRecordTakedown {
                scope_user: Some(user_id),
                ..
            } => uuid_to_routing(user_hashes, user_id),
            Self::SetRecordTakedown { .. } => Routing::Global,
        }
    }
}

pub enum UserBlockRequest {
    InsertUserBlocks {
        user_id: Uuid,
        block_cids: Vec<Vec<u8>>,
        repo_rev: Tid,
        tx: Tx<()>,
    },
    DeleteUserBlocks {
        user_id: Uuid,
        block_cids: Vec<Vec<u8>>,
        tx: Tx<()>,
    },
    GetUserBlockCidsSinceRev {
        user_id: Uuid,
        since_rev: Option<Tid>,
        tx: Tx<Vec<Vec<u8>>>,
    },
    CountUserBlocks {
        user_id: Uuid,
        tx: Tx<i64>,
    },
}

impl UserBlockRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::InsertUserBlocks { user_id, .. }
            | Self::DeleteUserBlocks { user_id, .. }
            | Self::GetUserBlockCidsSinceRev { user_id, .. }
            | Self::CountUserBlocks { user_id, .. } => uuid_to_routing(user_hashes, user_id),
        }
    }
}

pub enum EventRequest {
    InsertCommitEvent {
        data: CommitEventData,
        tx: Tx<SequenceNumber>,
    },
    InsertIdentityEvent {
        did: Did,
        handle: Option<Handle>,
        tx: Tx<SequenceNumber>,
    },
    InsertAccountEvent {
        did: Did,
        status: AccountStatus,
        tx: Tx<SequenceNumber>,
    },
    InsertSyncEvent {
        did: Did,
        commit_cid: CidLink,
        rev: Option<Tid>,
        commit_bytes: Vec<u8>,
        tx: Tx<SequenceNumber>,
    },
    InsertGenesisCommitEvent {
        did: Did,
        commit_cid: CidLink,
        mst_root_cid: CidLink,
        rev: Tid,
        commit_bytes: Vec<u8>,
        mst_root_bytes: Vec<u8>,
        tx: Tx<SequenceNumber>,
    },
    PurgeDidEventsKeepingLatest {
        did: Did,
        tx: Tx<()>,
    },
    GetMaxSeq {
        tx: Tx<SequenceNumber>,
    },
    GetMinSeqSince {
        since: DateTime<Utc>,
        tx: Tx<Option<SequenceNumber>>,
    },
    GetEventsSinceSeq {
        since_seq: SequenceNumber,
        limit: Option<i64>,
        tx: Tx<Vec<SequencedEvent>>,
    },
    GetEventsInSeqRange {
        start_seq: SequenceNumber,
        end_seq: SequenceNumber,
        tx: Tx<Vec<SequencedEvent>>,
    },
    GetEventBySeq {
        seq: SequenceNumber,
        tx: Tx<Option<SequencedEvent>>,
    },
    GetEventsSinceCursor {
        cursor: SequenceNumber,
        limit: i64,
        tx: Tx<Vec<SequencedEvent>>,
    },
}

impl EventRequest {
    fn routing(&self) -> Routing {
        match self {
            Self::InsertCommitEvent { data, .. } => {
                Routing::Sharded(UserHash::from_did(data.did.as_str()).raw())
            }
            Self::InsertIdentityEvent { did, .. }
            | Self::InsertAccountEvent { did, .. }
            | Self::InsertSyncEvent { did, .. }
            | Self::InsertGenesisCommitEvent { did, .. }
            | Self::PurgeDidEventsKeepingLatest { did, .. } => {
                Routing::Sharded(UserHash::from_did(did.as_str()).raw())
            }
            Self::GetMaxSeq { .. }
            | Self::GetMinSeqSince { .. }
            | Self::GetEventsSinceSeq { .. }
            | Self::GetEventsInSeqRange { .. }
            | Self::GetEventBySeq { .. }
            | Self::GetEventsSinceCursor { .. } => Routing::Global,
        }
    }
}

pub enum CommitRequest {
    ApplyCommit {
        input: Box<ApplyCommitInput>,
        tx: oneshot::Sender<Result<ApplyCommitResult, ApplyCommitError>>,
    },
    ImportRepoData {
        user_id: Uuid,
        blocks: Vec<ImportBlock>,
        records: Vec<ImportRecord>,
        expected_root_cid: Option<CidLink>,
        tx: oneshot::Sender<Result<(), ImportRepoError>>,
    },
    GetUsersWithoutBlocks {
        tx: Tx<Vec<UserWithoutBlocks>>,
    },
    GetUsersNeedingRecordBlobsBackfill {
        limit: i64,
        tx: Tx<Vec<UserNeedingRecordBlobsBackfill>>,
    },
    InsertRecordBlobs {
        repo_id: Uuid,
        record_uris: Vec<AtUri>,
        blob_cids: Vec<CidLink>,
        tx: Tx<()>,
    },
}

impl CommitRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::ApplyCommit { input, .. } => did_to_routing(&input.did),
            Self::ImportRepoData { user_id, .. }
            | Self::InsertRecordBlobs {
                repo_id: user_id, ..
            } => uuid_to_routing(user_hashes, user_id),
            Self::GetUsersWithoutBlocks { .. }
            | Self::GetUsersNeedingRecordBlobsBackfill { .. } => Routing::Global,
        }
    }
}

pub enum BacklinkRequest {
    GetBacklinkConflicts {
        repo_id: Uuid,
        collection: Nsid,
        backlinks: Vec<Backlink>,
        tx: Tx<Vec<AtUri>>,
    },
    AddBacklinks {
        repo_id: Uuid,
        backlinks: Vec<Backlink>,
        tx: Tx<()>,
    },
    RemoveBacklinksByUri {
        uri: AtUri,
        tx: Tx<()>,
    },
    RemoveBacklinksByRepo {
        repo_id: Uuid,
        tx: Tx<()>,
    },
}

impl BacklinkRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::GetBacklinkConflicts { repo_id, .. }
            | Self::AddBacklinks { repo_id, .. }
            | Self::RemoveBacklinksByRepo { repo_id, .. } => uuid_to_routing(user_hashes, repo_id),
            Self::RemoveBacklinksByUri { uri, .. } => match uri.did() {
                Some(did) => did_to_routing(did),
                None => Routing::Global,
            },
        }
    }
}

pub enum BlobRequest {
    InsertBlob {
        cid: CidLink,
        mime_type: String,
        size_bytes: i64,
        created_by_user: Uuid,
        storage_key: String,
        tx: Tx<Option<CidLink>>,
    },
    GetBlobMetadata {
        cid: CidLink,
        tx: Tx<Option<tranquil_db_traits::BlobMetadata>>,
    },
    GetBlobWithTakedown {
        cid: CidLink,
        tx: Tx<Option<tranquil_db_traits::BlobWithTakedown>>,
    },
    GetBlobStorageKey {
        cid: CidLink,
        tx: Tx<Option<String>>,
    },
    ListBlobsByUser {
        user_id: Uuid,
        cursor: Option<String>,
        limit: i64,
        tx: Tx<Vec<CidLink>>,
    },
    ListBlobsSinceRev {
        did: Did,
        since: Tid,
        tx: Tx<Vec<CidLink>>,
    },
    CountBlobsByUser {
        user_id: Uuid,
        tx: Tx<i64>,
    },
    SumBlobStorage {
        tx: Tx<i64>,
    },
    UpdateBlobTakedown {
        cid: CidLink,
        takedown_ref: Option<String>,
        tx: Tx<bool>,
    },
    DeleteBlobByCid {
        cid: CidLink,
        tx: Tx<bool>,
    },
    DeleteBlobsByUser {
        user_id: Uuid,
        tx: Tx<u64>,
    },
    GetBlobStorageKeysByUser {
        user_id: Uuid,
        tx: Tx<Vec<String>>,
    },
    ListMissingBlobs {
        repo_id: Uuid,
        cursor: Option<String>,
        limit: i64,
        tx: Tx<Vec<tranquil_db_traits::MissingBlobInfo>>,
    },
    CountDistinctRecordBlobs {
        repo_id: Uuid,
        tx: Tx<i64>,
    },
    GetBlobsForExport {
        repo_id: Uuid,
        tx: Tx<Vec<tranquil_db_traits::BlobForExport>>,
    },
}

impl BlobRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::InsertBlob { cid, .. }
            | Self::UpdateBlobTakedown { cid, .. }
            | Self::DeleteBlobByCid { cid, .. } => cid_to_routing(cid),

            Self::DeleteBlobsByUser { user_id, .. } => uuid_to_routing(user_hashes, user_id),

            Self::GetBlobMetadata { .. }
            | Self::GetBlobWithTakedown { .. }
            | Self::GetBlobStorageKey { .. }
            | Self::SumBlobStorage { .. } => Routing::Global,

            Self::ListBlobsByUser { user_id, .. }
            | Self::CountBlobsByUser { user_id, .. }
            | Self::GetBlobStorageKeysByUser { user_id, .. } => {
                uuid_to_routing(user_hashes, user_id)
            }
            Self::ListMissingBlobs { repo_id, .. }
            | Self::CountDistinctRecordBlobs { repo_id, .. }
            | Self::GetBlobsForExport { repo_id, .. } => uuid_to_routing(user_hashes, repo_id),
            Self::ListBlobsSinceRev { did, .. } => did_to_routing(did),
        }
    }
}

pub enum DelegationRequest {
    IsDelegatedAccount {
        did: Did,
        tx: Tx<bool>,
    },
    CreateDelegation {
        delegated_did: Did,
        controller_did: Did,
        granted_scopes: DbScope,
        granted_by: Did,
        tx: Tx<Uuid>,
    },
    RevokeDelegation {
        delegated_did: Did,
        controller_did: Did,
        revoked_by: Did,
        tx: Tx<bool>,
    },
    UpdateDelegationScopes {
        delegated_did: Did,
        controller_did: Did,
        new_scopes: DbScope,
        tx: Tx<bool>,
    },
    GetDelegation {
        delegated_did: Did,
        controller_did: Did,
        tx: Tx<Option<tranquil_db_traits::DelegationGrant>>,
    },
    GetDelegationsForAccount {
        delegated_did: Did,
        tx: Tx<Vec<tranquil_db_traits::ControllerInfo>>,
    },
    GetAccountsControlledBy {
        controller_did: Did,
        tx: Tx<Vec<tranquil_db_traits::DelegatedAccountInfo>>,
    },
    CountActiveControllers {
        delegated_did: Did,
        tx: Tx<i64>,
    },
    ControlsAnyAccounts {
        did: Did,
        tx: Tx<bool>,
    },
    LogDelegationAction {
        delegated_did: Did,
        actor_did: Did,
        controller_did: Option<Did>,
        action_type: DelegationActionType,
        action_details: Option<serde_json::Value>,
        ip_address: Option<String>,
        user_agent: Option<String>,
        tx: Tx<Uuid>,
    },
    GetAuditLogForAccount {
        delegated_did: Did,
        limit: i64,
        offset: i64,
        tx: Tx<Vec<tranquil_db_traits::AuditLogEntry>>,
    },
    CountAuditLogEntries {
        delegated_did: Did,
        tx: Tx<i64>,
    },
}

impl DelegationRequest {
    fn routing(&self) -> Routing {
        match self {
            Self::IsDelegatedAccount { did, .. }
            | Self::GetDelegationsForAccount {
                delegated_did: did, ..
            }
            | Self::CountActiveControllers {
                delegated_did: did, ..
            }
            | Self::GetAuditLogForAccount {
                delegated_did: did, ..
            }
            | Self::CountAuditLogEntries {
                delegated_did: did, ..
            } => did_to_routing(did),
            Self::CreateDelegation { delegated_did, .. }
            | Self::RevokeDelegation { delegated_did, .. }
            | Self::UpdateDelegationScopes { delegated_did, .. }
            | Self::GetDelegation { delegated_did, .. }
            | Self::LogDelegationAction { delegated_did, .. } => did_to_routing(delegated_did),
            Self::GetAccountsControlledBy { controller_did, .. }
            | Self::ControlsAnyAccounts {
                did: controller_did,
                ..
            } => did_to_routing(controller_did),
        }
    }
}

pub enum SsoRequest {
    CreateExternalIdentity {
        did: Did,
        provider: tranquil_db_traits::SsoProviderType,
        provider_user_id: String,
        provider_username: Option<String>,
        provider_email: Option<String>,
        tx: Tx<Uuid>,
    },
    GetExternalIdentityByProvider {
        provider: tranquil_db_traits::SsoProviderType,
        provider_user_id: String,
        tx: Tx<Option<tranquil_db_traits::ExternalIdentity>>,
    },
    GetExternalIdentitiesByDid {
        did: Did,
        tx: Tx<Vec<tranquil_db_traits::ExternalIdentity>>,
    },
    UpdateExternalIdentityLogin {
        id: Uuid,
        provider_username: Option<String>,
        provider_email: Option<String>,
        tx: Tx<()>,
    },
    DeleteExternalIdentity {
        id: Uuid,
        did: Did,
        tx: Tx<bool>,
    },
    CreateSsoAuthState {
        state: String,
        request_uri: String,
        provider: tranquil_db_traits::SsoProviderType,
        action: tranquil_db_traits::SsoAction,
        nonce: Option<String>,
        code_verifier: Option<String>,
        did: Option<Did>,
        tx: Tx<()>,
    },
    ConsumeSsoAuthState {
        state: String,
        tx: Tx<Option<tranquil_db_traits::SsoAuthState>>,
    },
    CleanupExpiredSsoAuthStates {
        tx: Tx<u64>,
    },
    CreatePendingRegistration {
        token: String,
        request_uri: String,
        provider: tranquil_db_traits::SsoProviderType,
        provider_user_id: String,
        provider_username: Option<String>,
        provider_email: Option<String>,
        provider_email_verified: bool,
        tx: Tx<()>,
    },
    GetPendingRegistration {
        token: String,
        tx: Tx<Option<tranquil_db_traits::SsoPendingRegistration>>,
    },
    ConsumePendingRegistration {
        token: String,
        tx: Tx<Option<tranquil_db_traits::SsoPendingRegistration>>,
    },
    CleanupExpiredPendingRegistrations {
        tx: Tx<u64>,
    },
}

impl SsoRequest {
    fn routing(&self) -> Routing {
        match self {
            Self::CreateExternalIdentity { did, .. }
            | Self::GetExternalIdentitiesByDid { did, .. }
            | Self::DeleteExternalIdentity { did, .. } => did_to_routing(did),
            Self::GetExternalIdentityByProvider { .. }
            | Self::UpdateExternalIdentityLogin { .. }
            | Self::ConsumeSsoAuthState { .. }
            | Self::CreateSsoAuthState { .. }
            | Self::CleanupExpiredSsoAuthStates { .. }
            | Self::CreatePendingRegistration { .. }
            | Self::GetPendingRegistration { .. }
            | Self::ConsumePendingRegistration { .. }
            | Self::CleanupExpiredPendingRegistrations { .. } => Routing::Global,
        }
    }
}

pub enum SessionRequest {
    CreateSession {
        data: tranquil_db_traits::SessionTokenCreate,
        tx: Tx<SessionId>,
    },
    GetSessionByAccessJti {
        access_jti: String,
        tx: Tx<Option<tranquil_db_traits::SessionToken>>,
    },
    GetSessionForRefresh {
        refresh_jti: String,
        tx: Tx<Option<tranquil_db_traits::SessionForRefresh>>,
    },
    DeleteSessionByAccessJti {
        access_jti: String,
        did: Did,
        tx: Tx<u64>,
    },
    DeleteSessionById {
        session_id: SessionId,
        did: Did,
        tx: Tx<u64>,
    },
    DeleteSessionsByDid {
        did: Did,
        tx: Tx<u64>,
    },
    DeleteSessionsByDidExceptJti {
        did: Did,
        except_jti: String,
        tx: Tx<u64>,
    },
    ListSessionsByDid {
        did: Did,
        tx: Tx<Vec<tranquil_db_traits::SessionListItem>>,
    },
    GetSessionAccessJtiById {
        session_id: SessionId,
        did: Did,
        tx: Tx<Option<String>>,
    },
    DeleteSessionsByAppPassword {
        did: Did,
        app_password_name: String,
        tx: Tx<u64>,
    },
    GetSessionJtisByAppPassword {
        did: Did,
        app_password_name: String,
        tx: Tx<Vec<String>>,
    },
    LookupRefreshGrace {
        refresh_jti: String,
        tx: Tx<tranquil_db_traits::RefreshGraceLookup>,
    },
    ListAppPasswords {
        user_id: Uuid,
        tx: Tx<Vec<tranquil_db_traits::AppPasswordRecord>>,
    },
    GetAppPasswordsForLogin {
        user_id: Uuid,
        tx: Tx<Vec<tranquil_db_traits::AppPasswordRecord>>,
    },
    GetAppPasswordByName {
        user_id: Uuid,
        name: String,
        tx: Tx<Option<tranquil_db_traits::AppPasswordRecord>>,
    },
    CreateAppPassword {
        data: tranquil_db_traits::AppPasswordCreate,
        tx: Tx<Uuid>,
    },
    DeleteAppPassword {
        user_id: Uuid,
        name: String,
        tx: Tx<u64>,
    },
    DeleteAppPasswordsByController {
        did: Did,
        controller_did: Did,
        tx: Tx<u64>,
    },
    GetLastReauthAt {
        did: Did,
        tx: Tx<Option<DateTime<Utc>>>,
    },
    UpdateLastReauth {
        did: Did,
        tx: Tx<DateTime<Utc>>,
    },
    GetSessionMfaStatus {
        did: Did,
        tx: Tx<Option<tranquil_db_traits::SessionMfaStatus>>,
    },
    UpdateMfaVerified {
        did: Did,
        tx: Tx<()>,
    },
    GetAppPasswordHashesByDid {
        did: Did,
        tx: Tx<Vec<String>>,
    },
    RefreshSessionAtomic {
        data: tranquil_db_traits::SessionRefreshData,
        tx: Tx<RefreshSessionResult>,
    },
}

impl SessionRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::CreateSession { .. }
            | Self::GetSessionByAccessJti { .. }
            | Self::GetSessionForRefresh { .. }
            | Self::LookupRefreshGrace { .. } => Routing::Global,
            Self::DeleteSessionByAccessJti { did, .. }
            | Self::DeleteSessionById { did, .. }
            | Self::DeleteSessionsByDid { did, .. }
            | Self::DeleteSessionsByDidExceptJti { did, .. }
            | Self::ListSessionsByDid { did, .. }
            | Self::GetSessionAccessJtiById { did, .. }
            | Self::DeleteSessionsByAppPassword { did, .. }
            | Self::GetSessionJtisByAppPassword { did, .. }
            | Self::DeleteAppPasswordsByController { did, .. }
            | Self::GetLastReauthAt { did, .. }
            | Self::UpdateLastReauth { did, .. }
            | Self::GetSessionMfaStatus { did, .. }
            | Self::UpdateMfaVerified { did, .. }
            | Self::GetAppPasswordHashesByDid { did, .. } => did_to_routing(did),
            Self::RefreshSessionAtomic { data, .. } => did_to_routing(data.did.as_str()),
            Self::ListAppPasswords { user_id, .. }
            | Self::GetAppPasswordsForLogin { user_id, .. }
            | Self::GetAppPasswordByName { user_id, .. }
            | Self::CreateAppPassword {
                data: tranquil_db_traits::AppPasswordCreate { user_id, .. },
                ..
            }
            | Self::DeleteAppPassword { user_id, .. } => uuid_to_routing(user_hashes, user_id),
        }
    }
}

pub enum UserRequest {
    GetByDid {
        did: Did,
        tx: Tx<Option<UserRow>>,
    },
    GetByHandle {
        handle: Handle,
        tx: Tx<Option<UserRow>>,
    },
    GetWithKeyByDid {
        did: Did,
        tx: Tx<Option<UserWithKey>>,
    },
    GetStatusByDid {
        did: Did,
        tx: Tx<Option<UserStatus>>,
    },
    CountUsers {
        tx: Tx<i64>,
    },
    GetSessionAccessExpiry {
        did: Did,
        access_jti: String,
        tx: Tx<Option<DateTime<Utc>>>,
    },
    GetOAuthTokenWithUser {
        token_id: String,
        tx: Tx<Option<OAuthTokenWithUser>>,
    },
    GetUserInfoByDid {
        did: Did,
        tx: Tx<Option<UserInfoForAuth>>,
    },
    GetAnyAdminUserId {
        tx: Tx<Option<Uuid>>,
    },
    SetInvitesDisabled {
        did: Did,
        disabled: bool,
        tx: Tx<bool>,
    },
    SearchAccounts {
        cursor_did: Option<Did>,
        email_filter: Option<String>,
        handle_filter: Option<String>,
        limit: i64,
        tx: Tx<Vec<AccountSearchResult>>,
    },
    GetAuthInfoByDid {
        did: Did,
        tx: Tx<Option<UserAuthInfo>>,
    },
    GetByEmail {
        email: String,
        tx: Tx<Option<UserForVerification>>,
    },
    GetLoginCheckByIdentifier {
        identifier: String,
        tx: Tx<Option<UserLoginCheck>>,
    },
    GetLoginInfoByIdentifier {
        identifier: String,
        tx: Tx<Option<UserLoginInfo>>,
    },
    Get2faStatusByDid {
        did: Did,
        tx: Tx<Option<User2faStatus>>,
    },
    GetCommsPrefs {
        user_id: Uuid,
        tx: Tx<Option<UserCommsPrefs>>,
    },
    GetIdByDid {
        did: Did,
        tx: Tx<Option<Uuid>>,
    },
    GetUserKeyById {
        user_id: Uuid,
        tx: Tx<Option<UserKeyInfo>>,
    },
    GetIdAndHandleByDid {
        did: Did,
        tx: Tx<Option<UserIdAndHandle>>,
    },
    GetDidWebInfoByHandle {
        handle: Handle,
        tx: Tx<Option<UserDidWebInfo>>,
    },
    GetDidWebOverrides {
        user_id: Uuid,
        tx: Tx<Option<DidWebOverrides>>,
    },
    GetHandleByDid {
        did: Did,
        tx: Tx<Option<Handle>>,
    },
    IsAccountActiveByDid {
        did: Did,
        tx: Tx<Option<bool>>,
    },
    GetUserForDeletion {
        did: Did,
        tx: Tx<Option<UserForDeletion>>,
    },
    CheckHandleExists {
        handle: Handle,
        exclude_user_id: Uuid,
        tx: Tx<bool>,
    },
    UpdateHandle {
        user_id: Uuid,
        handle: Handle,
        tx: Tx<()>,
    },
    GetUserWithKeyByDid {
        did: Did,
        tx: Tx<Option<UserKeyWithId>>,
    },
    IsAccountMigrated {
        did: Did,
        tx: Tx<bool>,
    },
    HasVerifiedCommsChannel {
        did: Did,
        tx: Tx<bool>,
    },
    GetIdByHandle {
        handle: Handle,
        tx: Tx<Option<Uuid>>,
    },
    GetEmailInfoByDid {
        did: Did,
        tx: Tx<Option<UserEmailInfo>>,
    },
    CheckEmailExists {
        email: String,
        exclude_user_id: Uuid,
        tx: Tx<bool>,
    },
    UpdateEmail {
        user_id: Uuid,
        email: String,
        tx: Tx<()>,
    },
    SetEmailVerified {
        user_id: Uuid,
        verified: bool,
        tx: Tx<()>,
    },
    CheckEmailVerifiedByIdentifier {
        identifier: String,
        tx: Tx<Option<bool>>,
    },
    CheckChannelVerifiedByDid {
        did: Did,
        channel: CommsChannel,
        tx: Tx<Option<bool>>,
    },
    AdminUpdateEmail {
        did: Did,
        email: String,
        tx: Tx<u64>,
    },
    AdminUpdateHandle {
        did: Did,
        handle: Handle,
        tx: Tx<u64>,
    },
    AdminUpdatePassword {
        did: Did,
        password_hash: String,
        tx: Tx<u64>,
    },
    SetAdminStatus {
        did: Did,
        is_admin: bool,
        tx: Tx<()>,
    },
    GetNotificationPrefs {
        did: Did,
        tx: Tx<Option<NotificationPrefs>>,
    },
    GetIdHandleEmailByDid {
        did: Did,
        tx: Tx<Option<UserIdHandleEmail>>,
    },
    UpdatePreferredCommsChannel {
        did: Did,
        channel: CommsChannel,
        tx: Tx<()>,
    },
    ClearDiscord {
        user_id: Uuid,
        tx: Tx<()>,
    },
    ClearTelegram {
        user_id: Uuid,
        tx: Tx<()>,
    },
    ClearSignal {
        user_id: Uuid,
        tx: Tx<()>,
    },
    SetUnverifiedSignal {
        user_id: Uuid,
        signal_username: String,
        tx: Tx<()>,
    },
    SetUnverifiedTelegram {
        user_id: Uuid,
        telegram_username: String,
        tx: Tx<()>,
    },
    StoreTelegramChatId {
        telegram_username: String,
        chat_id: i64,
        handle: Option<String>,
        tx: Tx<Option<Uuid>>,
    },
    GetTelegramChatId {
        user_id: Uuid,
        tx: Tx<Option<i64>>,
    },
    SetUnverifiedDiscord {
        user_id: Uuid,
        discord_username: String,
        tx: Tx<()>,
    },
    StoreDiscordUserId {
        discord_username: String,
        discord_id: String,
        handle: Option<String>,
        tx: Tx<Option<Uuid>>,
    },
    GetVerificationInfo {
        did: Did,
        tx: Tx<Option<UserVerificationInfo>>,
    },
    VerifyEmailChannel {
        user_id: Uuid,
        email: String,
        tx: Tx<bool>,
    },
    VerifyDiscordChannel {
        user_id: Uuid,
        discord_id: String,
        tx: Tx<()>,
    },
    VerifyTelegramChannel {
        user_id: Uuid,
        telegram_username: String,
        tx: Tx<()>,
    },
    VerifySignalChannel {
        user_id: Uuid,
        signal_username: String,
        tx: Tx<()>,
    },
    SetEmailVerifiedFlag {
        user_id: Uuid,
        tx: Tx<()>,
    },
    SetDiscordVerifiedFlag {
        user_id: Uuid,
        tx: Tx<()>,
    },
    SetTelegramVerifiedFlag {
        user_id: Uuid,
        tx: Tx<()>,
    },
    SetSignalVerifiedFlag {
        user_id: Uuid,
        tx: Tx<()>,
    },
    HasTotpEnabled {
        did: Did,
        tx: Tx<bool>,
    },
    HasPasskeys {
        did: Did,
        tx: Tx<bool>,
    },
    GetPasswordHashByDid {
        did: Did,
        tx: Tx<Option<String>>,
    },
    GetPasskeysForUser {
        did: Did,
        tx: Tx<Vec<StoredPasskey>>,
    },
    GetPasskeyByCredentialId {
        credential_id: Vec<u8>,
        tx: Tx<Option<StoredPasskey>>,
    },
    SavePasskey {
        did: Did,
        credential_id: Vec<u8>,
        public_key: Vec<u8>,
        friendly_name: Option<String>,
        tx: Tx<Uuid>,
    },
    UpdatePasskeyCounter {
        credential_id: Vec<u8>,
        new_counter: i32,
        tx: Tx<bool>,
    },
    DeletePasskey {
        id: Uuid,
        did: Did,
        tx: Tx<bool>,
    },
    UpdatePasskeyName {
        id: Uuid,
        did: Did,
        name: String,
        tx: Tx<bool>,
    },
    SaveWebauthnChallenge {
        did: Did,
        challenge_type: WebauthnChallengeType,
        state_json: String,
        tx: Tx<Uuid>,
    },
    LoadWebauthnChallenge {
        did: Did,
        challenge_type: WebauthnChallengeType,
        tx: Tx<Option<String>>,
    },
    DeleteWebauthnChallenge {
        did: Did,
        challenge_type: WebauthnChallengeType,
        tx: Tx<()>,
    },
    SaveDiscoverableChallenge {
        request_key: String,
        state_json: String,
        tx: Tx<Uuid>,
    },
    LoadDiscoverableChallenge {
        request_key: String,
        tx: Tx<Option<String>>,
    },
    DeleteDiscoverableChallenge {
        request_key: String,
        tx: Tx<()>,
    },
    GetTotpRecord {
        did: Did,
        tx: Tx<Option<TotpRecord>>,
    },
    GetTotpRecordState {
        did: Did,
        tx: Tx<Option<TotpRecordState>>,
    },
    UpsertTotpSecret {
        did: Did,
        secret_encrypted: Vec<u8>,
        encryption_version: i32,
        tx: Tx<()>,
    },
    SetTotpVerified {
        did: Did,
        tx: Tx<()>,
    },
    UpdateTotpLastUsed {
        did: Did,
        tx: Tx<()>,
    },
    DeleteTotp {
        did: Did,
        tx: Tx<()>,
    },
    GetUnusedBackupCodes {
        did: Did,
        tx: Tx<Vec<StoredBackupCode>>,
    },
    MarkBackupCodeUsed {
        code_id: Uuid,
        tx: Tx<bool>,
    },
    CountUnusedBackupCodes {
        did: Did,
        tx: Tx<i64>,
    },
    DeleteBackupCodes {
        did: Did,
        tx: Tx<u64>,
    },
    InsertBackupCodes {
        did: Did,
        code_hashes: Vec<String>,
        tx: Tx<()>,
    },
    EnableTotpWithBackupCodes {
        did: Did,
        code_hashes: Vec<String>,
        tx: Tx<()>,
    },
    DeleteTotpAndBackupCodes {
        did: Did,
        tx: Tx<()>,
    },
    ReplaceBackupCodes {
        did: Did,
        code_hashes: Vec<String>,
        tx: Tx<()>,
    },
    GetSessionInfoByDid {
        did: Did,
        tx: Tx<Option<UserSessionInfo>>,
    },
    GetLegacyLoginPref {
        did: Did,
        tx: Tx<Option<UserLegacyLoginPref>>,
    },
    UpdateLegacyLogin {
        did: Did,
        allow: bool,
        tx: Tx<bool>,
    },
    UpdateLocale {
        did: Did,
        locale: String,
        tx: Tx<bool>,
    },
    GetLoginFullByIdentifier {
        identifier: String,
        tx: Tx<Option<UserLoginFull>>,
    },
    GetConfirmSignupByDid {
        did: Did,
        tx: Tx<Option<UserConfirmSignup>>,
    },
    GetResendVerificationByDid {
        did: Did,
        tx: Tx<Option<UserResendVerification>>,
    },
    SetChannelVerified {
        did: Did,
        channel: CommsChannel,
        tx: Tx<()>,
    },
    GetIdByEmailOrHandle {
        email: String,
        handle: String,
        tx: Tx<Option<Uuid>>,
    },
    CountAccountsByEmail {
        email: String,
        tx: Tx<i64>,
    },
    GetHandlesByEmail {
        email: String,
        tx: Tx<Vec<Handle>>,
    },
    SetPasswordResetCode {
        user_id: Uuid,
        code: String,
        expires_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    GetUserByResetCode {
        code: String,
        tx: Tx<Option<UserResetCodeInfo>>,
    },
    ClearPasswordResetCode {
        user_id: Uuid,
        tx: Tx<()>,
    },
    GetIdAndPasswordHashByDid {
        did: Did,
        tx: Tx<Option<UserIdAndPasswordHash>>,
    },
    UpdatePasswordHash {
        user_id: Uuid,
        password_hash: String,
        tx: Tx<()>,
    },
    ResetPasswordWithSessions {
        user_id: Uuid,
        password_hash: String,
        tx: Tx<PasswordResetResult>,
    },
    ActivateAccount {
        did: Did,
        tx: Tx<bool>,
    },
    DeactivateAccount {
        did: Did,
        delete_after: Option<DateTime<Utc>>,
        tx: Tx<bool>,
    },
    HasPasswordByDid {
        did: Did,
        tx: Tx<Option<bool>>,
    },
    GetPasswordInfoByDid {
        did: Did,
        tx: Tx<Option<UserPasswordInfo>>,
    },
    RemoveUserPassword {
        user_id: Uuid,
        tx: Tx<()>,
    },
    SetNewUserPassword {
        user_id: Uuid,
        password_hash: String,
        tx: Tx<()>,
    },
    GetUserKeyByDid {
        did: Did,
        tx: Tx<Option<UserKeyInfo>>,
    },
    DeleteAccountComplete {
        user_id: Uuid,
        did: Did,
        tx: Tx<()>,
    },
    SetUserTakedown {
        did: Did,
        takedown_ref: Option<String>,
        tx: Tx<bool>,
    },
    AdminDeleteAccountComplete {
        user_id: Uuid,
        did: Did,
        tx: Tx<()>,
    },
    GetUserForDidDoc {
        did: Did,
        tx: Tx<Option<UserForDidDoc>>,
    },
    GetUserForDidDocBuild {
        did: Did,
        tx: Tx<Option<UserForDidDocBuild>>,
    },
    UpsertDidWebOverrides {
        user_id: Uuid,
        verification_methods: Option<serde_json::Value>,
        also_known_as: Option<Vec<String>>,
        tx: Tx<()>,
    },
    UpdateMigratedToPds {
        did: Did,
        endpoint: String,
        tx: Tx<()>,
    },
    GetUserForPasskeySetup {
        did: Did,
        tx: Tx<Option<UserForPasskeySetup>>,
    },
    GetUserForPasskeyRecovery {
        identifier: String,
        normalized_handle: String,
        tx: Tx<Option<UserForPasskeyRecovery>>,
    },
    SetRecoveryToken {
        did: Did,
        token_hash: String,
        expires_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    GetUserForRecovery {
        did: Did,
        tx: Tx<Option<UserForRecovery>>,
    },
    GetAccountsScheduledForDeletion {
        limit: i64,
        tx: Tx<Vec<ScheduledDeletionAccount>>,
    },
    DeleteAccountWithFirehose {
        user_id: Uuid,
        did: Did,
        tx: Tx<()>,
    },
    CreatePasswordAccount {
        input: CreatePasswordAccountInput,
        tx: oneshot::Sender<Result<CreatePasswordAccountResult, CreateAccountError>>,
    },
    CreateDelegatedAccount {
        input: CreateDelegatedAccountInput,
        tx: oneshot::Sender<Result<Uuid, CreateAccountError>>,
    },
    CreatePasskeyAccount {
        input: CreatePasskeyAccountInput,
        tx: oneshot::Sender<Result<CreatePasswordAccountResult, CreateAccountError>>,
    },
    CreateSsoAccount {
        input: CreateSsoAccountInput,
        tx: oneshot::Sender<Result<CreatePasswordAccountResult, CreateAccountError>>,
    },
    ReactivateMigrationAccount {
        input: MigrationReactivationInput,
        tx: oneshot::Sender<Result<ReactivatedAccountInfo, MigrationReactivationError>>,
    },
    CheckHandleAvailableForNewAccount {
        handle: Handle,
        tx: Tx<bool>,
    },
    ReserveHandle {
        handle: Handle,
        reserved_by: String,
        tx: Tx<bool>,
    },
    ReleaseHandleReservation {
        handle: Handle,
        tx: Tx<()>,
    },
    CleanupExpiredHandleReservations {
        tx: Tx<u64>,
    },
    CompletePasskeySetup {
        input: CompletePasskeySetupInput,
        tx: Tx<()>,
    },
    RecoverPasskeyAccount {
        input: RecoverPasskeyAccountInput,
        tx: Tx<RecoverPasskeyAccountResult>,
    },
    GetPasswordResetInfo {
        email: String,
        tx: Tx<Option<tranquil_db_traits::PasswordResetInfo>>,
    },
    EnableTotpVerified {
        did: Did,
        encrypted_secret: Vec<u8>,
        tx: Tx<()>,
    },
    SetTwoFactorEnabled {
        did: Did,
        enabled: bool,
        tx: Tx<()>,
    },
    ExpirePasswordResetCode {
        email: String,
        tx: Tx<()>,
    },
}

impl UserRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::GetByDid { did, .. }
            | Self::GetWithKeyByDid { did, .. }
            | Self::GetStatusByDid { did, .. }
            | Self::GetSessionAccessExpiry { did, .. }
            | Self::GetUserInfoByDid { did, .. }
            | Self::SetInvitesDisabled { did, .. }
            | Self::GetAuthInfoByDid { did, .. }
            | Self::Get2faStatusByDid { did, .. }
            | Self::GetIdByDid { did, .. }
            | Self::GetIdAndHandleByDid { did, .. }
            | Self::GetHandleByDid { did, .. }
            | Self::IsAccountActiveByDid { did, .. }
            | Self::GetUserForDeletion { did, .. }
            | Self::GetUserWithKeyByDid { did, .. }
            | Self::IsAccountMigrated { did, .. }
            | Self::HasVerifiedCommsChannel { did, .. }
            | Self::GetEmailInfoByDid { did, .. }
            | Self::CheckChannelVerifiedByDid { did, .. }
            | Self::AdminUpdateEmail { did, .. }
            | Self::AdminUpdateHandle { did, .. }
            | Self::AdminUpdatePassword { did, .. }
            | Self::SetAdminStatus { did, .. }
            | Self::GetNotificationPrefs { did, .. }
            | Self::GetIdHandleEmailByDid { did, .. }
            | Self::UpdatePreferredCommsChannel { did, .. }
            | Self::GetVerificationInfo { did, .. }
            | Self::HasTotpEnabled { did, .. }
            | Self::HasPasskeys { did, .. }
            | Self::GetPasswordHashByDid { did, .. }
            | Self::GetPasskeysForUser { did, .. }
            | Self::SavePasskey { did, .. }
            | Self::DeletePasskey { did, .. }
            | Self::UpdatePasskeyName { did, .. }
            | Self::SaveWebauthnChallenge { did, .. }
            | Self::LoadWebauthnChallenge { did, .. }
            | Self::DeleteWebauthnChallenge { did, .. }
            | Self::GetTotpRecord { did, .. }
            | Self::GetTotpRecordState { did, .. }
            | Self::UpsertTotpSecret { did, .. }
            | Self::SetTotpVerified { did, .. }
            | Self::UpdateTotpLastUsed { did, .. }
            | Self::DeleteTotp { did, .. }
            | Self::GetUnusedBackupCodes { did, .. }
            | Self::CountUnusedBackupCodes { did, .. }
            | Self::DeleteBackupCodes { did, .. }
            | Self::InsertBackupCodes { did, .. }
            | Self::EnableTotpWithBackupCodes { did, .. }
            | Self::DeleteTotpAndBackupCodes { did, .. }
            | Self::ReplaceBackupCodes { did, .. }
            | Self::GetSessionInfoByDid { did, .. }
            | Self::GetLegacyLoginPref { did, .. }
            | Self::UpdateLegacyLogin { did, .. }
            | Self::UpdateLocale { did, .. }
            | Self::GetConfirmSignupByDid { did, .. }
            | Self::GetResendVerificationByDid { did, .. }
            | Self::SetChannelVerified { did, .. }
            | Self::GetIdAndPasswordHashByDid { did, .. }
            | Self::ActivateAccount { did, .. }
            | Self::DeactivateAccount { did, .. }
            | Self::HasPasswordByDid { did, .. }
            | Self::GetPasswordInfoByDid { did, .. }
            | Self::GetUserKeyByDid { did, .. }
            | Self::DeleteAccountComplete { did, .. }
            | Self::SetUserTakedown { did, .. }
            | Self::AdminDeleteAccountComplete { did, .. }
            | Self::GetUserForDidDoc { did, .. }
            | Self::GetUserForDidDocBuild { did, .. }
            | Self::UpdateMigratedToPds { did, .. }
            | Self::GetUserForPasskeySetup { did, .. }
            | Self::GetUserForRecovery { did, .. }
            | Self::DeleteAccountWithFirehose { did, .. }
            | Self::CreatePasswordAccount {
                input: CreatePasswordAccountInput { did, .. },
                ..
            }
            | Self::CreateDelegatedAccount {
                input: CreateDelegatedAccountInput { did, .. },
                ..
            }
            | Self::CreatePasskeyAccount {
                input: CreatePasskeyAccountInput { did, .. },
                ..
            }
            | Self::CreateSsoAccount {
                input: CreateSsoAccountInput { did, .. },
                ..
            }
            | Self::ReactivateMigrationAccount {
                input: MigrationReactivationInput { did, .. },
                ..
            }
            | Self::CompletePasskeySetup {
                input: CompletePasskeySetupInput { did, .. },
                ..
            }
            | Self::RecoverPasskeyAccount {
                input: RecoverPasskeyAccountInput { did, .. },
                ..
            }
            | Self::SetRecoveryToken { did, .. }
            | Self::EnableTotpVerified { did, .. }
            | Self::SetTwoFactorEnabled { did, .. } => did_to_routing(did),

            Self::GetCommsPrefs { user_id, .. }
            | Self::GetUserKeyById { user_id, .. }
            | Self::GetDidWebOverrides { user_id, .. }
            | Self::UpdateHandle { user_id, .. }
            | Self::UpdateEmail { user_id, .. }
            | Self::SetEmailVerified { user_id, .. }
            | Self::ClearDiscord { user_id, .. }
            | Self::ClearTelegram { user_id, .. }
            | Self::ClearSignal { user_id, .. }
            | Self::SetUnverifiedSignal { user_id, .. }
            | Self::SetUnverifiedTelegram { user_id, .. }
            | Self::GetTelegramChatId { user_id, .. }
            | Self::SetUnverifiedDiscord { user_id, .. }
            | Self::VerifyEmailChannel { user_id, .. }
            | Self::VerifyDiscordChannel { user_id, .. }
            | Self::VerifyTelegramChannel { user_id, .. }
            | Self::VerifySignalChannel { user_id, .. }
            | Self::SetEmailVerifiedFlag { user_id, .. }
            | Self::SetDiscordVerifiedFlag { user_id, .. }
            | Self::SetTelegramVerifiedFlag { user_id, .. }
            | Self::SetSignalVerifiedFlag { user_id, .. }
            | Self::SetPasswordResetCode { user_id, .. }
            | Self::ClearPasswordResetCode { user_id, .. }
            | Self::UpdatePasswordHash { user_id, .. }
            | Self::ResetPasswordWithSessions { user_id, .. }
            | Self::RemoveUserPassword { user_id, .. }
            | Self::SetNewUserPassword { user_id, .. }
            | Self::UpsertDidWebOverrides { user_id, .. } => uuid_to_routing(user_hashes, user_id),

            Self::CheckHandleExists {
                exclude_user_id, ..
            }
            | Self::CheckEmailExists {
                exclude_user_id, ..
            } => uuid_to_routing(user_hashes, exclude_user_id),

            Self::MarkBackupCodeUsed { .. } => Routing::Global,

            Self::GetByHandle { .. }
            | Self::GetDidWebInfoByHandle { .. }
            | Self::GetIdByHandle { .. }
            | Self::CheckHandleAvailableForNewAccount { .. }
            | Self::ReserveHandle { .. }
            | Self::ReleaseHandleReservation { .. } => Routing::Global,

            Self::CountUsers { .. }
            | Self::GetOAuthTokenWithUser { .. }
            | Self::GetAnyAdminUserId { .. }
            | Self::SearchAccounts { .. }
            | Self::GetByEmail { .. }
            | Self::GetLoginCheckByIdentifier { .. }
            | Self::GetLoginInfoByIdentifier { .. }
            | Self::CheckEmailVerifiedByIdentifier { .. }
            | Self::StoreTelegramChatId { .. }
            | Self::StoreDiscordUserId { .. }
            | Self::GetPasskeyByCredentialId { .. }
            | Self::UpdatePasskeyCounter { .. }
            | Self::GetLoginFullByIdentifier { .. }
            | Self::GetIdByEmailOrHandle { .. }
            | Self::CountAccountsByEmail { .. }
            | Self::GetHandlesByEmail { .. }
            | Self::GetUserByResetCode { .. }
            | Self::GetUserForPasskeyRecovery { .. }
            | Self::GetAccountsScheduledForDeletion { .. }
            | Self::CleanupExpiredHandleReservations { .. }
            | Self::GetPasswordResetInfo { .. }
            | Self::ExpirePasswordResetCode { .. }
            | Self::SaveDiscoverableChallenge { .. }
            | Self::LoadDiscoverableChallenge { .. }
            | Self::DeleteDiscoverableChallenge { .. } => Routing::Global,
        }
    }
}

pub enum InfraRequest {
    EnqueueComms {
        user_id: Option<Uuid>,
        channel: CommsChannel,
        comms_type: CommsType,
        recipient: String,
        subject: Option<String>,
        body: String,
        metadata: Option<serde_json::Value>,
        tx: Tx<Uuid>,
    },
    FetchPendingComms {
        now: DateTime<Utc>,
        batch_size: i64,
        tx: Tx<Vec<QueuedComms>>,
    },
    MarkCommsSent {
        id: Uuid,
        tx: Tx<()>,
    },
    MarkCommsFailed {
        id: Uuid,
        error: String,
        tx: Tx<()>,
    },
    MarkCommsFailedPermanent {
        id: Uuid,
        error: String,
        tx: Tx<()>,
    },
    CreateInviteCode {
        code: InviteCode,
        use_count: i32,
        for_account: Did,
        tx: Tx<bool>,
    },
    CreateInviteCodesBatch {
        codes: Vec<InviteCode>,
        use_count: i32,
        created_by_user: Uuid,
        for_account: Did,
        tx: Tx<()>,
    },
    GetInviteCodeAvailableUses {
        code: InviteCode,
        tx: Tx<Option<i32>>,
    },
    ValidateInviteCode {
        code: InviteCode,
        tx: oneshot::Sender<Result<(), InviteCodeError>>,
    },
    GetInviteCodesForAccount {
        for_account: Did,
        tx: Tx<Vec<InviteCodeInfo>>,
    },
    GetInviteCodeUses {
        code: String,
        tx: Tx<Vec<InviteCodeUse>>,
    },
    DisableInviteCodesByCode {
        codes: Vec<String>,
        tx: Tx<()>,
    },
    DisableInviteCodesByAccount {
        accounts: Vec<Did>,
        tx: Tx<()>,
    },
    ListInviteCodes {
        cursor: Option<String>,
        limit: i64,
        sort: InviteCodeSortOrder,
        tx: Tx<Vec<InviteCodeRow>>,
    },
    GetUserDidsByIds {
        user_ids: Vec<Uuid>,
        tx: Tx<Vec<(Uuid, Did)>>,
    },
    GetInviteCodeUsesBatch {
        codes: Vec<String>,
        tx: Tx<Vec<InviteCodeUse>>,
    },
    GetInvitesCreatedByUser {
        user_id: Uuid,
        tx: Tx<Vec<InviteCodeInfo>>,
    },
    GetInviteCodeInfo {
        code: String,
        tx: Tx<Option<InviteCodeInfo>>,
    },
    GetInviteCodesByUsers {
        user_ids: Vec<Uuid>,
        tx: Tx<Vec<(Uuid, InviteCodeInfo)>>,
    },
    GetInviteCodeUsedByUser {
        user_id: Uuid,
        tx: Tx<Option<String>>,
    },
    DeleteInviteCodeUsesByUser {
        user_id: Uuid,
        tx: Tx<()>,
    },
    DeleteInviteCodesByUser {
        user_id: Uuid,
        tx: Tx<()>,
    },
    ReserveSigningKey {
        did: Option<Did>,
        public_key_did_key: String,
        private_key_bytes: Vec<u8>,
        expires_at: DateTime<Utc>,
        tx: Tx<Uuid>,
    },
    GetReservedSigningKey {
        public_key_did_key: String,
        tx: Tx<Option<ReservedSigningKey>>,
    },
    MarkSigningKeyUsed {
        key_id: Uuid,
        tx: Tx<()>,
    },
    CreateDeletionRequest {
        token: String,
        did: Did,
        expires_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    GetDeletionRequest {
        token: String,
        tx: Tx<Option<DeletionRequest>>,
    },
    DeleteDeletionRequest {
        token: String,
        tx: Tx<()>,
    },
    DeleteDeletionRequestsByDid {
        did: Did,
        tx: Tx<()>,
    },
    UpsertAccountPreference {
        user_id: Uuid,
        name: String,
        value_json: serde_json::Value,
        tx: Tx<()>,
    },
    InsertAccountPreferenceIfNotExists {
        user_id: Uuid,
        name: String,
        value_json: serde_json::Value,
        tx: Tx<()>,
    },
    GetServerConfig {
        key: String,
        tx: Tx<Option<String>>,
    },
    InsertReport {
        id: i64,
        reason_type: String,
        reason: Option<String>,
        subject_json: serde_json::Value,
        reported_by_did: Did,
        created_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    DeletePlcTokensForUser {
        user_id: Uuid,
        tx: Tx<()>,
    },
    InsertPlcToken {
        user_id: Uuid,
        token: String,
        expires_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    GetPlcTokenExpiry {
        user_id: Uuid,
        token: String,
        tx: Tx<Option<DateTime<Utc>>>,
    },
    DeletePlcToken {
        user_id: Uuid,
        token: String,
        tx: Tx<()>,
    },
    GetAccountPreferences {
        user_id: Uuid,
        tx: Tx<Vec<(String, serde_json::Value)>>,
    },
    ReplaceNamespacePreferences {
        user_id: Uuid,
        namespace: String,
        preferences: Vec<(String, serde_json::Value)>,
        tx: Tx<()>,
    },
    GetNotificationHistory {
        user_id: Uuid,
        limit: i64,
        tx: Tx<Vec<NotificationHistoryRow>>,
    },
    GetServerConfigs {
        keys: Vec<String>,
        tx: Tx<Vec<(String, String)>>,
    },
    UpsertServerConfig {
        key: String,
        value: String,
        tx: Tx<()>,
    },
    DeleteServerConfig {
        key: String,
        tx: Tx<()>,
    },
    GetBlobStorageKeyByCid {
        cid: CidLink,
        tx: Tx<Option<String>>,
    },
    DeleteBlobByCid {
        cid: CidLink,
        tx: Tx<()>,
    },
    GetAdminAccountInfoByDid {
        did: Did,
        tx: Tx<Option<AdminAccountInfo>>,
    },
    GetAdminAccountInfosByDids {
        dids: Vec<Did>,
        tx: Tx<Vec<AdminAccountInfo>>,
    },
    GetInviteCodeUsesByUsers {
        user_ids: Vec<Uuid>,
        tx: Tx<Vec<(Uuid, String)>>,
    },
    GetDeletionRequestByDid {
        did: Did,
        tx: Tx<Option<DeletionRequestWithToken>>,
    },
    GetLatestCommsForUser {
        user_id: Uuid,
        comms_type: CommsType,
        limit: i64,
        tx: Tx<Vec<QueuedComms>>,
    },
    CountCommsByType {
        user_id: Uuid,
        comms_type: CommsType,
        tx: Tx<i64>,
    },
    DeleteCommsByTypeForUser {
        user_id: Uuid,
        comms_type: CommsType,
        tx: Tx<u64>,
    },
    ExpireDeletionRequest {
        token: String,
        tx: Tx<()>,
    },
    GetReservedSigningKeyFull {
        public_key_did_key: String,
        tx: Tx<Option<ReservedSigningKeyFull>>,
    },
    GetPlcTokensByDid {
        did: Did,
        tx: Tx<Vec<PlcTokenInfo>>,
    },
    CountPlcTokensByDid {
        did: Did,
        tx: Tx<i64>,
    },
}

impl InfraRequest {
    fn routing(&self, user_hashes: &UserHashMap) -> Routing {
        match self {
            Self::UpsertAccountPreference { user_id, .. }
            | Self::InsertAccountPreferenceIfNotExists { user_id, .. }
            | Self::GetAccountPreferences { user_id, .. }
            | Self::ReplaceNamespacePreferences { user_id, .. }
            | Self::GetNotificationHistory { user_id, .. }
            | Self::DeletePlcTokensForUser { user_id, .. }
            | Self::InsertPlcToken { user_id, .. }
            | Self::GetPlcTokenExpiry { user_id, .. }
            | Self::DeletePlcToken { user_id, .. }
            | Self::GetInvitesCreatedByUser { user_id, .. }
            | Self::GetInviteCodeUsedByUser { user_id, .. }
            | Self::DeleteInviteCodeUsesByUser { user_id, .. }
            | Self::DeleteInviteCodesByUser { user_id, .. }
            | Self::GetLatestCommsForUser { user_id, .. }
            | Self::CountCommsByType { user_id, .. }
            | Self::DeleteCommsByTypeForUser { user_id, .. } => {
                uuid_to_routing(user_hashes, user_id)
            }
            Self::CreateInviteCodesBatch {
                created_by_user, ..
            } => uuid_to_routing(user_hashes, created_by_user),
            Self::EnqueueComms {
                user_id: Some(uid), ..
            } => uuid_to_routing(user_hashes, uid),
            Self::GetInviteCodesForAccount { for_account, .. } => {
                did_to_routing(for_account.as_str())
            }
            Self::DeleteDeletionRequestsByDid { did, .. }
            | Self::CreateDeletionRequest { did, .. }
            | Self::GetAdminAccountInfoByDid { did, .. }
            | Self::GetDeletionRequestByDid { did, .. }
            | Self::GetPlcTokensByDid { did, .. }
            | Self::CountPlcTokensByDid { did, .. } => did_to_routing(did),
            Self::GetBlobStorageKeyByCid { cid, .. } | Self::DeleteBlobByCid { cid, .. } => {
                cid_to_routing(cid)
            }
            _ => Routing::Global,
        }
    }
}

pub enum OAuthRequest {
    CreateToken {
        data: TokenData,
        tx: Tx<TokenFamilyId>,
    },
    GetTokenById {
        token_id: TokenId,
        tx: Tx<Option<TokenData>>,
    },
    GetTokenByRefreshToken {
        refresh_token: RefreshToken,
        tx: Tx<Option<(TokenFamilyId, TokenData)>>,
    },
    GetTokenByPreviousRefreshToken {
        refresh_token: RefreshToken,
        tx: Tx<Option<(TokenFamilyId, TokenData)>>,
    },
    RotateToken {
        old_db_id: TokenFamilyId,
        new_refresh_token: RefreshToken,
        new_expires_at: DateTime<Utc>,
        tx: Tx<()>,
    },
    CheckRefreshTokenUsed {
        refresh_token: RefreshToken,
        tx: Tx<Option<TokenFamilyId>>,
    },
    DeleteToken {
        token_id: TokenId,
        tx: Tx<()>,
    },
    DeleteTokenFamily {
        db_id: TokenFamilyId,
        tx: Tx<()>,
    },
    ListTokensForUser {
        did: Did,
        tx: Tx<Vec<TokenData>>,
    },
    CountTokensForUser {
        did: Did,
        tx: Tx<i64>,
    },
    DeleteOldestTokensForUser {
        did: Did,
        keep_count: i64,
        tx: Tx<u64>,
    },
    RevokeTokensForClient {
        did: Did,
        client_id: ClientId,
        tx: Tx<u64>,
    },
    RevokeTokensForController {
        delegated_did: Did,
        controller_did: Did,
        tx: Tx<u64>,
    },
    CreateAuthorizationRequest {
        request_id: RequestId,
        data: RequestData,
        tx: Tx<()>,
    },
    GetAuthorizationRequest {
        request_id: RequestId,
        tx: Tx<Option<RequestData>>,
    },
    SetAuthorizationDid {
        request_id: RequestId,
        did: Did,
        device_id: Option<DeviceId>,
        tx: Tx<()>,
    },
    UpdateAuthorizationRequest {
        request_id: RequestId,
        did: Did,
        device_id: Option<DeviceId>,
        code: AuthorizationCode,
        tx: Tx<()>,
    },
    ConsumeAuthorizationRequestByCode {
        code: AuthorizationCode,
        tx: Tx<Option<RequestData>>,
    },
    DeleteAuthorizationRequest {
        request_id: RequestId,
        tx: Tx<()>,
    },
    DeleteExpiredAuthorizationRequests {
        tx: Tx<u64>,
    },
    ExtendAuthorizationRequestExpiry {
        request_id: RequestId,
        new_expires_at: DateTime<Utc>,
        tx: Tx<bool>,
    },
    MarkRequestAuthenticated {
        request_id: RequestId,
        did: Did,
        device_id: Option<DeviceId>,
        tx: Tx<()>,
    },
    UpdateRequestScope {
        request_id: RequestId,
        scope: String,
        tx: Tx<()>,
    },
    SetControllerDid {
        request_id: RequestId,
        controller_did: Did,
        tx: Tx<()>,
    },
    SetRequestDid {
        request_id: RequestId,
        did: Did,
        tx: Tx<()>,
    },
    CreateDevice {
        device_id: DeviceId,
        data: DeviceData,
        tx: Tx<()>,
    },
    GetDevice {
        device_id: DeviceId,
        tx: Tx<Option<DeviceData>>,
    },
    UpdateDeviceLastSeen {
        device_id: DeviceId,
        tx: Tx<()>,
    },
    DeleteDevice {
        device_id: DeviceId,
        tx: Tx<()>,
    },
    UpsertAccountDevice {
        did: Did,
        device_id: DeviceId,
        tx: Tx<()>,
    },
    GetDeviceAccounts {
        device_id: DeviceId,
        tx: Tx<Vec<tranquil_db_traits::DeviceAccountRow>>,
    },
    VerifyAccountOnDevice {
        device_id: DeviceId,
        did: Did,
        tx: Tx<bool>,
    },
    CheckAndRecordDpopJti {
        jti: DPoPProofId,
        tx: Tx<bool>,
    },
    CleanupExpiredDpopJtis {
        max_age_secs: i64,
        tx: Tx<u64>,
    },
    Create2faChallenge {
        did: Did,
        request_uri: RequestId,
        tx: Tx<tranquil_db_traits::TwoFactorChallenge>,
    },
    Get2faChallenge {
        request_uri: RequestId,
        tx: Tx<Option<tranquil_db_traits::TwoFactorChallenge>>,
    },
    Increment2faAttempts {
        id: Uuid,
        tx: Tx<i32>,
    },
    Delete2faChallenge {
        id: Uuid,
        tx: Tx<()>,
    },
    Delete2faChallengeByRequestUri {
        request_uri: RequestId,
        tx: Tx<()>,
    },
    CleanupExpired2faChallenges {
        tx: Tx<u64>,
    },
    CheckUser2faEnabled {
        did: Did,
        tx: Tx<bool>,
    },
    GetScopePreferences {
        did: Did,
        client_id: ClientId,
        tx: Tx<Vec<ScopePreference>>,
    },
    UpsertScopePreferences {
        did: Did,
        client_id: ClientId,
        prefs: Vec<ScopePreference>,
        tx: Tx<()>,
    },
    DeleteScopePreferences {
        did: Did,
        client_id: ClientId,
        tx: Tx<()>,
    },
    UpsertAuthorizedClient {
        did: Did,
        client_id: ClientId,
        data: AuthorizedClientData,
        tx: Tx<()>,
    },
    GetAuthorizedClient {
        did: Did,
        client_id: ClientId,
        tx: Tx<Option<AuthorizedClientData>>,
    },
    ListTrustedDevices {
        did: Did,
        tx: Tx<Vec<tranquil_db_traits::TrustedDeviceRow>>,
    },
    GetDeviceTrustInfo {
        device_id: DeviceId,
        did: Did,
        tx: Tx<Option<tranquil_db_traits::DeviceTrustInfo>>,
    },
    DeviceBelongsToUser {
        device_id: DeviceId,
        did: Did,
        tx: Tx<bool>,
    },
    RevokeDeviceTrust {
        device_id: DeviceId,
        did: Did,
        tx: Tx<()>,
    },
    UpdateDeviceFriendlyName {
        device_id: DeviceId,
        did: Did,
        friendly_name: Option<String>,
        tx: Tx<()>,
    },
    TrustDevice {
        device_id: DeviceId,
        did: Did,
        trusted_at: DateTime<Utc>,
        trusted_until: DateTime<Utc>,
        tx: Tx<()>,
    },
    ExtendDeviceTrust {
        device_id: DeviceId,
        did: Did,
        trusted_until: DateTime<Utc>,
        tx: Tx<()>,
    },
    ListSessionsByDid {
        did: Did,
        tx: Tx<Vec<tranquil_db_traits::OAuthSessionListItem>>,
    },
    DeleteSessionById {
        session_id: TokenFamilyId,
        did: Did,
        tx: Tx<u64>,
    },
    DeleteSessionsByDid {
        did: Did,
        tx: Tx<u64>,
    },
    DeleteSessionsByDidExcept {
        did: Did,
        except_token_id: TokenId,
        tx: Tx<u64>,
    },
    Get2faChallengeCode {
        request_uri: RequestId,
        tx: Tx<Option<String>>,
    },
}

impl OAuthRequest {
    fn routing(&self) -> Routing {
        match self {
            Self::ListTokensForUser { did, .. }
            | Self::CountTokensForUser { did, .. }
            | Self::DeleteOldestTokensForUser { did, .. }
            | Self::RevokeTokensForClient { did, .. }
            | Self::Create2faChallenge { did, .. }
            | Self::CheckUser2faEnabled { did, .. }
            | Self::GetScopePreferences { did, .. }
            | Self::UpsertScopePreferences { did, .. }
            | Self::DeleteScopePreferences { did, .. }
            | Self::UpsertAuthorizedClient { did, .. }
            | Self::GetAuthorizedClient { did, .. }
            | Self::ListTrustedDevices { did, .. }
            | Self::GetDeviceTrustInfo { did, .. }
            | Self::DeviceBelongsToUser { did, .. }
            | Self::UpsertAccountDevice { did, .. }
            | Self::VerifyAccountOnDevice { did, .. }
            | Self::ListSessionsByDid { did, .. }
            | Self::DeleteSessionsByDid { did, .. }
            | Self::DeleteSessionsByDidExcept { did, .. }
            | Self::DeleteSessionById { did, .. } => did_to_routing(did),
            Self::RevokeTokensForController { delegated_did, .. } => did_to_routing(delegated_did),
            Self::SetAuthorizationDid { did, .. }
            | Self::UpdateAuthorizationRequest { did, .. }
            | Self::MarkRequestAuthenticated { did, .. }
            | Self::SetRequestDid { did, .. } => did_to_routing(did),
            Self::CreateToken { .. }
            | Self::GetTokenById { .. }
            | Self::GetTokenByRefreshToken { .. }
            | Self::GetTokenByPreviousRefreshToken { .. }
            | Self::RotateToken { .. }
            | Self::CheckRefreshTokenUsed { .. }
            | Self::DeleteToken { .. }
            | Self::DeleteTokenFamily { .. }
            | Self::CreateAuthorizationRequest { .. }
            | Self::GetAuthorizationRequest { .. }
            | Self::ConsumeAuthorizationRequestByCode { .. }
            | Self::DeleteAuthorizationRequest { .. }
            | Self::DeleteExpiredAuthorizationRequests { .. }
            | Self::ExtendAuthorizationRequestExpiry { .. }
            | Self::UpdateRequestScope { .. }
            | Self::SetControllerDid { .. }
            | Self::CreateDevice { .. }
            | Self::GetDevice { .. }
            | Self::UpdateDeviceLastSeen { .. }
            | Self::DeleteDevice { .. }
            | Self::GetDeviceAccounts { .. }
            | Self::CheckAndRecordDpopJti { .. }
            | Self::CleanupExpiredDpopJtis { .. }
            | Self::Get2faChallenge { .. }
            | Self::Increment2faAttempts { .. }
            | Self::Delete2faChallenge { .. }
            | Self::Delete2faChallengeByRequestUri { .. }
            | Self::CleanupExpired2faChallenges { .. }
            | Self::RevokeDeviceTrust { .. }
            | Self::UpdateDeviceFriendlyName { .. }
            | Self::TrustDevice { .. }
            | Self::ExtendDeviceTrust { .. }
            | Self::Get2faChallengeCode { .. } => Routing::Global,
        }
    }
}

fn convert_repo_info(
    r: super::repo_ops::RepoInfo,
) -> Result<tranquil_db_traits::RepoInfo, DbError> {
    Ok(tranquil_db_traits::RepoInfo {
        user_id: r.user_id,
        repo_root_cid: r.repo_root_cid,
        repo_rev: r
            .repo_rev
            .map(|rev| {
                Tid::new(rev).map_err(|_| DbError::CorruptData("corrupt repo_meta repo_rev"))
            })
            .transpose()?,
    })
}

fn convert_repo_account(
    r: super::repo_ops::RepoAccountEntry,
) -> tranquil_db_traits::RepoAccountInfo {
    tranquil_db_traits::RepoAccountInfo {
        user_id: r.user_id,
        did: r.did,
        deactivated_at: r.deactivated_at,
        takedown_ref: r.takedown_ref,
        repo_root_cid: r.repo_root_cid,
    }
}

fn convert_repo_list_entry(
    r: super::repo_ops::RepoListEntry,
) -> Result<tranquil_db_traits::RepoListItem, DbError> {
    let did = r
        .did
        .ok_or(DbError::CorruptData("repo_meta missing DID field"))?;
    Ok(tranquil_db_traits::RepoListItem {
        did: Did::new(did).map_err(|_| DbError::CorruptData("corrupt repo_meta did"))?,
        deactivated_at: r.deactivated_at,
        takedown_ref: r.takedown_ref,
        repo_root_cid: r.repo_root_cid,
        repo_rev: r
            .repo_rev
            .map(|rev| {
                Tid::new(rev).map_err(|_| DbError::CorruptData("corrupt repo_meta repo_rev"))
            })
            .transpose()?,
    })
}

fn convert_record_info(r: super::record_ops::RecordInfo) -> tranquil_db_traits::RecordInfo {
    tranquil_db_traits::RecordInfo {
        rkey: r.rkey,
        record_cid: r.record_cid,
    }
}

fn convert_full_record_info(
    r: super::record_ops::FullRecordInfo,
) -> tranquil_db_traits::FullRecordInfo {
    tranquil_db_traits::FullRecordInfo {
        collection: r.collection,
        rkey: r.rkey,
        record_cid: r.record_cid,
    }
}

fn convert_record_with_takedown(
    r: super::record_ops::RecordWithTakedown,
) -> tranquil_db_traits::RecordWithTakedown {
    tranquil_db_traits::RecordWithTakedown {
        id: r.id,
        takedown_ref: r.takedown_ref,
    }
}

fn convert_without_rev(
    r: super::repo_ops::RepoWithoutRevEntry,
) -> tranquil_db_traits::RepoWithoutRev {
    tranquil_db_traits::RepoWithoutRev {
        user_id: r.user_id,
        repo_root_cid: r.repo_root_cid,
    }
}

struct HandlerState<S: StorageIO> {
    metastore: Metastore,
    event_ops: EventOps<S>,
    commit_ops: CommitOps<S>,
}

fn dispatch_repo<S: StorageIO>(state: &HandlerState<S>, req: RepoRequest) {
    match req {
        RepoRequest::CreateRepoFull {
            user_id,
            did,
            handle,
            repo_root_cid,
            repo_rev,
            tx,
        } => {
            let result = state
                .metastore
                .repo_ops()
                .create_repo(
                    state.metastore.database(),
                    user_id,
                    &did,
                    &handle,
                    &repo_root_cid,
                    &repo_rev,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::UpdateRepoRoot {
            user_id,
            repo_root_cid,
            repo_rev,
            tx,
        } => {
            let result = state
                .metastore
                .repo_ops()
                .update_repo_root(
                    state.metastore.database(),
                    user_id,
                    &repo_root_cid,
                    &repo_rev,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::UpdateRepoRev {
            user_id,
            repo_rev,
            tx,
        } => {
            let result = state
                .metastore
                .repo_ops()
                .update_repo_rev(state.metastore.database(), user_id, &repo_rev)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::DeleteRepo { user_id, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .delete_repo(state.metastore.database(), user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::GetRepoRootForUpdate { user_id, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_repo_root_for_update(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::GetRepo { user_id, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_repo(user_id)
                .map_err(metastore_to_db)
                .and_then(|opt| opt.map(convert_repo_info).transpose());
            let _ = tx.send(result);
        }
        RepoRequest::GetRepoRootByDid { did, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_repo_root_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::CountRepos { tx } => {
            let result = state
                .metastore
                .repo_ops()
                .count_repos()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::GetReposWithoutRev { tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_repos_without_rev(MAX_REPOS_WITHOUT_REV)
                .map(|v| v.into_iter().map(convert_without_rev).collect())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::GetRepoRootCidByUserId { user_id, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_repo_root_cid_by_user_id(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::GetAccountWithRepo { did, tx } => {
            let result = state
                .metastore
                .repo_ops()
                .get_account_with_repo(&did)
                .map(|opt| opt.map(convert_repo_account))
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RepoRequest::ListReposPaginated {
            cursor_user_hash,
            limit,
            tx,
        } => {
            let result = state
                .metastore
                .repo_ops()
                .list_repos_paginated(cursor_user_hash, limit)
                .map_err(metastore_to_db)
                .and_then(|entries| entries.into_iter().map(convert_repo_list_entry).collect());
            let _ = tx.send(result);
        }
        RepoRequest::UpdateRepoStatus {
            did,
            takedown,
            takedown_ref,
            deactivated,
            tx,
        } => {
            let result = state
                .metastore
                .repo_ops()
                .update_repo_status(
                    state.metastore.database(),
                    &did,
                    takedown,
                    takedown_ref.as_deref(),
                    deactivated,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_record<S: StorageIO>(state: &HandlerState<S>, req: RecordRequest) {
    match req {
        RecordRequest::UpsertRecords {
            repo_id,
            collections,
            rkeys,
            record_cids,
            repo_rev,
            tx,
        } => {
            let result = (|| {
                let (user_hash, mut meta) = state
                    .metastore
                    .repo_ops()
                    .get_repo_meta(repo_id)
                    .map_err(metastore_to_db)?
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let writes: Vec<super::record_ops::RecordWrite<'_>> = collections
                    .iter()
                    .zip(rkeys.iter())
                    .zip(record_cids.iter())
                    .map(|((c, r), cid)| super::record_ops::RecordWrite {
                        collection: c,
                        rkey: r,
                        cid,
                    })
                    .collect();
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .record_ops()
                    .upsert_records(&mut batch, user_hash, &writes)
                    .map_err(metastore_to_db)?;
                meta.repo_rev = repo_rev.as_str().to_owned();
                state
                    .metastore
                    .repo_ops()
                    .write_repo_meta(&mut batch, user_hash, &meta);
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        RecordRequest::DeleteRecords {
            repo_id,
            collections,
            rkeys,
            tx,
        } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&repo_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let deletes: Vec<super::record_ops::RecordDelete<'_>> = collections
                    .iter()
                    .zip(rkeys.iter())
                    .map(|(c, r)| super::record_ops::RecordDelete {
                        collection: c,
                        rkey: r,
                    })
                    .collect();
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .record_ops()
                    .delete_records(&mut batch, user_hash, &deletes)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        RecordRequest::DeleteAllRecords { repo_id, tx } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&repo_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .record_ops()
                    .delete_all_records(&mut batch, user_hash)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        RecordRequest::GetRecordCid {
            repo_id,
            collection,
            rkey,
            tx,
        } => {
            let result = state
                .metastore
                .record_ops()
                .get_record_cid(repo_id, &collection, &rkey)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::ListRecords {
            repo_id,
            collection,
            cursor,
            limit,
            reverse,
            rkey_start,
            rkey_end,
            tx,
        } => {
            let query = ListRecordsQuery {
                user_id: repo_id,
                collection: &collection,
                cursor: cursor.as_ref(),
                limit: usize::try_from(limit).unwrap_or(0),
                reverse,
                rkey_start: rkey_start.as_ref(),
                rkey_end: rkey_end.as_ref(),
            };
            let result = state
                .metastore
                .record_ops()
                .list_records(&query)
                .map(|v| v.into_iter().map(convert_record_info).collect())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::GetAllRecords { repo_id, tx } => {
            let result = state
                .metastore
                .record_ops()
                .get_all_records(repo_id)
                .map(|v| v.into_iter().map(convert_full_record_info).collect())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::ListCollections { repo_id, tx } => {
            let result = state
                .metastore
                .record_ops()
                .list_collections(repo_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::CountRecords { repo_id, tx } => {
            let result = state
                .metastore
                .record_ops()
                .count_records(repo_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::CountAllRecords { tx } => {
            let result = state
                .metastore
                .record_ops()
                .count_all_records()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::GetRecordByCid { cid, tx } => {
            let result = state
                .metastore
                .record_ops()
                .get_record_by_cid(&cid, None)
                .map(|opt| opt.map(convert_record_with_takedown))
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::ReferencedRecordCids {
            repo_id,
            cids,
            excluded_keys,
            tx,
        } => {
            let excluded: Vec<(&Nsid, &Rkey)> = excluded_keys
                .iter()
                .map(|(collection, rkey)| (collection, rkey))
                .collect();
            let result = state
                .metastore
                .record_ops()
                .referenced_record_cids(repo_id, &cids, &excluded)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        RecordRequest::SetRecordTakedown {
            cid,
            takedown_ref,
            scope_user,
            tx,
        } => {
            let result = state
                .metastore
                .record_ops()
                .set_record_takedown(
                    state.metastore.database(),
                    &cid,
                    takedown_ref.as_deref(),
                    scope_user,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_user_block<S: StorageIO>(state: &HandlerState<S>, req: UserBlockRequest) {
    match req {
        UserBlockRequest::InsertUserBlocks {
            user_id,
            block_cids,
            repo_rev,
            tx,
        } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&user_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .user_block_ops()
                    .insert_user_blocks(&mut batch, user_hash, &block_cids, &repo_rev)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        UserBlockRequest::DeleteUserBlocks {
            user_id,
            block_cids,
            tx,
        } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&user_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .user_block_ops()
                    .delete_user_blocks_by_cid(&mut batch, user_hash, &block_cids)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        UserBlockRequest::GetUserBlockCidsSinceRev {
            user_id,
            since_rev,
            tx,
        } => {
            let result = state
                .metastore
                .user_block_ops()
                .get_user_block_cids_since_rev(user_id, since_rev.as_ref())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        UserBlockRequest::CountUserBlocks { user_id, tx } => {
            let result = state
                .metastore
                .user_block_ops()
                .count_user_blocks(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_event<S: StorageIO + 'static>(state: &HandlerState<S>, req: EventRequest) {
    match req {
        EventRequest::InsertCommitEvent { data, tx } => {
            let result = state.event_ops.insert_commit_event(&data);
            let _ = tx.send(result);
        }
        EventRequest::InsertIdentityEvent { did, handle, tx } => {
            let result = state.event_ops.insert_identity_event(&did, handle.as_ref());
            let _ = tx.send(result);
        }
        EventRequest::InsertAccountEvent { did, status, tx } => {
            let result = state.event_ops.insert_account_event(&did, status);
            let _ = tx.send(result);
        }
        EventRequest::InsertSyncEvent {
            did,
            commit_cid,
            rev,
            commit_bytes,
            tx,
        } => {
            let result =
                state
                    .event_ops
                    .insert_sync_event(&did, &commit_cid, rev.as_ref(), &commit_bytes);
            let _ = tx.send(result);
        }
        EventRequest::InsertGenesisCommitEvent {
            did,
            commit_cid,
            mst_root_cid,
            rev,
            commit_bytes,
            mst_root_bytes,
            tx,
        } => {
            let result = state.event_ops.insert_genesis_commit_event(
                &did,
                &commit_cid,
                &mst_root_cid,
                &rev,
                &commit_bytes,
                &mst_root_bytes,
            );
            let _ = tx.send(result);
        }
        EventRequest::PurgeDidEventsKeepingLatest { did, tx } => {
            let result = state.event_ops.purge_did_events_keeping_latest(&did);
            let _ = tx.send(result);
        }
        EventRequest::GetMaxSeq { tx } => {
            let _ = tx.send(Ok(state.event_ops.get_max_seq()));
        }
        EventRequest::GetMinSeqSince { since, tx } => {
            let _ = tx.send(state.event_ops.get_min_seq_since(since));
        }
        EventRequest::GetEventsSinceSeq {
            since_seq,
            limit,
            tx,
        } => {
            let _ = tx.send(state.event_ops.get_events_since_seq(since_seq, limit));
        }
        EventRequest::GetEventsInSeqRange {
            start_seq,
            end_seq,
            tx,
        } => {
            let _ = tx.send(state.event_ops.get_events_in_seq_range(start_seq, end_seq));
        }
        EventRequest::GetEventBySeq { seq, tx } => {
            let _ = tx.send(state.event_ops.get_event_by_seq(seq));
        }
        EventRequest::GetEventsSinceCursor { cursor, limit, tx } => {
            let _ = tx.send(state.event_ops.get_events_since_cursor(cursor, limit));
        }
    }
}

fn dispatch_commit<S: StorageIO + 'static>(state: &HandlerState<S>, req: CommitRequest) {
    match req {
        CommitRequest::ApplyCommit { input, tx } => {
            let _ = tx.send(state.commit_ops.apply_commit(*input));
        }
        CommitRequest::ImportRepoData {
            user_id,
            blocks,
            records,
            expected_root_cid,
            tx,
        } => {
            let _ = tx.send(state.commit_ops.import_repo_data(
                user_id,
                &blocks,
                &records,
                expected_root_cid.as_ref(),
            ));
        }
        CommitRequest::GetUsersWithoutBlocks { tx } => {
            let _ = tx.send(
                state
                    .commit_ops
                    .get_users_without_blocks()
                    .map_err(metastore_to_db),
            );
        }
        CommitRequest::GetUsersNeedingRecordBlobsBackfill { limit, tx } => {
            let _ = tx.send(
                state
                    .commit_ops
                    .get_users_needing_record_blobs_backfill(limit)
                    .map_err(metastore_to_db),
            );
        }
        CommitRequest::InsertRecordBlobs {
            repo_id,
            record_uris,
            blob_cids,
            tx,
        } => {
            let _ = tx.send(
                state
                    .commit_ops
                    .insert_record_blobs(repo_id, &record_uris, &blob_cids)
                    .map_err(metastore_to_db),
            );
        }
    }
}

fn dispatch_backlink<S: StorageIO>(state: &HandlerState<S>, req: BacklinkRequest) {
    match req {
        BacklinkRequest::GetBacklinkConflicts {
            repo_id,
            collection,
            backlinks,
            tx,
        } => {
            let result = state
                .metastore
                .backlink_ops()
                .get_backlink_conflicts(repo_id, &collection, &backlinks)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BacklinkRequest::AddBacklinks {
            repo_id,
            backlinks,
            tx,
        } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&repo_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .backlink_ops()
                    .add_backlinks(&mut batch, user_hash, &backlinks)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        BacklinkRequest::RemoveBacklinksByUri { uri, tx } => {
            let result = (|| {
                let did_str = uri
                    .did()
                    .ok_or(DbError::Query("backlink uri missing did".to_string()))?;
                let user_hash = UserHash::from_did(did_str);
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .backlink_ops()
                    .remove_backlinks_by_uri(&mut batch, user_hash, &uri)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
        BacklinkRequest::RemoveBacklinksByRepo { repo_id, tx } => {
            let result = (|| {
                let user_hash = state
                    .metastore
                    .user_hashes()
                    .get(&repo_id)
                    .ok_or(DbError::Query("unknown user_id".to_string()))?;
                let mut batch = state.metastore.database().batch();
                state
                    .metastore
                    .backlink_ops()
                    .remove_backlinks_by_repo(&mut batch, user_hash)
                    .map_err(metastore_to_db)?;
                batch.commit().map_err(|e| DbError::Query(e.to_string()))
            })();
            let _ = tx.send(result);
        }
    }
}

fn dispatch_blob<S: StorageIO + 'static>(state: &HandlerState<S>, req: BlobRequest) {
    match req {
        BlobRequest::InsertBlob {
            cid,
            mime_type,
            size_bytes,
            created_by_user,
            storage_key,
            tx,
        } => {
            let result = state
                .metastore
                .blob_ops()
                .insert_blob(&cid, &mime_type, size_bytes, created_by_user, &storage_key)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::GetBlobMetadata { cid, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .get_blob_metadata(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::GetBlobWithTakedown { cid, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .get_blob_with_takedown(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::GetBlobStorageKey { cid, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .get_blob_storage_key(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::ListBlobsByUser {
            user_id,
            cursor,
            limit,
            tx,
        } => {
            let result = state
                .metastore
                .blob_ops()
                .list_blobs_by_user(
                    user_id,
                    cursor.as_deref(),
                    usize::try_from(limit).unwrap_or(0),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::ListBlobsSinceRev { did, since, tx } => {
            let result = state.event_ops.get_blob_cids_since_rev(&did, &since);
            let _ = tx.send(result);
        }
        BlobRequest::CountBlobsByUser { user_id, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .count_blobs_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::SumBlobStorage { tx } => {
            let result = state
                .metastore
                .blob_ops()
                .sum_blob_storage()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::UpdateBlobTakedown {
            cid,
            takedown_ref,
            tx,
        } => {
            let result = state
                .metastore
                .blob_ops()
                .update_blob_takedown(&cid, takedown_ref.as_deref())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::DeleteBlobByCid { cid, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .delete_blob_by_cid(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::DeleteBlobsByUser { user_id, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .delete_blobs_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::GetBlobStorageKeysByUser { user_id, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .get_blob_storage_keys_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::ListMissingBlobs {
            repo_id,
            cursor,
            limit,
            tx,
        } => {
            let result = state
                .metastore
                .blob_ops()
                .list_missing_blobs(
                    repo_id,
                    cursor.as_deref(),
                    usize::try_from(limit).unwrap_or(0),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::CountDistinctRecordBlobs { repo_id, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .count_distinct_record_blobs(repo_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        BlobRequest::GetBlobsForExport { repo_id, tx } => {
            let result = state
                .metastore
                .blob_ops()
                .get_blobs_for_export(repo_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_delegation<S: StorageIO>(state: &HandlerState<S>, req: DelegationRequest) {
    match req {
        DelegationRequest::IsDelegatedAccount { did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .is_delegated_account(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::CreateDelegation {
            delegated_did,
            controller_did,
            granted_scopes,
            granted_by,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .create_delegation(
                    &delegated_did,
                    &controller_did,
                    &granted_scopes,
                    &granted_by,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::RevokeDelegation {
            delegated_did,
            controller_did,
            revoked_by,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .revoke_delegation(&delegated_did, &controller_did, &revoked_by)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::UpdateDelegationScopes {
            delegated_did,
            controller_did,
            new_scopes,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .update_delegation_scopes(&delegated_did, &controller_did, &new_scopes)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::GetDelegation {
            delegated_did,
            controller_did,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .get_delegation(&delegated_did, &controller_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::GetDelegationsForAccount { delegated_did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .get_delegations_for_account(&delegated_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::GetAccountsControlledBy { controller_did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .get_accounts_controlled_by(&controller_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::CountActiveControllers { delegated_did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .count_active_controllers(&delegated_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::ControlsAnyAccounts { did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .controls_any_accounts(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::LogDelegationAction {
            delegated_did,
            actor_did,
            controller_did,
            action_type,
            action_details,
            ip_address,
            user_agent,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .log_delegation_action(
                    &delegated_did,
                    &actor_did,
                    controller_did.as_ref(),
                    action_type,
                    action_details,
                    ip_address.as_deref(),
                    user_agent.as_deref(),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::GetAuditLogForAccount {
            delegated_did,
            limit,
            offset,
            tx,
        } => {
            let result = state
                .metastore
                .delegation_ops()
                .get_audit_log_for_account(&delegated_did, limit, offset)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        DelegationRequest::CountAuditLogEntries { delegated_did, tx } => {
            let result = state
                .metastore
                .delegation_ops()
                .count_audit_log_entries(&delegated_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_sso<S: StorageIO>(state: &HandlerState<S>, req: SsoRequest) {
    match req {
        SsoRequest::CreateExternalIdentity {
            did,
            provider,
            provider_user_id,
            provider_username,
            provider_email,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .create_external_identity(
                    &did,
                    provider,
                    &provider_user_id,
                    provider_username.as_deref(),
                    provider_email.as_deref(),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::GetExternalIdentityByProvider {
            provider,
            provider_user_id,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .get_external_identity_by_provider(provider, &provider_user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::GetExternalIdentitiesByDid { did, tx } => {
            let result = state
                .metastore
                .sso_ops()
                .get_external_identities_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::UpdateExternalIdentityLogin {
            id,
            provider_username,
            provider_email,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .update_external_identity_login(
                    id,
                    provider_username.as_deref(),
                    provider_email.as_deref(),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::DeleteExternalIdentity { id, did, tx } => {
            let result = state
                .metastore
                .sso_ops()
                .delete_external_identity(id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::CreateSsoAuthState {
            state: sso_state,
            request_uri,
            provider,
            action,
            nonce,
            code_verifier,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .create_sso_auth_state(
                    &sso_state,
                    &request_uri,
                    provider,
                    action,
                    nonce.as_deref(),
                    code_verifier.as_deref(),
                    did.as_ref(),
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::ConsumeSsoAuthState {
            state: sso_state,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .consume_sso_auth_state(&sso_state)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::CleanupExpiredSsoAuthStates { tx } => {
            let result = state
                .metastore
                .sso_ops()
                .cleanup_expired_sso_auth_states()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::CreatePendingRegistration {
            token,
            request_uri,
            provider,
            provider_user_id,
            provider_username,
            provider_email,
            provider_email_verified,
            tx,
        } => {
            let result = state
                .metastore
                .sso_ops()
                .create_pending_registration(
                    &token,
                    &request_uri,
                    provider,
                    &provider_user_id,
                    provider_username.as_deref(),
                    provider_email.as_deref(),
                    provider_email_verified,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::GetPendingRegistration { token, tx } => {
            let result = state
                .metastore
                .sso_ops()
                .get_pending_registration(&token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::ConsumePendingRegistration { token, tx } => {
            let result = state
                .metastore
                .sso_ops()
                .consume_pending_registration(&token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SsoRequest::CleanupExpiredPendingRegistrations { tx } => {
            let result = state
                .metastore
                .sso_ops()
                .cleanup_expired_pending_registrations()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_session<S: StorageIO>(state: &HandlerState<S>, req: SessionRequest) {
    match req {
        SessionRequest::CreateSession { data, tx } => {
            let result = state
                .metastore
                .session_ops()
                .create_session(&data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetSessionByAccessJti { access_jti, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_session_by_access_jti(&access_jti)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetSessionForRefresh { refresh_jti, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_session_for_refresh(&refresh_jti)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteSessionByAccessJti {
            access_jti,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .delete_session_by_access_jti(&access_jti, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteSessionById {
            session_id,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .delete_session_by_id(session_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteSessionsByDid { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .delete_sessions_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteSessionsByDidExceptJti {
            did,
            except_jti,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .delete_sessions_by_did_except_jti(&did, &except_jti)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::ListSessionsByDid { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .list_sessions_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetSessionAccessJtiById {
            session_id,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .get_session_access_jti_by_id(session_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteSessionsByAppPassword {
            did,
            app_password_name,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .delete_sessions_by_app_password(&did, &app_password_name)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetSessionJtisByAppPassword {
            did,
            app_password_name,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .get_session_jtis_by_app_password(&did, &app_password_name)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::LookupRefreshGrace { refresh_jti, tx } => {
            let result = state
                .metastore
                .session_ops()
                .lookup_refresh_grace(&refresh_jti)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::ListAppPasswords { user_id, tx } => {
            let result = state
                .metastore
                .session_ops()
                .list_app_passwords(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetAppPasswordsForLogin { user_id, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_app_passwords_for_login(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetAppPasswordByName { user_id, name, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_app_password_by_name(user_id, &name)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::CreateAppPassword { data, tx } => {
            let result = state
                .metastore
                .session_ops()
                .create_app_password(&data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteAppPassword { user_id, name, tx } => {
            let result = state
                .metastore
                .session_ops()
                .delete_app_password(user_id, &name)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::DeleteAppPasswordsByController {
            did,
            controller_did,
            tx,
        } => {
            let result = state
                .metastore
                .session_ops()
                .delete_app_passwords_by_controller(&did, &controller_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetLastReauthAt { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_last_reauth_at(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::UpdateLastReauth { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .update_last_reauth(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetSessionMfaStatus { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_session_mfa_status(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::UpdateMfaVerified { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .update_mfa_verified(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::GetAppPasswordHashesByDid { did, tx } => {
            let result = state
                .metastore
                .session_ops()
                .get_app_password_hashes_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        SessionRequest::RefreshSessionAtomic { data, tx } => {
            let result = state
                .metastore
                .session_ops()
                .refresh_session_atomic(&data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch_infra<S: StorageIO>(state: &HandlerState<S>, req: InfraRequest) {
    match req {
        InfraRequest::EnqueueComms {
            user_id,
            channel,
            comms_type,
            recipient,
            subject,
            body,
            metadata,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .enqueue_comms(
                    user_id,
                    channel,
                    comms_type,
                    &recipient,
                    subject.as_deref(),
                    &body,
                    metadata,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::FetchPendingComms {
            now,
            batch_size,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .fetch_pending_comms(now, batch_size)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::MarkCommsSent { id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .mark_comms_sent(id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::MarkCommsFailed { id, error, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .mark_comms_failed(id, &error)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::MarkCommsFailedPermanent { id, error, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .mark_comms_failed_permanent(id, &error)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::CreateInviteCode {
            code,
            use_count,
            for_account,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .create_invite_code(&code, use_count, &for_account)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::CreateInviteCodesBatch {
            codes,
            use_count,
            created_by_user,
            for_account,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .create_invite_codes_batch(&codes, use_count, created_by_user, &for_account)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeAvailableUses { code, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_available_uses(&code)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::ValidateInviteCode { code, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .validate_invite_code(&code)
                .map(|_| ());
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodesForAccount { for_account, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_codes_for_account(&for_account)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeUses { code, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_uses(&code)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DisableInviteCodesByCode { codes, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .disable_invite_codes_by_code(&codes)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DisableInviteCodesByAccount { accounts, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .disable_invite_codes_by_account(&accounts)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::ListInviteCodes {
            cursor,
            limit,
            sort,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .list_invite_codes(cursor.as_deref(), limit, sort)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetUserDidsByIds { user_ids, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_user_dids_by_ids(&user_ids)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeUsesBatch { codes, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_uses_batch(&codes)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInvitesCreatedByUser { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invites_created_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeInfo { code, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_info(&code)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodesByUsers { user_ids, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_codes_by_users(&user_ids)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeUsedByUser { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_used_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteInviteCodeUsesByUser { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_invite_code_uses_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteInviteCodesByUser { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_invite_codes_by_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::ReserveSigningKey {
            did,
            public_key_did_key,
            private_key_bytes,
            expires_at,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .reserve_signing_key(
                    did.as_ref(),
                    &public_key_did_key,
                    &private_key_bytes,
                    expires_at,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetReservedSigningKey {
            public_key_did_key,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .get_reserved_signing_key(&public_key_did_key)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::MarkSigningKeyUsed { key_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .mark_signing_key_used(key_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::CreateDeletionRequest {
            token,
            did,
            expires_at,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .create_deletion_request(&token, &did, expires_at)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetDeletionRequest { token, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_deletion_request(&token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteDeletionRequest { token, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_deletion_request(&token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteDeletionRequestsByDid { did, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_deletion_requests_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::UpsertAccountPreference {
            user_id,
            name,
            value_json,
            tx,
        } => {
            if name == "email_auth_factor" {
                let enabled = value_json.as_bool().unwrap_or(false);
                let _ = state
                    .metastore
                    .user_ops()
                    .set_email_2fa_enabled(user_id, enabled);
            }
            let result = state
                .metastore
                .infra_ops()
                .upsert_account_preference(user_id, &name, value_json)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::InsertAccountPreferenceIfNotExists {
            user_id,
            name,
            value_json,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .insert_account_preference_if_not_exists(user_id, &name, value_json)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetServerConfig { key, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_server_config(&key)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::InsertReport {
            id,
            reason_type,
            reason,
            subject_json,
            reported_by_did,
            created_at,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .insert_report(
                    id,
                    &reason_type,
                    reason.as_deref(),
                    subject_json,
                    &reported_by_did,
                    created_at,
                )
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeletePlcTokensForUser { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_plc_tokens_for_user(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::InsertPlcToken {
            user_id,
            token,
            expires_at,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .insert_plc_token(user_id, &token, expires_at)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetPlcTokenExpiry { user_id, token, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_plc_token_expiry(user_id, &token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeletePlcToken { user_id, token, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_plc_token(user_id, &token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetAccountPreferences { user_id, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_account_preferences(user_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::ReplaceNamespacePreferences {
            user_id,
            namespace,
            preferences,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .replace_namespace_preferences(user_id, &namespace, preferences)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetNotificationHistory { user_id, limit, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_notification_history(user_id, limit)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetServerConfigs { keys, tx } => {
            let key_refs: Vec<&str> = keys.iter().map(String::as_str).collect();
            let result = state
                .metastore
                .infra_ops()
                .get_server_configs(&key_refs)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::UpsertServerConfig { key, value, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .upsert_server_config(&key, &value)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteServerConfig { key, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_server_config(&key)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetBlobStorageKeyByCid { cid, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_blob_storage_key_by_cid(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteBlobByCid { cid, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_blob_by_cid(&cid)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetAdminAccountInfoByDid { did, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_admin_account_info_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetAdminAccountInfosByDids { dids, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_admin_account_infos_by_dids(&dids)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetInviteCodeUsesByUsers { user_ids, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_invite_code_uses_by_users(&user_ids)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetDeletionRequestByDid { did, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .get_deletion_request_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetLatestCommsForUser {
            user_id,
            comms_type,
            limit,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .get_latest_comms_for_user(user_id, comms_type, limit)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::CountCommsByType {
            user_id,
            comms_type,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .count_comms_by_type(user_id, comms_type)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::DeleteCommsByTypeForUser {
            user_id,
            comms_type,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .delete_comms_by_type_for_user(user_id, comms_type)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::ExpireDeletionRequest { token, tx } => {
            let result = state
                .metastore
                .infra_ops()
                .expire_deletion_request(&token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetReservedSigningKeyFull {
            public_key_did_key,
            tx,
        } => {
            let result = state
                .metastore
                .infra_ops()
                .get_reserved_signing_key_full(&public_key_did_key)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        InfraRequest::GetPlcTokensByDid { did, tx } => {
            let result = (|| {
                let user_id = state
                    .metastore
                    .user_ops()
                    .get_id_by_did(&did)
                    .map_err(metastore_to_db)?;
                match user_id {
                    Some(uid) => state
                        .metastore
                        .infra_ops()
                        .get_plc_tokens_for_user(uid)
                        .map_err(metastore_to_db),
                    None => Ok(Vec::new()),
                }
            })();
            let _ = tx.send(result);
        }
        InfraRequest::CountPlcTokensByDid { did, tx } => {
            let result = (|| {
                let user_id = state
                    .metastore
                    .user_ops()
                    .get_id_by_did(&did)
                    .map_err(metastore_to_db)?;
                match user_id {
                    Some(uid) => state
                        .metastore
                        .infra_ops()
                        .count_plc_tokens_for_user(uid)
                        .map_err(metastore_to_db),
                    None => Ok(0),
                }
            })();
            let _ = tx.send(result);
        }
    }
}

fn dispatch_oauth<S: StorageIO>(state: &HandlerState<S>, req: OAuthRequest) {
    match req {
        OAuthRequest::CreateToken { data, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .create_token(&data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetTokenById { token_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_token_by_id(&token_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetTokenByRefreshToken { refresh_token, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_token_by_refresh_token(&refresh_token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetTokenByPreviousRefreshToken { refresh_token, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_token_by_previous_refresh_token(&refresh_token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::RotateToken {
            old_db_id,
            new_refresh_token,
            new_expires_at,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .rotate_token(old_db_id, &new_refresh_token, new_expires_at)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CheckRefreshTokenUsed { refresh_token, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .check_refresh_token_used(&refresh_token)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteToken { token_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_token(&token_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteTokenFamily { db_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_token_family(db_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ListTokensForUser { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .list_tokens_for_user(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CountTokensForUser { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .count_tokens_for_user(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteOldestTokensForUser {
            did,
            keep_count,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_oldest_tokens_for_user(&did, keep_count)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::RevokeTokensForClient { did, client_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .revoke_tokens_for_client(&did, &client_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::RevokeTokensForController {
            delegated_did,
            controller_did,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .revoke_tokens_for_controller(&delegated_did, &controller_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CreateAuthorizationRequest {
            request_id,
            data,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .create_authorization_request(&request_id, &data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetAuthorizationRequest { request_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_authorization_request(&request_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::SetAuthorizationDid {
            request_id,
            did,
            device_id,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .set_authorization_did(&request_id, &did, device_id.as_ref())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpdateAuthorizationRequest {
            request_id,
            did,
            device_id,
            code,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .update_authorization_request(&request_id, &did, device_id.as_ref(), &code)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ConsumeAuthorizationRequestByCode { code, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .consume_authorization_request_by_code(&code)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteAuthorizationRequest { request_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_authorization_request(&request_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteExpiredAuthorizationRequests { tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_expired_authorization_requests()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ExtendAuthorizationRequestExpiry {
            request_id,
            new_expires_at,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .extend_authorization_request_expiry(&request_id, new_expires_at)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::MarkRequestAuthenticated {
            request_id,
            did,
            device_id,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .mark_request_authenticated(&request_id, &did, device_id.as_ref())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpdateRequestScope {
            request_id,
            scope,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .update_request_scope(&request_id, &scope)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::SetControllerDid {
            request_id,
            controller_did,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .set_controller_did(&request_id, &controller_did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::SetRequestDid {
            request_id,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .set_request_did(&request_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CreateDevice {
            device_id,
            data,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .create_device(&device_id, &data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetDevice { device_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_device(&device_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpdateDeviceLastSeen { device_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .update_device_last_seen(&device_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteDevice { device_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_device(&device_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpsertAccountDevice { did, device_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .upsert_account_device(&did, &device_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetDeviceAccounts { device_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_device_accounts(&device_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::VerifyAccountOnDevice { device_id, did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .verify_account_on_device(&device_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CheckAndRecordDpopJti { jti, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .check_and_record_dpop_jti(&jti)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CleanupExpiredDpopJtis { max_age_secs, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .cleanup_expired_dpop_jtis(max_age_secs)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Create2faChallenge {
            did,
            request_uri,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .create_2fa_challenge(&did, &request_uri)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Get2faChallenge { request_uri, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_2fa_challenge(&request_uri)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Increment2faAttempts { id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .increment_2fa_attempts(id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Delete2faChallenge { id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_2fa_challenge(id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Delete2faChallengeByRequestUri { request_uri, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_2fa_challenge_by_request_uri(&request_uri)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CleanupExpired2faChallenges { tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .cleanup_expired_2fa_challenges()
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::CheckUser2faEnabled { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .check_user_2fa_enabled(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetScopePreferences { did, client_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_scope_preferences(&did, &client_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpsertScopePreferences {
            did,
            client_id,
            prefs,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .upsert_scope_preferences(&did, &client_id, &prefs)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteScopePreferences { did, client_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_scope_preferences(&did, &client_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpsertAuthorizedClient {
            did,
            client_id,
            data,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .upsert_authorized_client(&did, &client_id, &data)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetAuthorizedClient { did, client_id, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_authorized_client(&did, &client_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ListTrustedDevices { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .list_trusted_devices(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::GetDeviceTrustInfo { device_id, did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_device_trust_info(&device_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeviceBelongsToUser { device_id, did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .device_belongs_to_user(&device_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::RevokeDeviceTrust { device_id, did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .revoke_device_trust(&device_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::UpdateDeviceFriendlyName {
            device_id,
            did,
            friendly_name,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .update_device_friendly_name(&device_id, &did, friendly_name.as_deref())
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::TrustDevice {
            device_id,
            did,
            trusted_at,
            trusted_until,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .trust_device(&device_id, &did, trusted_at, trusted_until)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ExtendDeviceTrust {
            device_id,
            did,
            trusted_until,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .extend_device_trust(&device_id, &did, trusted_until)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::ListSessionsByDid { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .list_sessions_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteSessionById {
            session_id,
            did,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_session_by_id(session_id, &did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteSessionsByDid { did, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_sessions_by_did(&did)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::DeleteSessionsByDidExcept {
            did,
            except_token_id,
            tx,
        } => {
            let result = state
                .metastore
                .oauth_ops()
                .delete_sessions_by_did_except(&did, &except_token_id)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        OAuthRequest::Get2faChallengeCode { request_uri, tx } => {
            let result = state
                .metastore
                .oauth_ops()
                .get_2fa_challenge_code(&request_uri)
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
    }
}

fn dispatch<S: StorageIO + 'static>(state: &HandlerState<S>, request: MetastoreRequest) {
    match request {
        MetastoreRequest::Repo(r) => dispatch_repo(state, r),
        MetastoreRequest::Record(r) => dispatch_record(state, r),
        MetastoreRequest::UserBlock(r) => dispatch_user_block(state, r),
        MetastoreRequest::Event(r) => dispatch_event(state, r),
        MetastoreRequest::Commit(r) => dispatch_commit(state, *r),
        MetastoreRequest::Backlink(r) => dispatch_backlink(state, r),
        MetastoreRequest::Blob(r) => dispatch_blob(state, r),
        MetastoreRequest::Delegation(r) => dispatch_delegation(state, r),
        MetastoreRequest::Sso(r) => dispatch_sso(state, r),
        MetastoreRequest::Session(r) => dispatch_session(state, r),
        MetastoreRequest::Infra(r) => dispatch_infra(state, r),
        MetastoreRequest::OAuth(r) => dispatch_oauth(state, r),
        MetastoreRequest::User(r) => dispatch_user(state, r),
    }
}

fn purge_repo_side_data<S: StorageIO + 'static>(
    state: &HandlerState<S>,
    user_id: Uuid,
    did: &Did,
) -> Result<(), MetastoreError> {
    let _ = state.metastore.blob_ops().delete_blobs_by_user(user_id)?;
    let mut batch = state.metastore.database().batch();
    state
        .metastore
        .backlink_ops()
        .remove_backlinks_by_repo(&mut batch, UserHash::from_did(did.as_str()))?;
    batch.commit().map_err(MetastoreError::Fjall)
}

fn dispatch_user<S: StorageIO + 'static>(state: &HandlerState<S>, req: UserRequest) {
    let user = state.metastore.user_ops();
    match req {
        UserRequest::GetByDid { did, tx } => {
            let _ = tx.send(user.get_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetByHandle { handle, tx } => {
            let _ = tx.send(user.get_by_handle(&handle).map_err(metastore_to_db));
        }
        UserRequest::GetWithKeyByDid { did, tx } => {
            let _ = tx.send(user.get_with_key_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetStatusByDid { did, tx } => {
            let _ = tx.send(user.get_status_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::CountUsers { tx } => {
            let _ = tx.send(user.count_users().map_err(metastore_to_db));
        }
        UserRequest::GetSessionAccessExpiry {
            did,
            access_jti,
            tx,
        } => {
            let _ = tx.send(
                user.get_session_access_expiry(&did, &access_jti)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetOAuthTokenWithUser { token_id, tx } => {
            let _ = tx.send(
                user.get_oauth_token_with_user(&token_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserInfoByDid { did, tx } => {
            let _ = tx.send(user.get_user_info_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetAnyAdminUserId { tx } => {
            let _ = tx.send(user.get_any_admin_user_id().map_err(metastore_to_db));
        }
        UserRequest::SetInvitesDisabled { did, disabled, tx } => {
            let _ = tx.send(
                user.set_invites_disabled(&did, disabled)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SearchAccounts {
            cursor_did,
            email_filter,
            handle_filter,
            limit,
            tx,
        } => {
            let _ = tx.send(
                user.search_accounts(
                    cursor_did.as_ref(),
                    email_filter.as_deref(),
                    handle_filter.as_deref(),
                    limit,
                )
                .map_err(metastore_to_db),
            );
        }
        UserRequest::GetAuthInfoByDid { did, tx } => {
            let _ = tx.send(user.get_auth_info_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetByEmail { email, tx } => {
            let _ = tx.send(user.get_by_email(&email).map_err(metastore_to_db));
        }
        UserRequest::GetLoginCheckByIdentifier { identifier, tx } => {
            let _ = tx.send(
                user.get_login_check_by_identifier(&identifier)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetLoginInfoByIdentifier { identifier, tx } => {
            let _ = tx.send(
                user.get_login_info_by_identifier(&identifier)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::Get2faStatusByDid { did, tx } => {
            let _ = tx.send(user.get_2fa_status_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetCommsPrefs { user_id, tx } => {
            let _ = tx.send(user.get_comms_prefs(user_id).map_err(metastore_to_db));
        }
        UserRequest::GetIdByDid { did, tx } => {
            let _ = tx.send(user.get_id_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetUserKeyById { user_id, tx } => {
            let _ = tx.send(user.get_user_key_by_id(user_id).map_err(metastore_to_db));
        }
        UserRequest::GetIdAndHandleByDid { did, tx } => {
            let _ = tx.send(user.get_id_and_handle_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetDidWebInfoByHandle { handle, tx } => {
            let _ = tx.send(
                user.get_did_web_info_by_handle(&handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetDidWebOverrides { user_id, tx } => {
            let _ = tx.send(user.get_did_web_overrides(user_id).map_err(metastore_to_db));
        }
        UserRequest::GetHandleByDid { did, tx } => {
            let _ = tx.send(user.get_handle_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::IsAccountActiveByDid { did, tx } => {
            let _ = tx.send(user.is_account_active_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetUserForDeletion { did, tx } => {
            let _ = tx.send(user.get_user_for_deletion(&did).map_err(metastore_to_db));
        }
        UserRequest::CheckHandleExists {
            handle,
            exclude_user_id,
            tx,
        } => {
            let _ = tx.send(
                user.check_handle_exists(&handle, exclude_user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdateHandle {
            user_id,
            handle,
            tx,
        } => {
            let _ = tx.send(
                user.update_handle(user_id, &handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserWithKeyByDid { did, tx } => {
            let _ = tx.send(user.get_user_with_key_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::IsAccountMigrated { did, tx } => {
            let _ = tx.send(user.is_account_migrated(&did).map_err(metastore_to_db));
        }
        UserRequest::HasVerifiedCommsChannel { did, tx } => {
            let _ = tx.send(
                user.has_verified_comms_channel(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetIdByHandle { handle, tx } => {
            let _ = tx.send(user.get_id_by_handle(&handle).map_err(metastore_to_db));
        }
        UserRequest::GetEmailInfoByDid { did, tx } => {
            let _ = tx.send(user.get_email_info_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::CheckEmailExists {
            email,
            exclude_user_id,
            tx,
        } => {
            let _ = tx.send(
                user.check_email_exists(&email, exclude_user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdateEmail { user_id, email, tx } => {
            let _ = tx.send(user.update_email(user_id, &email).map_err(metastore_to_db));
        }
        UserRequest::SetEmailVerified {
            user_id,
            verified,
            tx,
        } => {
            let _ = tx.send(
                user.set_email_verified(user_id, verified)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::CheckEmailVerifiedByIdentifier { identifier, tx } => {
            let _ = tx.send(
                user.check_email_verified_by_identifier(&identifier)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::CheckChannelVerifiedByDid { did, channel, tx } => {
            let _ = tx.send(
                user.check_channel_verified_by_did(&did, channel)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::AdminUpdateEmail { did, email, tx } => {
            let _ = tx.send(
                user.admin_update_email(&did, &email)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::AdminUpdateHandle { did, handle, tx } => {
            let _ = tx.send(
                user.admin_update_handle(&did, &handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::AdminUpdatePassword {
            did,
            password_hash,
            tx,
        } => {
            let _ = tx.send(
                user.admin_update_password(&did, &password_hash)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetAdminStatus { did, is_admin, tx } => {
            let _ = tx.send(
                user.set_admin_status(&did, is_admin)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetNotificationPrefs { did, tx } => {
            let _ = tx.send(user.get_notification_prefs(&did).map_err(metastore_to_db));
        }
        UserRequest::GetIdHandleEmailByDid { did, tx } => {
            let _ = tx.send(
                user.get_id_handle_email_by_did(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdatePreferredCommsChannel { did, channel, tx } => {
            let _ = tx.send(
                user.update_preferred_comms_channel(&did, channel)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ClearDiscord { user_id, tx } => {
            let _ = tx.send(user.clear_discord(user_id).map_err(metastore_to_db));
        }
        UserRequest::ClearTelegram { user_id, tx } => {
            let _ = tx.send(user.clear_telegram(user_id).map_err(metastore_to_db));
        }
        UserRequest::ClearSignal { user_id, tx } => {
            let _ = tx.send(user.clear_signal(user_id).map_err(metastore_to_db));
        }
        UserRequest::SetUnverifiedSignal {
            user_id,
            signal_username,
            tx,
        } => {
            let _ = tx.send(
                user.set_unverified_signal(user_id, &signal_username)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetUnverifiedTelegram {
            user_id,
            telegram_username,
            tx,
        } => {
            let _ = tx.send(
                user.set_unverified_telegram(user_id, &telegram_username)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::StoreTelegramChatId {
            telegram_username,
            chat_id,
            handle,
            tx,
        } => {
            let _ = tx.send(
                user.store_telegram_chat_id(&telegram_username, chat_id, handle.as_deref())
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetTelegramChatId { user_id, tx } => {
            let _ = tx.send(user.get_telegram_chat_id(user_id).map_err(metastore_to_db));
        }
        UserRequest::SetUnverifiedDiscord {
            user_id,
            discord_username,
            tx,
        } => {
            let _ = tx.send(
                user.set_unverified_discord(user_id, &discord_username)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::StoreDiscordUserId {
            discord_username,
            discord_id,
            handle,
            tx,
        } => {
            let _ = tx.send(
                user.store_discord_user_id(&discord_username, &discord_id, handle.as_deref())
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetVerificationInfo { did, tx } => {
            let _ = tx.send(user.get_verification_info(&did).map_err(metastore_to_db));
        }
        UserRequest::VerifyEmailChannel { user_id, email, tx } => {
            let _ = tx.send(
                user.verify_email_channel(user_id, &email)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::VerifyDiscordChannel {
            user_id,
            discord_id,
            tx,
        } => {
            let _ = tx.send(
                user.verify_discord_channel(user_id, &discord_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::VerifyTelegramChannel {
            user_id,
            telegram_username,
            tx,
        } => {
            let _ = tx.send(
                user.verify_telegram_channel(user_id, &telegram_username)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::VerifySignalChannel {
            user_id,
            signal_username,
            tx,
        } => {
            let _ = tx.send(
                user.verify_signal_channel(user_id, &signal_username)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetEmailVerifiedFlag { user_id, tx } => {
            let _ = tx.send(
                user.set_email_verified_flag(user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetDiscordVerifiedFlag { user_id, tx } => {
            let _ = tx.send(
                user.set_discord_verified_flag(user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetTelegramVerifiedFlag { user_id, tx } => {
            let _ = tx.send(
                user.set_telegram_verified_flag(user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetSignalVerifiedFlag { user_id, tx } => {
            let _ = tx.send(
                user.set_signal_verified_flag(user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::HasTotpEnabled { did, tx } => {
            let _ = tx.send(user.has_totp_enabled(&did).map_err(metastore_to_db));
        }
        UserRequest::HasPasskeys { did, tx } => {
            let _ = tx.send(user.has_passkeys(&did).map_err(metastore_to_db));
        }
        UserRequest::GetPasswordHashByDid { did, tx } => {
            let _ = tx.send(user.get_password_hash_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetPasskeysForUser { did, tx } => {
            let _ = tx.send(user.get_passkeys_for_user(&did).map_err(metastore_to_db));
        }
        UserRequest::GetPasskeyByCredentialId { credential_id, tx } => {
            let _ = tx.send(
                user.get_passkey_by_credential_id(&credential_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SavePasskey {
            did,
            credential_id,
            public_key,
            friendly_name,
            tx,
        } => {
            let _ = tx.send(
                user.save_passkey(&did, &credential_id, &public_key, friendly_name.as_deref())
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdatePasskeyCounter {
            credential_id,
            new_counter,
            tx,
        } => {
            let _ = tx.send(
                user.update_passkey_counter(&credential_id, new_counter)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeletePasskey { id, did, tx } => {
            let _ = tx.send(user.delete_passkey(id, &did).map_err(metastore_to_db));
        }
        UserRequest::UpdatePasskeyName { id, did, name, tx } => {
            let _ = tx.send(
                user.update_passkey_name(id, &did, &name)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SaveWebauthnChallenge {
            did,
            challenge_type,
            state_json,
            tx,
        } => {
            let _ = tx.send(
                user.save_webauthn_challenge(&did, challenge_type, &state_json)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::LoadWebauthnChallenge {
            did,
            challenge_type,
            tx,
        } => {
            let _ = tx.send(
                user.load_webauthn_challenge(&did, challenge_type)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeleteWebauthnChallenge {
            did,
            challenge_type,
            tx,
        } => {
            let _ = tx.send(
                user.delete_webauthn_challenge(&did, challenge_type)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SaveDiscoverableChallenge {
            request_key,
            state_json,
            tx,
        } => {
            let _ = tx.send(
                user.save_discoverable_challenge(&request_key, &state_json)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::LoadDiscoverableChallenge { request_key, tx } => {
            let _ = tx.send(
                user.load_discoverable_challenge(&request_key)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeleteDiscoverableChallenge { request_key, tx } => {
            let _ = tx.send(
                user.delete_discoverable_challenge(&request_key)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetTotpRecord { did, tx } => {
            let _ = tx.send(user.get_totp_record(&did).map_err(metastore_to_db));
        }
        UserRequest::GetTotpRecordState { did, tx } => {
            let _ = tx.send(user.get_totp_record_state(&did).map_err(metastore_to_db));
        }
        UserRequest::UpsertTotpSecret {
            did,
            secret_encrypted,
            encryption_version,
            tx,
        } => {
            let _ = tx.send(
                user.upsert_totp_secret(&did, &secret_encrypted, encryption_version)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetTotpVerified { did, tx } => {
            let _ = tx.send(user.set_totp_verified(&did).map_err(metastore_to_db));
        }
        UserRequest::UpdateTotpLastUsed { did, tx } => {
            let _ = tx.send(user.update_totp_last_used(&did).map_err(metastore_to_db));
        }
        UserRequest::DeleteTotp { did, tx } => {
            let _ = tx.send(user.delete_totp(&did).map_err(metastore_to_db));
        }
        UserRequest::GetUnusedBackupCodes { did, tx } => {
            let _ = tx.send(user.get_unused_backup_codes(&did).map_err(metastore_to_db));
        }
        UserRequest::MarkBackupCodeUsed { code_id, tx } => {
            let _ = tx.send(user.mark_backup_code_used(code_id).map_err(metastore_to_db));
        }
        UserRequest::CountUnusedBackupCodes { did, tx } => {
            let _ = tx.send(
                user.count_unused_backup_codes(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeleteBackupCodes { did, tx } => {
            let _ = tx.send(user.delete_backup_codes(&did).map_err(metastore_to_db));
        }
        UserRequest::InsertBackupCodes {
            did,
            code_hashes,
            tx,
        } => {
            let _ = tx.send(
                user.insert_backup_codes(&did, &code_hashes)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::EnableTotpWithBackupCodes {
            did,
            code_hashes,
            tx,
        } => {
            let _ = tx.send(
                user.enable_totp_with_backup_codes(&did, &code_hashes)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeleteTotpAndBackupCodes { did, tx } => {
            let _ = tx.send(
                user.delete_totp_and_backup_codes(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ReplaceBackupCodes {
            did,
            code_hashes,
            tx,
        } => {
            let _ = tx.send(
                user.replace_backup_codes(&did, &code_hashes)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetSessionInfoByDid { did, tx } => {
            let _ = tx.send(user.get_session_info_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetLegacyLoginPref { did, tx } => {
            let _ = tx.send(user.get_legacy_login_pref(&did).map_err(metastore_to_db));
        }
        UserRequest::UpdateLegacyLogin { did, allow, tx } => {
            let _ = tx.send(
                user.update_legacy_login(&did, allow)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdateLocale { did, locale, tx } => {
            let _ = tx.send(user.update_locale(&did, &locale).map_err(metastore_to_db));
        }
        UserRequest::GetLoginFullByIdentifier { identifier, tx } => {
            let _ = tx.send(
                user.get_login_full_by_identifier(&identifier)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetConfirmSignupByDid { did, tx } => {
            let _ = tx.send(
                user.get_confirm_signup_by_did(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetResendVerificationByDid { did, tx } => {
            let _ = tx.send(
                user.get_resend_verification_by_did(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetChannelVerified { did, channel, tx } => {
            let _ = tx.send(
                user.set_channel_verified(&did, channel)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetIdByEmailOrHandle { email, handle, tx } => {
            let _ = tx.send(
                user.get_id_by_email_or_handle(&email, &handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::CountAccountsByEmail { email, tx } => {
            let _ = tx.send(
                user.count_accounts_by_email(&email)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetHandlesByEmail { email, tx } => {
            let _ = tx.send(user.get_handles_by_email(&email).map_err(metastore_to_db));
        }
        UserRequest::SetPasswordResetCode {
            user_id,
            code,
            expires_at,
            tx,
        } => {
            let _ = tx.send(
                user.set_password_reset_code(user_id, &code, expires_at)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserByResetCode { code, tx } => {
            let _ = tx.send(user.get_user_by_reset_code(&code).map_err(metastore_to_db));
        }
        UserRequest::ClearPasswordResetCode { user_id, tx } => {
            let _ = tx.send(
                user.clear_password_reset_code(user_id)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetIdAndPasswordHashByDid { did, tx } => {
            let _ = tx.send(
                user.get_id_and_password_hash_by_did(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdatePasswordHash {
            user_id,
            password_hash,
            tx,
        } => {
            let _ = tx.send(
                user.update_password_hash(user_id, &password_hash)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ResetPasswordWithSessions {
            user_id,
            password_hash,
            tx,
        } => {
            let _ = tx.send(
                user.reset_password_with_sessions(user_id, &password_hash)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ActivateAccount { did, tx } => {
            let _ = tx.send(user.activate_account(&did).map_err(metastore_to_db));
        }
        UserRequest::DeactivateAccount {
            did,
            delete_after,
            tx,
        } => {
            let _ = tx.send(
                user.deactivate_account(&did, delete_after)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::HasPasswordByDid { did, tx } => {
            let _ = tx.send(user.has_password_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::GetPasswordInfoByDid { did, tx } => {
            let _ = tx.send(user.get_password_info_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::RemoveUserPassword { user_id, tx } => {
            let _ = tx.send(user.remove_user_password(user_id).map_err(metastore_to_db));
        }
        UserRequest::SetNewUserPassword {
            user_id,
            password_hash,
            tx,
        } => {
            let _ = tx.send(
                user.set_new_user_password(user_id, &password_hash)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserKeyByDid { did, tx } => {
            let _ = tx.send(user.get_user_key_by_did(&did).map_err(metastore_to_db));
        }
        UserRequest::DeleteAccountComplete { user_id, did, tx } => {
            let result = purge_repo_side_data(state, user_id, &did)
                .and_then(|()| user.delete_account_complete(user_id, &did))
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        UserRequest::SetUserTakedown {
            did,
            takedown_ref,
            tx,
        } => {
            let _ = tx.send(
                user.set_user_takedown(&did, takedown_ref.as_deref())
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::AdminDeleteAccountComplete { user_id, did, tx } => {
            let result = purge_repo_side_data(state, user_id, &did)
                .and_then(|()| user.admin_delete_account_complete(user_id, &did))
                .map_err(metastore_to_db);
            let _ = tx.send(result);
        }
        UserRequest::GetUserForDidDoc { did, tx } => {
            let _ = tx.send(user.get_user_for_did_doc(&did).map_err(metastore_to_db));
        }
        UserRequest::GetUserForDidDocBuild { did, tx } => {
            let _ = tx.send(
                user.get_user_for_did_doc_build(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpsertDidWebOverrides {
            user_id,
            verification_methods,
            also_known_as,
            tx,
        } => {
            let _ = tx.send(
                user.upsert_did_web_overrides(user_id, verification_methods, also_known_as)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::UpdateMigratedToPds { did, endpoint, tx } => {
            let _ = tx.send(
                user.update_migrated_to_pds(&did, &endpoint)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserForPasskeySetup { did, tx } => {
            let _ = tx.send(
                user.get_user_for_passkey_setup(&did)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserForPasskeyRecovery {
            identifier,
            normalized_handle,
            tx,
        } => {
            let _ = tx.send(
                user.get_user_for_passkey_recovery(&identifier, &normalized_handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetRecoveryToken {
            did,
            token_hash,
            expires_at,
            tx,
        } => {
            let _ = tx.send(
                user.set_recovery_token(&did, &token_hash, expires_at)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetUserForRecovery { did, tx } => {
            let _ = tx.send(user.get_user_for_recovery(&did).map_err(metastore_to_db));
        }
        UserRequest::GetAccountsScheduledForDeletion { limit, tx } => {
            let _ = tx.send(
                user.get_accounts_scheduled_for_deletion(limit)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::DeleteAccountWithFirehose { user_id, did, tx } => {
            let result = user
                .delete_account_complete(user_id, &did)
                .map_err(metastore_to_db)
                .and_then(|()| {
                    state
                        .event_ops
                        .insert_account_event(&did, AccountStatus::Deleted)
                });
            let _ = tx.send(result.map(|_| ()));
        }
        UserRequest::CreatePasswordAccount { input, tx } => {
            let infra = state.metastore.infra_ops();
            let code = input.invite_code.as_ref();
            let result = reserve_invite(&infra, code).and_then(|()| {
                finalize_account(
                    &infra,
                    code,
                    user.create_password_account(&input),
                    |result| {
                        if let Some(key_id) = input.reserved_key_id {
                            infra
                                .mark_signing_key_used(key_id)
                                .map_err(|e| CreateAccountError::Database(e.to_string()))?;
                        }
                        Ok(result.user_id)
                    },
                )
            });
            let _ = tx.send(result);
        }
        UserRequest::CreateDelegatedAccount { input, tx } => {
            let result = user.create_delegated_account(&input).and_then(|account| {
                let scope =
                    tranquil_db_traits::DbScope::new(&input.controller_scopes).map_err(|e| {
                        tranquil_db_traits::CreateAccountError::Database(format!(
                            "invalid delegation scope: {e}"
                        ))
                    })?;
                state
                    .metastore
                    .delegation_ops()
                    .create_delegation(
                        &input.did,
                        &input.controller_did,
                        &scope,
                        &input.controller_did,
                    )
                    .map_err(|e| {
                        tranquil_db_traits::CreateAccountError::Database(format!(
                            "delegation grant creation failed: {e}"
                        ))
                    })?;
                Ok(account)
            });
            let _ = tx.send(result);
        }
        UserRequest::CreatePasskeyAccount { input, tx } => {
            let infra = state.metastore.infra_ops();
            let code = input.invite_code.as_ref();
            let result = reserve_invite(&infra, code).and_then(|()| {
                finalize_account(
                    &infra,
                    code,
                    user.create_passkey_account(&input),
                    |result| {
                        if let Some(key_id) = input.reserved_key_id {
                            infra
                                .mark_signing_key_used(key_id)
                                .map_err(|e| CreateAccountError::Database(e.to_string()))?;
                        }
                        Ok(result.user_id)
                    },
                )
            });
            let _ = tx.send(result);
        }
        UserRequest::CreateSsoAccount { input, tx } => {
            let sso_ops = state.metastore.sso_ops();
            let infra = state.metastore.infra_ops();
            let code = input.invite_code.as_ref();
            let result = sso_ops
                .consume_pending_registration(&input.pending_registration_token)
                .map_err(|e| CreateAccountError::Database(e.to_string()))
                .and_then(|consumed| match consumed {
                    Some(_) => reserve_invite(&infra, code).and_then(|()| {
                        finalize_account(&infra, code, user.create_sso_account(&input), |result| {
                            sso_ops
                                .create_external_identity(
                                    &input.did,
                                    input.sso_provider,
                                    &input.sso_provider_user_id,
                                    input.sso_provider_username.as_deref(),
                                    input.sso_provider_email.as_deref(),
                                )
                                .map_err(|e| CreateAccountError::Database(e.to_string()))?;
                            Ok(result.user_id)
                        })
                    }),
                    None => Err(CreateAccountError::InvalidToken),
                });
            let _ = tx.send(result);
        }
        UserRequest::ReactivateMigrationAccount { input, tx } => {
            let _ = tx.send(user.reactivate_migration_account(&input));
        }
        UserRequest::CheckHandleAvailableForNewAccount { handle, tx } => {
            let _ = tx.send(
                user.check_handle_available_for_new_account(&handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ReserveHandle {
            handle,
            reserved_by,
            tx,
        } => {
            let _ = tx.send(
                user.reserve_handle(&handle, &reserved_by)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ReleaseHandleReservation { handle, tx } => {
            let _ = tx.send(
                user.release_handle_reservation(&handle)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::CleanupExpiredHandleReservations { tx } => {
            let _ = tx.send(
                user.cleanup_expired_handle_reservations()
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::CompletePasskeySetup { input, tx } => {
            let _ = tx.send(user.complete_passkey_setup(&input).map_err(metastore_to_db));
        }
        UserRequest::RecoverPasskeyAccount { input, tx } => {
            let _ = tx.send(
                user.recover_passkey_account(&input)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::GetPasswordResetInfo { email, tx } => {
            let _ = tx.send(
                user.get_password_reset_info(&email)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::EnableTotpVerified {
            did,
            encrypted_secret,
            tx,
        } => {
            let _ = tx.send(
                user.enable_totp_verified(&did, &encrypted_secret)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::SetTwoFactorEnabled { did, enabled, tx } => {
            let _ = tx.send(
                user.set_two_factor_enabled(&did, enabled)
                    .map_err(metastore_to_db),
            );
        }
        UserRequest::ExpirePasswordResetCode { email, tx } => {
            let _ = tx.send(
                user.expire_password_reset_code(&email)
                    .map_err(metastore_to_db),
            );
        }
    }
}

fn handler_loop<S: StorageIO + 'static>(
    metastore: Metastore,
    bridge: Arc<EventLogBridge<S>>,
    blockstore: Option<TranquilBlockStore<RealIO, SystemClock>>,
    rx: flume::Receiver<MetastoreRequest>,
    thread_index: usize,
) {
    let event_ops = metastore.event_ops(Arc::clone(&bridge));
    let mut commit_ops = metastore.commit_ops(bridge);
    if let Some(bs) = blockstore {
        commit_ops = commit_ops.with_blockstore(bs);
    }
    let state = HandlerState {
        metastore,
        event_ops,
        commit_ops,
    };
    tracing::info!(thread_index, "metastore handler thread started");
    rx.iter().for_each(|req| {
        match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| dispatch(&state, req))) {
            Ok(()) => {}
            Err(e) => {
                let msg = match e.downcast_ref::<&str>() {
                    Some(s) => (*s).to_owned(),
                    None => match e.downcast_ref::<String>() {
                        Some(s) => s.clone(),
                        None => "unknown panic payload".to_owned(),
                    },
                };
                tracing::error!(thread_index, msg, "recovered metastore handler panic");
            }
        }
    });
    tracing::info!(thread_index, "metastore handler thread exiting");
}

const DEFAULT_CHANNEL_BOUND: usize = 256;
const MAX_REPOS_WITHOUT_REV: usize = 10_000;

pub struct HandlerPool {
    senders: parking_lot::Mutex<Vec<flume::Sender<MetastoreRequest>>>,
    handles: parking_lot::Mutex<Option<Vec<JoinHandle<()>>>>,
    sender_count: usize,
    user_hashes: Arc<UserHashMap>,
    round_robin: AtomicUsize,
}

impl HandlerPool {
    pub fn spawn<S: StorageIO + 'static>(
        metastore: Metastore,
        bridge: Arc<EventLogBridge<S>>,
        blockstore: Option<TranquilBlockStore<RealIO, SystemClock>>,
        thread_count: Option<usize>,
    ) -> Self {
        let count = thread_count
            .unwrap_or_else(|| {
                std::thread::available_parallelism()
                    .map(|n| n.get().max(2) / 2)
                    .unwrap_or(1)
            })
            .max(1);

        let user_hashes = Arc::clone(metastore.user_hashes());

        let (senders, handles): (Vec<_>, Vec<_>) = (0..count)
            .map(|i| {
                let (tx, rx) = flume::bounded(DEFAULT_CHANNEL_BOUND);
                let ms = metastore.clone();
                let br = Arc::clone(&bridge);
                let bs = blockstore.clone();
                let handle = std::thread::Builder::new()
                    .name(format!("metastore-{i}"))
                    .spawn(move || handler_loop(ms, br, bs, rx, i))
                    .expect("failed to spawn metastore handler thread");
                (tx, handle)
            })
            .unzip();

        Self {
            sender_count: senders.len(),
            senders: parking_lot::Mutex::new(senders),
            handles: parking_lot::Mutex::new(Some(handles)),
            user_hashes,
            round_robin: AtomicUsize::new(0),
        }
    }

    pub fn send(&self, request: MetastoreRequest) -> Result<(), DbError> {
        let senders = self.senders.lock();
        if senders.is_empty() {
            return Err(DbError::Connection(
                "metastore handler pool shut down".to_string(),
            ));
        }
        let index = match request.routing(&self.user_hashes) {
            Routing::Sharded(bits) => (bits as usize) % senders.len(),
            Routing::Global => self.round_robin.fetch_add(1, Ordering::Relaxed) % senders.len(),
        };
        senders[index].try_send(request).map_err(|e| match e {
            flume::TrySendError::Full(_) => {
                DbError::Query("metastore handler backpressure".to_string())
            }
            flume::TrySendError::Disconnected(_) => {
                DbError::Connection("metastore handler pool shut down".to_string())
            }
        })
    }

    pub fn thread_count(&self) -> usize {
        self.sender_count
    }

    pub async fn close(&self) {
        {
            self.senders.lock().clear();
        }
        let handles = { self.handles.lock().take() };
        if let Some(handles) = handles {
            let join_fut = tokio::task::spawn_blocking(move || {
                handles.into_iter().for_each(|h| {
                    if let Err(e) = h.join() {
                        tracing::error!("metastore handler thread panicked: {e:?}");
                    }
                });
            });
            match tokio::time::timeout(std::time::Duration::from_secs(30), join_fut).await {
                Ok(_) => tracing::info!("metastore handler threads shut down cleanly"),
                Err(_) => tracing::error!("metastore handler thread shutdown timed out after 30s"),
            }
        }
    }
}

impl Drop for HandlerPool {
    fn drop(&mut self) {
        self.senders.get_mut().clear();
        if let Some(handles) = self.handles.get_mut().take() {
            tracing::warn!(
                "HandlerPool dropped without calling shutdown(); blocking on thread join"
            );
            handles.into_iter().for_each(|h| {
                if let Err(e) = h.join() {
                    tracing::error!("metastore handler thread panicked: {e:?}");
                }
            });
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::eventlog::{EventLog, EventLogConfig};
    use crate::metastore::MetastoreConfig;
    use tranquil_types::{Did, Handle, InviteCode, Jti};

    struct TestHarness {
        _metastore_dir: tempfile::TempDir,
        _eventlog_dir: tempfile::TempDir,
        pool: HandlerPool,
    }

    fn setup() -> TestHarness {
        let metastore_dir = tempfile::TempDir::new().unwrap();
        let eventlog_dir = tempfile::TempDir::new().unwrap();
        let segments_dir = eventlog_dir.path().join("segments");
        std::fs::create_dir_all(&segments_dir).unwrap();

        let metastore = Metastore::open(
            metastore_dir.path(),
            MetastoreConfig {
                cache_size_bytes: 64 * 1024 * 1024,
            },
        )
        .unwrap();

        let event_log = EventLog::open(
            EventLogConfig {
                segments_dir,
                ..EventLogConfig::default()
            },
            RealIO::new(),
        )
        .unwrap();

        let bridge = Arc::new(EventLogBridge::new(Arc::new(event_log)));

        let pool = HandlerPool::spawn::<RealIO>(metastore, bridge, None, Some(2));

        TestHarness {
            _metastore_dir: metastore_dir,
            _eventlog_dir: eventlog_dir,
            pool,
        }
    }

    fn test_cid_link(seed: u8) -> CidLink {
        let digest: [u8; 32] = std::array::from_fn(|i| seed.wrapping_add(i as u8));
        let mh = multihash::Multihash::<64>::wrap(0x12, &digest).unwrap();
        let c = cid::Cid::new_v1(0x71, mh);
        CidLink::from_cid(&c)
    }

    fn test_rev(seq: u64) -> Tid {
        const ALPHABET: &[u8] = b"234567abcdefghijklmnopqrstuvwxyz";
        let s: String = (0..13)
            .rev()
            .map(|i| ALPHABET[((seq >> (i * 5)) & 0x1F) as usize] as char)
            .collect();
        Tid::new(s).expect("generated TID is valid")
    }

    #[tokio::test]
    async fn create_and_get_roundtrip() {
        let h = setup();
        let user_id = Uuid::new_v4();
        let did = Did::new("did:plc:whelk").expect("test DID is well-formed");
        let handle = Handle::new("whelk.oyster.cafe").expect("test handle is valid");
        let cid = test_cid_link(1);
        let rev = test_rev(1);

        let (tx, rx) = oneshot::channel();
        h.pool
            .send(MetastoreRequest::Repo(RepoRequest::CreateRepoFull {
                user_id,
                did,
                handle,
                repo_root_cid: cid.clone(),
                repo_rev: rev.clone(),
                tx,
            }))
            .unwrap();
        rx.await.unwrap().unwrap();

        let (tx, rx) = oneshot::channel();
        h.pool
            .send(MetastoreRequest::Repo(RepoRequest::GetRepo { user_id, tx }))
            .unwrap();
        let repo = rx.await.unwrap().unwrap().unwrap();
        assert_eq!(repo.repo_root_cid, cid);
        assert_eq!(repo.repo_rev.as_deref(), Some(rev.as_str()));
    }

    #[test]
    fn reserve_invite_code_consumes_once_and_guards_exhaustion() {
        let dir = tempfile::TempDir::new().unwrap();
        let metastore = Metastore::open(
            dir.path(),
            MetastoreConfig {
                cache_size_bytes: 64 * 1024 * 1024,
            },
        )
        .unwrap();
        let infra = metastore.infra_ops();
        let squid = InviteCode::new("squid-invite");
        let owner = Did::new("did:plc:whelk").expect("valid DID");
        let whelk = InviteCode::new("whelk");

        assert!(infra.create_invite_code(&squid, 1, &owner).unwrap());

        infra.reserve_invite_code(&squid).unwrap();
        assert_eq!(
            infra.get_invite_code_available_uses(&squid).unwrap(),
            Some(0)
        );

        assert!(matches!(
            infra.reserve_invite_code(&squid),
            Err(InviteCodeError::ExhaustedUses)
        ));
        assert_eq!(
            infra.get_invite_code_available_uses(&squid).unwrap(),
            Some(0),
            "a rejected reservation must not decrement below zero"
        );

        assert!(matches!(
            infra.reserve_invite_code(&whelk),
            Err(InviteCodeError::NotFound)
        ));
    }

    #[test]
    fn refund_invite_code_restores_a_reserved_use() {
        let dir = tempfile::TempDir::new().unwrap();
        let metastore = Metastore::open(
            dir.path(),
            MetastoreConfig {
                cache_size_bytes: 64 * 1024 * 1024,
            },
        )
        .unwrap();
        let infra = metastore.infra_ops();
        let squid = InviteCode::new("squid-invite");
        let owner = Did::new("did:plc:whelk").expect("valid DID");
        let whelk = InviteCode::new("whelk");

        assert!(infra.create_invite_code(&squid, 1, &owner).unwrap());

        infra.reserve_invite_code(&squid).unwrap();
        infra.refund_invite_code(&squid).unwrap();
        assert_eq!(
            infra.get_invite_code_available_uses(&squid).unwrap(),
            Some(1),
            "refund must return the reserved use so a failed signup does not burn it"
        );

        infra.reserve_invite_code(&squid).unwrap();
        assert_eq!(
            infra.get_invite_code_available_uses(&squid).unwrap(),
            Some(0)
        );

        assert!(matches!(
            infra.refund_invite_code(&whelk),
            Err(InviteCodeError::NotFound)
        ));
    }

    #[test]
    fn routing_determinism() {
        let user_id = Uuid::from_u128(0x12345678);
        let bits = user_id.as_u128() as u64;
        let thread_count = 4usize;
        let expected = (bits as usize) % thread_count;
        (0..100).for_each(|_| {
            assert_eq!((bits as usize) % thread_count, expected);
        });
    }

    #[test]
    fn global_round_robin_distributes() {
        let counter = AtomicUsize::new(0);
        let thread_count = 4usize;
        let indices: Vec<usize> = (0..8)
            .map(|_| counter.fetch_add(1, Ordering::Relaxed) % thread_count)
            .collect();
        assert_eq!(indices, vec![0, 1, 2, 3, 0, 1, 2, 3]);
    }

    #[test]
    fn session_mutations_route_by_did() {
        let dir = tempfile::TempDir::new().unwrap();
        let ms = Metastore::open(
            dir.path(),
            MetastoreConfig {
                cache_size_bytes: 1024 * 1024,
            },
        )
        .unwrap();
        let user_hashes = ms.user_hashes().as_ref();
        let did = Did::new("did:plc:limpet").expect("test DID is well-formed");
        let expected = did_to_routing(&did);
        let sid = SessionId::new(7);

        let (tx, _rx) = oneshot::channel();
        let delete_by_id = SessionRequest::DeleteSessionById {
            session_id: sid,
            did: did.clone(),
            tx,
        };
        let (tx, _rx) = oneshot::channel();
        let delete_by_jti = SessionRequest::DeleteSessionByAccessJti {
            access_jti: "a".to_string(),
            did: did.clone(),
            tx,
        };
        let (tx, _rx) = oneshot::channel();
        let delete_by_did = SessionRequest::DeleteSessionsByDid {
            did: did.clone(),
            tx,
        };
        let (tx, _rx) = oneshot::channel();
        let refresh = SessionRequest::RefreshSessionAtomic {
            data: tranquil_db_traits::SessionRefreshData {
                did: did.clone(),
                old_refresh_jti: Jti::new("r0"),
                session_id: sid,
                new_access_jti: Jti::new("a1"),
                new_refresh_jti: Jti::new("r1"),
                new_access_expires_at: Utc::now(),
                new_refresh_expires_at: Utc::now(),
            },
            tx,
        };

        assert_eq!(delete_by_id.routing(user_hashes), expected);
        assert_eq!(delete_by_jti.routing(user_hashes), expected);
        assert_eq!(delete_by_did.routing(user_hashes), expected);
        assert_eq!(refresh.routing(user_hashes), expected);
    }

    #[tokio::test]
    async fn shutdown_completes_inflight() {
        let h = setup();
        let user_id = Uuid::new_v4();
        let did = Did::new("did:plc:scallop").expect("test DID is well-formed");
        let handle = Handle::new("scallop.oyster.cafe").expect("test handle is valid");
        let cid = test_cid_link(2);

        let (tx, rx) = oneshot::channel();
        h.pool
            .send(MetastoreRequest::Repo(RepoRequest::CreateRepoFull {
                user_id,
                did,
                handle,
                repo_root_cid: cid,
                repo_rev: test_rev(1),
                tx,
            }))
            .unwrap();
        rx.await.unwrap().unwrap();

        h.pool.close().await;
    }
}
