AWS SDK

AWS SDK

rev. 01140188efe3be26ec6653bc30094c80ed1a1b99

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-http-client/src/client/pool/admission/delivery.rs

@@ -1,1 +536,575 @@
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
//! One-to-one acquisition payload delivery across admission and cell locks.
    7      7   
//!
    8      8   
//! Admission reserves one demand generation and moves either bounded capacity
    9      9   
//! or a provisional HTTP/1 sender into a [`DeliveryGuard`]. The guard
   10     10   
//! commits any connection cell transition before taking the requesting
   11     11   
//! cell lock, then owns the payload until that cell accepts it. Its
   12         -
//! acknowledgement keeps the demand fence installed until requesting-cell
          12  +
//! settlement keeps the demand assignment installed until requesting-cell
   13     13   
//! state is authoritative.
   14     14   
   15         -
use super::reuse::{H1AvailabilityOutcome, ReuseCandidate, ReuseId};
          15  +
use super::h1::{H1Candidate, H1MatchId, H1SupplyOutcome};
   16     16   
use super::{
   17         -
    AdmissionAction, DeliveryAckResult, DeliveryId, DemandId, DemandSnapshot, OriginAdmission,
   18         -
    Permit,
          17  +
    AdmissionAction, CapacityLease, CapacityPermit, DemandAssignment, DemandAssignmentOutcome,
          18  +
    DemandId, DemandSnapshot, OriginAdmission,
   19     19   
};
   20         -
use crate::client::pool::cell::h1::H1Selection;
   21     20   
use crate::client::pool::cell::{
   22         -
    AcquisitionEvent, AcquisitionResult, EstablishmentPermit, OriginCell,
          21  +
    AcquisitionOutcome, AcquisitionStep, EstablishmentPermit, OriginCell,
   23     22   
};
   24     23   
use crate::client::pool::partition::PartitionId;
   25     24   
use crate::sync::Arc;
   26     25   
use aws_smithy_runtime_api::client::connection::ConnectionId;
   27     26   
use std::fmt;
   28     27   
   29     28   
/// Capacity or a borrowed HTTP/1 sender crossing to waiting demand.
   30         -
enum AcquisitionPayload {
          29  +
enum DeliveryPayload {
   31     30   
    /// Permit removed from admission but not yet represented by a lease.
   32         -
    Capacity(Permit),
          31  +
    Capacity(CapacityPermit),
   33     32   
    /// Provisional sender whose owning-cell reservation must revalidate.
   34     33   
    BorrowedH1 {
   35         -
        /// Reuse operation that selected this sender.
   36         -
        reuse_id: ReuseId,
          34  +
        /// Retained H1 match that selected this sender.
          35  +
        match_id: H1MatchId,
   37     36   
        /// Cell that owns the sender and local reservation.
   38         -
        connection_partition: PartitionId,
          37  +
        supplier: PartitionId,
   39     38   
        /// Sender owner with cancellation fallback.
   40         -
        candidate: ReuseCandidate,
          39  +
        candidate: H1Candidate,
   41     40   
    },
   42     41   
}
   43     42   
   44         -
/// Payload after every connection cell-side fallible transition has completed.
   45         -
enum MaterializedPayload {
   46         -
    /// Establishment authority ready to move into the requesting cell.
   47         -
    Capacity(EstablishmentPermit),
   48         -
    /// Selected sender ready to move into the requesting cell.
   49         -
    BorrowedH1 {
   50         -
        /// Reuse operation that selected this sender.
   51         -
        reuse_id: ReuseId,
   52         -
        /// Cell that owns the installed connection record.
   53         -
        connection_partition: PartitionId,
   54         -
        /// Dispatch-ready sender ownership.
   55         -
        selection: H1Selection,
   56         -
    },
   57         -
}
   58         -
   59         -
/// One acquisition payload and its admission-owned delivery fence.
          43  +
/// One acquisition payload and its admission-owned demand assignment.
   60     44   
///
   61     45   
/// Dropping an undelivered guard refunnels its payload before making the
   62         -
/// requesting cell's demand schedulable again. Once committed, [`DeliveryAck`]
   63         -
/// owns fence completion and the requesting cell owns the acquisition event.
          46  +
/// requesting cell's demand schedulable again. Once committed,
          47  +
/// [`DeliverySettlement`] owns assignment settlement and the requesting cell
          48  +
/// owns the acquisition step.
   64     49   
pub(in crate::client::pool) struct DeliveryGuard {
   65         -
    /// Admission authority that owns the delivery fence and fallback.
   66         -
    origin: Arc<OriginAdmission>,
   67         -
    /// Never-reused identity of this one crossing.
   68         -
    delivery: DeliveryId,
   69         -
    /// Cell selected while admission was locked.
   70         -
    requesting_partition: PartitionId,
   71         -
    /// Exact requesting-cell demand generation that must revalidate the
   72         -
    /// payload.
   73         -
    demand: DemandId,
   74         -
    /// Payload ownership before materialization, after materialization, or after transfer.
   75         -
    state: DeliveryGuardState,
          50  +
    /// Admission authority that owns the assignment and fallback.
          51  +
    admission: Arc<OriginAdmission>,
          52  +
    /// Exact demand excluded from competing admission while the payload crosses.
          53  +
    assignment: DemandAssignment,
          54  +
    /// Payload ownership before resolution, after resolution, or after transfer.
          55  +
    state: DeliveryState,
   76     56   
}
   77     57   
   78         -
/// Ownership phase of one admission-to-cell delivery.
          58  +
/// Ownership phase of one admission-to-cell delivery crossing.
   79     59   
///
   80     60   
/// ```text
   81         -
/// Undelivered -- materialize connection-cell work ----------> Materialized
   82         -
/// Undelivered -- peer sender rejection or drop ------------------> admission fallback
   83         -
/// Materialized -- commit to requesting cell ----------------> Disarmed + DeliveryAck
   84         -
/// Materialized -- drop -------------------------------------> admission fallback
          61  +
/// Pending -- resolve connection-cell work ------------> Ready
          62  +
/// Pending -- peer sender rejection or drop -----------> admission fallback
          63  +
/// Ready   -- commit to requesting cell ---------------> Disarmed + DeliverySettlement
          64  +
/// Ready   -- drop ------------------------------------> admission fallback
   85     65   
/// ```
   86     66   
///
   87         -
/// `Disarmed` owns no payload. After commit, `DeliveryAck` owns fence and
   88         -
/// connection-cell completion.
   89         -
enum DeliveryGuardState {
   90         -
    /// Admission removed the payload, but connection cell-side work may still fail.
   91         -
    Undelivered {
   92         -
        /// Payload still owned by this fallback.
   93         -
        payload: Option<AcquisitionPayload>,
   94         -
        /// Demand acknowledgement used if the guard is dropped.
   95         -
        on_drop: DeliveryAckResult,
   96         -
    },
   97         -
    /// Connection-owning-cell work completed; the requesting cell may reserve
   98         -
    /// its waiter.
   99         -
    Materialized {
  100         -
        /// Requesting-cell-ready payload still owned by this fallback.
  101         -
        payload: Option<MaterializedPayload>,
  102         -
        /// Demand acknowledgement used if the guard is dropped.
  103         -
        on_drop: DeliveryAckResult,
          67  +
/// `Disarmed` owns no payload. After commit, `DeliverySettlement` owns
          68  +
/// assignment and connection-cell completion.
          69  +
enum DeliveryState {
          70  +
    /// Admission selected the payload, but connection cell-side work may fail.
          71  +
    Pending(DeliveryPayload),
          72  +
    /// Connection-owning-cell work completed; the exact acquisition step may
          73  +
    /// now cross to the requesting cell.
          74  +
    Ready {
          75  +
        step: AcquisitionStep,
          76  +
        settlement: DeliverySettlementKind,
  104     77   
    },
  105     78   
    /// Payload and fallback responsibility moved to requesting cell-owned state.
  106     79   
    Disarmed,
  107     80   
}
  108     81   
  109     82   
impl DeliveryGuard {
  110     83   
    /// Creates a delivery for one permit removed from admission.
  111     84   
    pub(super) fn capacity(
  112         -
        origin: Arc<OriginAdmission>,
  113         -
        delivery: DeliveryId,
  114         -
        requesting_partition: PartitionId,
  115         -
        demand: DemandId,
  116         -
        permit: Permit,
          85  +
        admission: Arc<OriginAdmission>,
          86  +
        assignment: DemandAssignment,
          87  +
        permit: CapacityPermit,
  117     88   
    ) -> Self {
  118     89   
        Self {
  119         -
            origin,
  120         -
            delivery,
  121         -
            requesting_partition,
  122         -
            demand,
  123         -
            state: DeliveryGuardState::Undelivered {
  124         -
                payload: Some(AcquisitionPayload::Capacity(permit)),
  125         -
                on_drop: DeliveryAckResult::RetrySameResidence,
  126         -
            },
          90  +
            admission,
          91  +
            assignment,
          92  +
            state: DeliveryState::Pending(DeliveryPayload::Capacity(permit)),
  127     93   
        }
  128     94   
    }
  129     95   
  130     96   
    /// Creates a delivery for one provisional sender selected for borrowing.
  131     97   
    pub(super) fn borrowed_h1(
  132         -
        origin: Arc<OriginAdmission>,
  133         -
        delivery: DeliveryId,
  134         -
        requesting_partition: PartitionId,
  135         -
        demand: DemandId,
  136         -
        reuse_id: ReuseId,
  137         -
        connection_partition: PartitionId,
  138         -
        candidate: ReuseCandidate,
          98  +
        admission: Arc<OriginAdmission>,
          99  +
        assignment: DemandAssignment,
         100  +
        match_id: H1MatchId,
         101  +
        supplier: PartitionId,
         102  +
        candidate: H1Candidate,
  139    103   
    ) -> Self {
  140    104   
        Self {
  141         -
            origin,
  142         -
            delivery,
  143         -
            requesting_partition,
  144         -
            demand,
  145         -
            state: DeliveryGuardState::Undelivered {
  146         -
                payload: Some(AcquisitionPayload::BorrowedH1 {
  147         -
                    reuse_id,
  148         -
                    connection_partition,
  149         -
                    candidate,
  150         -
                }),
  151         -
                on_drop: DeliveryAckResult::RetrySameResidence,
  152         -
            },
         105  +
            admission,
         106  +
            assignment,
         107  +
            state: DeliveryState::Pending(DeliveryPayload::BorrowedH1 {
         108  +
                match_id,
         109  +
                supplier,
         110  +
                candidate,
         111  +
            }),
  153    112   
        }
  154    113   
    }
  155    114   
  156         -
    /// Returns the demand generation fenced by this delivery.
         115  +
    /// Returns the demand generation owned by this delivery assignment.
  157    116   
    pub(in crate::client::pool) fn demand(&self) -> DemandId {
  158         -
        self.demand
         117  +
        self.assignment.demand
  159    118   
    }
  160    119   
  161         -
    /// Returns whether admission still recognizes this delivery fence.
         120  +
    /// Returns whether admission still recognizes this delivery assignment.
  162    121   
    #[cfg(test)]
  163    122   
    pub(in crate::client::pool) fn is_current(&self) -> bool {
  164         -
        self.origin
  165         -
            .delivery_is_current(self.delivery, &self.requesting_partition, self.demand)
         123  +
        self.admission.assignment_is_current(&self.assignment)
  166    124   
    }
  167    125   
  168    126   
    /// Materializes owning-cell state and attempts one requesting-cell delivery.
  169         -
    pub(super) fn deliver_once(mut self) -> Option<AdmissionAction> {
  170         -
        if !self.materialize() {
         127  +
    pub(super) fn deliver(mut self) -> Option<AdmissionAction> {
         128  +
        if !self.resolve_payload() {
  171    129   
            return None;
  172    130   
        }
  173         -
        match self.origin.cell(&self.requesting_partition) {
         131  +
        match self.admission.cell(&self.assignment.requester) {
  174    132   
            Some(requesting_cell) => OriginCell::receive_delivery(&requesting_cell, self),
  175         -
            None => self.reject(None),
         133  +
            None => self.refuse(None),
  176    134   
        }
  177    135   
    }
  178    136   
  179    137   
    /// Completes fallible owning-cell work before reserving requesting-cell state.
  180         -
    fn materialize(&mut self) -> bool {
  181         -
        let state = std::mem::replace(&mut self.state, DeliveryGuardState::Disarmed);
  182         -
        let DeliveryGuardState::Undelivered {
  183         -
            mut payload,
  184         -
            on_drop,
  185         -
        } = state
  186         -
        else {
  187         -
            unreachable!("delivery payload materialized more than once");
         138  +
    fn resolve_payload(&mut self) -> bool {
         139  +
        let state = std::mem::replace(&mut self.state, DeliveryState::Disarmed);
         140  +
        let DeliveryState::Pending(payload) = state else {
         141  +
            unreachable!("delivery payload resolved more than once");
  188    142   
        };
  189         -
        let payload = payload
  190         -
            .take()
  191         -
            .expect("undelivered acquisition payload disappeared");
  192         -
        let materialized = match payload {
  193         -
            AcquisitionPayload::Capacity(permit) => {
  194         -
                MaterializedPayload::Capacity(EstablishmentPermit::bounded(
  195         -
                    super::CapacityLease::new(self.origin.clone(), permit),
  196         -
                ))
  197         -
            }
  198         -
            AcquisitionPayload::BorrowedH1 {
  199         -
                reuse_id,
  200         -
                connection_partition,
         143  +
        let (step, settlement) = match payload {
         144  +
            DeliveryPayload::Capacity(permit) => (
         145  +
                AcquisitionStep::StartEstablishment(EstablishmentPermit::bounded(
         146  +
                    CapacityLease::new(self.admission.clone(), permit),
         147  +
                )),
         148  +
                DeliverySettlementKind::Capacity,
         149  +
            ),
         150  +
            DeliveryPayload::BorrowedH1 {
         151  +
                match_id,
         152  +
                supplier,
  201    153   
                candidate,
  202    154   
            } => match candidate.commit() {
  203         -
                Ok(selection) => MaterializedPayload::BorrowedH1 {
  204         -
                    reuse_id,
  205         -
                    connection_partition,
  206         -
                    selection,
  207         -
                },
         155  +
                Ok(selection) => {
         156  +
                    let connection_id = selection.connection_id();
         157  +
                    (
         158  +
                        AcquisitionStep::Resolved(AcquisitionOutcome::H1(selection)),
         159  +
                        DeliverySettlementKind::BorrowedH1 {
         160  +
                            connection_id,
         161  +
                            match_id,
         162  +
                            supplier,
         163  +
                        },
         164  +
                    )
         165  +
                }
  208    166   
                Err(candidate) => {
  209         -
                    drop(candidate);
  210         -
                    let next = OriginAdmission::finish_delivery(
  211         -
                        &self.origin,
  212         -
                        self.delivery,
  213         -
                        &self.requesting_partition,
         167  +
                    let outcome = candidate.reject();
         168  +
                    let next = OriginAdmission::settle_borrow_delivery(
         169  +
                        &self.admission,
         170  +
                        match_id,
         171  +
                        &self.assignment,
         172  +
                        DemandAssignmentOutcome::RetrySamePosition,
  214    173   
                        None,
  215         -
                        on_drop,
         174  +
                        Some(outcome),
  216    175   
                    );
  217         -
                    OriginAdmission::drive(next);
         176  +
                    OriginAdmission::run_action_chain(next);
  218    177   
                    return false;
  219    178   
                }
  220    179   
            },
  221    180   
        };
  222         -
        self.state = DeliveryGuardState::Materialized {
  223         -
            payload: Some(materialized),
  224         -
            on_drop,
  225         -
        };
         181  +
        self.state = DeliveryState::Ready { step, settlement };
  226    182   
        true
  227    183   
    }
  228    184   
  229    185   
    /// Materializes this guard before tests manually split the requesting cell
  230    186   
    /// reservation and installation transitions.
  231    187   
    #[cfg(test)]
  232         -
    pub(in crate::client::pool) fn materialize_for_test(&mut self) -> bool {
  233         -
        self.materialize()
         188  +
    pub(in crate::client::pool) fn resolve_payload_for_test(&mut self) -> bool {
         189  +
        self.resolve_payload()
  234    190   
    }
  235    191   
  236         -
    /// Moves the materialized payload into a requesting cell-owned event.
  237         -
    pub(in crate::client::pool) fn commit(
         192  +
    /// Moves the resolved payload into a requesting cell-owned acquisition step.
         193  +
    pub(in crate::client::pool) fn into_step(
  238    194   
        mut self,
  239    195   
        successor: Option<DemandSnapshot>,
  240         -
    ) -> (AcquisitionEvent, DeliveryAck) {
  241         -
        let DeliveryGuardState::Materialized { payload, .. } = &mut self.state else {
  242         -
            unreachable!("delivery committed before payload materialization");
         196  +
    ) -> (AcquisitionStep, DeliverySettlement) {
         197  +
        let state = std::mem::replace(&mut self.state, DeliveryState::Disarmed);
         198  +
        let DeliveryState::Ready { step, settlement } = state else {
         199  +
            unreachable!("delivery committed before payload resolution");
  243    200   
        };
  244         -
        let payload = payload
  245         -
            .take()
  246         -
            .expect("materialized acquisition payload moved more than once");
  247         -
        let (event, kind) = match payload {
  248         -
            MaterializedPayload::Capacity(permit) => {
  249         -
                (AcquisitionEvent::Establish(permit), DeliveryKind::Capacity)
  250         -
            }
  251         -
            MaterializedPayload::BorrowedH1 {
  252         -
                reuse_id,
  253         -
                connection_partition,
  254         -
                selection,
  255         -
            } => {
  256         -
                let connection_id = selection.connection_id();
  257         -
                (
  258         -
                    AcquisitionEvent::Complete(AcquisitionResult::H1(selection)),
  259         -
                    DeliveryKind::BorrowedH1 {
  260         -
                        connection_id,
  261         -
                        reuse_id,
  262         -
                        connection_partition,
  263         -
                    },
  264         -
                )
  265         -
            }
  266         -
        };
  267         -
        self.state = DeliveryGuardState::Disarmed;
  268    201   
        (
  269         -
            event,
  270         -
            DeliveryAck {
  271         -
                origin: self.origin.clone(),
  272         -
                delivery: self.delivery,
  273         -
                requesting_partition: self.requesting_partition,
         202  +
            step,
         203  +
            DeliverySettlement {
         204  +
                admission: self.admission.clone(),
         205  +
                assignment: self.assignment.clone(),
  274    206   
                successor,
  275         -
                kind: Some(kind),
         207  +
                kind: Some(settlement),
  276    208   
            },
  277    209   
        )
  278    210   
    }
  279    211   
  280    212   
    /// Refunnels this delivery after requesting cell revalidation rejects it.
  281         -
    pub(in crate::client::pool) fn reject(
         213  +
    pub(in crate::client::pool) fn refuse(
  282    214   
        mut self,
  283    215   
        successor: Option<DemandSnapshot>,
  284    216   
    ) -> Option<AdmissionAction> {
  285         -
        let state = std::mem::replace(&mut self.state, DeliveryGuardState::Disarmed);
  286         -
        self.finish_state(state, DeliveryAckResult::Rejected { successor })
         217  +
        let state = std::mem::replace(&mut self.state, DeliveryState::Disarmed);
         218  +
        self.settle_state(state, DemandAssignmentOutcome::Refused { successor })
  287    219   
    }
  288    220   
  289         -
    /// Resolves payload fallback before closing the admission-owned fence.
  290         -
    fn finish_state(
         221  +
    /// Resolves payload fallback before settling the admission-owned assignment.
         222  +
    fn settle_state(
  291    223   
        &self,
  292         -
        state: DeliveryGuardState,
  293         -
        result: DeliveryAckResult,
         224  +
        state: DeliveryState,
         225  +
        outcome: DemandAssignmentOutcome,
  294    226   
    ) -> Option<AdmissionAction> {
  295    227   
        match state {
  296         -
            DeliveryGuardState::Undelivered { mut payload, .. } => {
  297         -
                let permit = match payload.take() {
  298         -
                    Some(AcquisitionPayload::Capacity(permit)) => Some(permit),
  299         -
                    Some(AcquisitionPayload::BorrowedH1 { candidate, .. }) => {
  300         -
                        drop(candidate);
  301         -
                        None
  302         -
                    }
  303         -
                    None => None,
  304         -
                };
  305         -
                OriginAdmission::finish_delivery(
  306         -
                    &self.origin,
  307         -
                    self.delivery,
  308         -
                    &self.requesting_partition,
  309         -
                    permit,
  310         -
                    result,
         228  +
            DeliveryState::Pending(DeliveryPayload::Capacity(permit)) => {
         229  +
                OriginAdmission::settle_delivery(
         230  +
                    &self.admission,
         231  +
                    &self.assignment,
         232  +
                    Some(permit),
         233  +
                    outcome,
         234  +
                )
         235  +
            }
         236  +
            DeliveryState::Pending(DeliveryPayload::BorrowedH1 {
         237  +
                match_id,
         238  +
                candidate,
         239  +
                ..
         240  +
            }) => {
         241  +
                let supply = candidate.reject();
         242  +
                OriginAdmission::settle_borrow_delivery(
         243  +
                    &self.admission,
         244  +
                    match_id,
         245  +
                    &self.assignment,
         246  +
                    outcome,
         247  +
                    None,
         248  +
                    Some(supply),
  311    249   
                )
  312    250   
            }
  313         -
            DeliveryGuardState::Materialized { mut payload, .. } => match payload.take() {
  314         -
                Some(MaterializedPayload::Capacity(permit)) => {
  315         -
                    drop(permit);
  316         -
                    OriginAdmission::finish_delivery(
  317         -
                        &self.origin,
  318         -
                        self.delivery,
  319         -
                        &self.requesting_partition,
         251  +
            DeliveryState::Ready { step, settlement } => match settlement {
         252  +
                DeliverySettlementKind::Capacity => {
         253  +
                    drop(step);
         254  +
                    OriginAdmission::settle_delivery(
         255  +
                        &self.admission,
         256  +
                        &self.assignment,
  320    257   
                        None,
  321         -
                        result,
         258  +
                        outcome,
  322    259   
                    )
  323    260   
                }
  324         -
                Some(MaterializedPayload::BorrowedH1 {
  325         -
                    reuse_id,
  326         -
                    connection_partition,
  327         -
                    selection,
  328         -
                }) => {
  329         -
                    let owning_cell = self.origin.cell(&connection_partition);
  330         -
                    drop(selection);
  331         -
                    let outcome = match owning_cell {
  332         -
                        Some(owning_cell) => H1AvailabilityOutcome::reported(
  333         -
                            connection_partition,
  334         -
                            owning_cell.cancel_h1_reuse(reuse_id),
         261  +
                DeliverySettlementKind::BorrowedH1 {
         262  +
                    match_id, supplier, ..
         263  +
                } => {
         264  +
                    let supplier_cell = self.admission.cell(&supplier);
         265  +
                    drop(step);
         266  +
                    let supply = match supplier_cell {
         267  +
                        Some(supplier_cell) => H1SupplyOutcome::supplier_live(
         268  +
                            supplier,
         269  +
                            supplier_cell.cancel_h1_reservation(match_id),
  335    270   
                        ),
  336         -
                        None => H1AvailabilityOutcome::expired(connection_partition),
         271  +
                        None => H1SupplyOutcome::supplier_expired(supplier),
  337    272   
                    };
  338         -
                    OriginAdmission::finish_borrow_delivery(
  339         -
                        &self.origin,
  340         -
                        reuse_id,
  341         -
                        self.delivery,
  342         -
                        &self.requesting_partition,
  343         -
                        result,
         273  +
                    OriginAdmission::settle_borrow_delivery(
         274  +
                        &self.admission,
         275  +
                        match_id,
         276  +
                        &self.assignment,
         277  +
                        outcome,
  344    278   
                        None,
  345         -
                        Some(outcome),
         279  +
                        Some(supply),
  346    280   
                    )
  347    281   
                }
  348         -
  349         -
                None => None,
  350    282   
            },
  351         -
            DeliveryGuardState::Disarmed => None,
         283  +
            DeliveryState::Disarmed => None,
  352    284   
        }
  353    285   
    }
  354    286   
}
  355    287   
  356    288   
impl fmt::Debug for DeliveryGuard {
  357    289   
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  358    290   
        f.debug_struct("DeliveryGuard")
  359         -
            .field("delivery", &self.delivery)
  360         -
            .field("requesting_partition", &self.requesting_partition)
  361         -
            .field("demand", &self.demand)
         291  +
            .field("assignment", &self.assignment)
  362    292   
            .finish_non_exhaustive()
  363    293   
    }
  364    294   
}
  365    295   
  366    296   
impl Drop for DeliveryGuard {
  367    297   
    fn drop(&mut self) {
  368         -
        let state = std::mem::replace(&mut self.state, DeliveryGuardState::Disarmed);
  369         -
        let result = match &state {
  370         -
            DeliveryGuardState::Undelivered { on_drop, .. }
  371         -
            | DeliveryGuardState::Materialized { on_drop, .. } => on_drop.clone(),
  372         -
            DeliveryGuardState::Disarmed => return,
  373         -
        };
  374         -
        let next = self.finish_state(state, result);
  375         -
        OriginAdmission::drive(next);
         298  +
        let state = std::mem::replace(&mut self.state, DeliveryState::Disarmed);
         299  +
        if matches!(state, DeliveryState::Disarmed) {
         300  +
            return;
         301  +
        }
         302  +
        let next = self.settle_state(state, DemandAssignmentOutcome::RetrySamePosition);
         303  +
        OriginAdmission::run_action_chain(next);
  376    304   
    }
  377    305   
}
  378    306   
  379         -
/// Acknowledgement after an event becomes owned by the requesting cell.
         307  +
/// Assignment settlement after a step becomes owned by the requesting cell.
  380    308   
///
  381         -
/// Explicit rejection returns the event before closing the delivery fence.
  382         -
/// Once the requesting cell owns the event, dropping this value acknowledges
  383         -
/// success and completes any borrowed connection's reuse operation.
  384         -
pub(in crate::client::pool) struct DeliveryAck {
  385         -
    /// Admission authority that owns the outstanding fence.
  386         -
    origin: Arc<OriginAdmission>,
  387         -
    /// Delivery fence closed by this acknowledgement.
  388         -
    delivery: DeliveryId,
  389         -
    /// Cell that now owns or rejected the acquisition event.
  390         -
    requesting_partition: PartitionId,
         309  +
/// Explicit refusal returns the step before settling the assignment. Once the
         310  +
/// requesting cell owns the step, dropping this value accepts the assignment
         311  +
/// and completes any borrowed connection's H1 match.
         312  +
pub(in crate::client::pool) struct DeliverySettlement {
         313  +
    /// Admission authority that owns the outstanding assignment.
         314  +
    admission: Arc<OriginAdmission>,
         315  +
    /// Exact assignment settled by this value.
         316  +
    assignment: DemandAssignment,
  391    317   
    /// Successor demand to publish after the old generation finishes.
  392    318   
    successor: Option<DemandSnapshot>,
  393    319   
    /// Payload-specific connection cell completion still owed by this guard.
  394         -
    kind: Option<DeliveryKind>,
         320  +
    kind: Option<DeliverySettlementKind>,
  395    321   
}
  396    322   
  397    323   
/// Terminal work required after the requesting cell takes ownership.
  398         -
enum DeliveryKind {
  399         -
    /// Only the admission delivery fence remains to acknowledge.
         324  +
enum DeliverySettlementKind {
         325  +
    /// Only the admission demand assignment remains to settle.
  400    326   
    Capacity,
  401    327   
    /// The connection cell must learn whether sender transfer succeeded.
  402    328   
    BorrowedH1 {
  403    329   
        /// Connection whose sender crossed to the requesting cell.
  404    330   
        connection_id: ConnectionId,
  405         -
        /// Reuse operation completed by this acknowledgement.
  406         -
        reuse_id: ReuseId,
  407         -
        /// Cell whose local reuse reservation must complete.
  408         -
        connection_partition: PartitionId,
         331  +
        /// Retained H1 match completed by this settlement.
         332  +
        match_id: H1MatchId,
         333  +
        /// Cell whose local peer reservation must complete.
         334  +
        supplier: PartitionId,
  409    335   
    },
  410    336   
}
  411    337   
  412         -
impl DeliveryAck {
         338  +
impl DeliverySettlement {
  413    339   
    /// Avoids republishing a successor already covered by visible HTTP/2 state.
  414    340   
    ///
  415    341   
    /// Capacity or HTTP/1 delivery may reveal another waiter after the
  416    342   
    /// requesting cell already gained a local generation or peer route. That
  417    343   
    /// visible HTTP/2 state can serve an H2-compatible successor directly. If
  418    344   
    /// it later closes, its close path publishes the cell's current demand.
  419    345   
    pub(in crate::client::pool) fn suppress_h2_successor(&mut self) {
  420    346   
        if self
  421    347   
            .successor
  422    348   
            .as_ref()
  423    349   
            .is_some_and(DemandSnapshot::accepts_h2)
  424    350   
        {
  425    351   
            self.successor = None;
  426    352   
        }
  427    353   
    }
  428    354   
  429         -
    /// Acknowledges that requesting cell state accepted the acquisition event.
         355  +
    /// Records that requesting cell state accepted the acquisition step.
  430    356   
    pub(in crate::client::pool) fn accept(mut self) -> Option<AdmissionAction> {
  431    357   
        let kind = self
  432    358   
            .kind
  433    359   
            .take()
  434         -
            .expect("delivery acknowledgement completed more than once");
         360  +
            .expect("delivery settlement completed more than once");
  435    361   
        let successor = self.successor.take();
  436         -
        self.finish(kind, DeliveryAckResult::Accepted { successor }, None)
         362  +
        self.settle(kind, DemandAssignmentOutcome::Accepted { successor }, None)
  437    363   
    }
  438    364   
  439         -
    /// Refunnels events rejected after requesting cell reservation.
  440         -
    pub(in crate::client::pool) fn reject(
         365  +
    /// Refunnels steps refused after requesting cell reservation.
         366  +
    pub(in crate::client::pool) fn refuse(
  441    367   
        mut self,
  442         -
        returned_events: [Option<AcquisitionEvent>; 2],
         368  +
        returned_steps: [Option<AcquisitionStep>; 2],
  443    369   
    ) -> Option<AdmissionAction> {
  444    370   
        let kind = self
  445    371   
            .kind
  446    372   
            .take()
  447         -
            .expect("delivery acknowledgement completed more than once");
         373  +
            .expect("delivery settlement completed more than once");
  448    374   
        let successor = self.successor.take();
  449         -
        self.finish(
         375  +
        self.settle(
  450    376   
            kind,
  451         -
            DeliveryAckResult::Rejected { successor },
  452         -
            Some(returned_events),
         377  +
            DemandAssignmentOutcome::Refused { successor },
         378  +
            Some(returned_steps),
  453    379   
        )
  454    380   
    }
  455    381   
  456         -
    /// Completes the payload-specific reuse operation and delivery fence.
  457         -
    fn finish(
         382  +
    /// Completes payload-specific H1 work and settles the demand assignment.
         383  +
    fn settle(
  458    384   
        &self,
  459         -
        kind: DeliveryKind,
  460         -
        result: DeliveryAckResult,
  461         -
        returned_events: Option<[Option<AcquisitionEvent>; 2]>,
         385  +
        kind: DeliverySettlementKind,
         386  +
        outcome: DemandAssignmentOutcome,
         387  +
        returned_steps: Option<[Option<AcquisitionStep>; 2]>,
  462    388   
    ) -> Option<AdmissionAction> {
  463    389   
        match kind {
  464         -
            DeliveryKind::Capacity => {
  465         -
                drop(returned_events);
  466         -
                OriginAdmission::finish_delivery(
  467         -
                    &self.origin,
  468         -
                    self.delivery,
  469         -
                    &self.requesting_partition,
  470         -
                    None,
  471         -
                    result,
  472         -
                )
         390  +
            DeliverySettlementKind::Capacity => {
         391  +
                drop(returned_steps);
         392  +
                OriginAdmission::settle_delivery(&self.admission, &self.assignment, None, outcome)
  473    393   
            }
  474         -
            DeliveryKind::BorrowedH1 {
         394  +
            DeliverySettlementKind::BorrowedH1 {
  475    395   
                connection_id,
  476         -
                reuse_id,
  477         -
                connection_partition,
         396  +
                match_id,
         397  +
                supplier,
  478    398   
            } => {
  479         -
                let rejected = returned_events.is_some();
  480         -
                let owning_cell = rejected
  481         -
                    .then(|| self.origin.cell(&connection_partition))
  482         -
                    .flatten();
  483         -
                drop(returned_events);
  484         -
                let rejected_outcome = rejected.then(|| match owning_cell {
  485         -
                    Some(owning_cell) => H1AvailabilityOutcome::reported(
  486         -
                        connection_partition,
  487         -
                        owning_cell.cancel_h1_reuse(reuse_id),
         399  +
                let refused = returned_steps.is_some();
         400  +
                let supplier_cell = refused.then(|| self.admission.cell(&supplier)).flatten();
         401  +
                drop(returned_steps);
         402  +
                let refused_outcome = refused.then(|| match supplier_cell {
         403  +
                    Some(supplier_cell) => H1SupplyOutcome::supplier_live(
         404  +
                        supplier,
         405  +
                        supplier_cell.cancel_h1_reservation(match_id),
  488    406   
                    ),
  489         -
                    None => H1AvailabilityOutcome::expired(connection_partition),
         407  +
                    None => H1SupplyOutcome::supplier_expired(supplier),
  490    408   
                });
  491         -
                let transferred_connection_cell = (!rejected).then_some(connection_partition);
  492         -
                let action = OriginAdmission::finish_borrow_delivery(
  493         -
                    &self.origin,
  494         -
                    reuse_id,
  495         -
                    self.delivery,
  496         -
                    &self.requesting_partition,
  497         -
                    result,
  498         -
                    transferred_connection_cell,
  499         -
                    rejected_outcome,
         409  +
                let transferred_supplier = (!refused).then_some(supplier);
         410  +
                let action = OriginAdmission::settle_borrow_delivery(
         411  +
                    &self.admission,
         412  +
                    match_id,
         413  +
                    &self.assignment,
         414  +
                    outcome,
         415  +
                    transferred_supplier,
         416  +
                    refused_outcome,
  500    417   
                );
  501         -
                if !rejected {
         418  +
                if !refused {
  502    419   
                    tracing::trace!(
  503    420   
                        connection_id = %connection_id,
  504         -
                        request_partition = ?self.requesting_partition,
  505         -
                        connection_partition = ?connection_partition,
  506         -
                        origin_scheme = %self.origin.origin().scheme(),
  507         -
                        origin_host = self.origin.origin().host(),
  508         -
                        origin_port = ?self.origin.origin().port(),
         421  +
                        request_partition = ?self.assignment.requester,
         422  +
                        connection_partition = ?supplier,
         423  +
                        origin_scheme = %self.admission.origin().scheme(),
         424  +
                        origin_host = self.admission.origin().host(),
         425  +
                        origin_port = ?self.admission.origin().port(),
  509    426   
                        "HTTP/1 connection borrowed for peer demand"
  510    427   
                    );
  511    428   
                }
  512    429   
                action
  513    430   
            }
  514    431   
        }
  515    432   
    }
  516    433   
}
  517    434   
  518         -
impl fmt::Debug for DeliveryAck {
         435  +
impl fmt::Debug for DeliverySettlement {
  519    436   
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  520         -
        f.debug_struct("DeliveryAck")
  521         -
            .field("delivery", &self.delivery)
  522         -
            .field("requesting_partition", &self.requesting_partition)
         437  +
        f.debug_struct("DeliverySettlement")
         438  +
            .field("assignment", &self.assignment)
  523    439   
            .finish_non_exhaustive()
  524    440   
    }
  525    441   
}
  526    442   
  527         -
impl Drop for DeliveryAck {
         443  +
impl Drop for DeliverySettlement {
  528    444   
    fn drop(&mut self) {
  529    445   
        let Some(kind) = self.kind.take() else {
  530    446   
            return;
  531    447   
        };
  532    448   
        let successor = self.successor.take();
  533         -
        let next = self.finish(kind, DeliveryAckResult::Accepted { successor }, None);
  534         -
        OriginAdmission::drive(next);
         449  +
        let next = self.settle(kind, DemandAssignmentOutcome::Accepted { successor }, None);
         450  +
        OriginAdmission::run_action_chain(next);
         451  +
    }
         452  +
}
         453  +
         454  +
#[cfg(all(test, not(smithy_http_client_loom)))]
         455  +
mod tests {
         456  +
    use super::super::{ProtocolRequirement, SnapshotVersion};
         457  +
    use super::*;
         458  +
    use crate::client::pool::origin::OriginKey;
         459  +
    use crate::client::pool::partition::EligibilityGroup;
         460  +
    use std::num::NonZeroUsize;
         461  +
         462  +
    fn cell(origin: &Arc<OriginAdmission>, partition: usize) -> Arc<OriginCell> {
         463  +
        let cell = Arc::new(OriginCell::new(
         464  +
            PartitionId::from_index(partition),
         465  +
            OriginKey::from_parts(http_1x::uri::Scheme::HTTPS, "example.com", None).unwrap(),
         466  +
            EligibilityGroup::Pool,
         467  +
            Some(origin.clone()),
         468  +
            None,
         469  +
        ));
         470  +
        OriginAdmission::register_cell(origin, cell)
         471  +
    }
         472  +
         473  +
    fn demand(id: u64) -> DemandSnapshot {
         474  +
        DemandSnapshot::active(
         475  +
            DemandId::from_u64(id),
         476  +
            SnapshotVersion::INITIAL,
         477  +
            ProtocolRequirement::H1Compatible,
         478  +
            EligibilityGroup::Pool,
         479  +
        )
         480  +
    }
         481  +
         482  +
    #[test]
         483  +
    fn assignment_currency_includes_the_demand_id() {
         484  +
        let origin = OriginAdmission::for_test(NonZeroUsize::new(1).unwrap());
         485  +
        let requesting_partition = cell(&origin, 1);
         486  +
        let delivery = OriginAdmission::submit_without_running(
         487  +
            &origin,
         488  +
            requesting_partition.id().partition(),
         489  +
            demand(1),
         490  +
        )
         491  +
        .unwrap();
         492  +
        assert!(delivery.is_current());
         493  +
         494  +
        origin
         495  +
            .state
         496  +
            .lock()
         497  +
            .apply_demand_snapshot(requesting_partition.id().partition(), demand(2));
         498  +
        assert!(!delivery.is_current());
         499  +
        delivery.refuse(None);
         500  +
    }
         501  +
         502  +
    #[test]
         503  +
    fn stale_successor_cannot_leave_active_demand_idle() {
         504  +
        let origin = OriginAdmission::for_test(NonZeroUsize::new(1).unwrap());
         505  +
        let requesting_partition = cell(&origin, 1);
         506  +
        let delivery = OriginAdmission::submit_without_running(
         507  +
            &origin,
         508  +
            requesting_partition.id().partition(),
         509  +
            demand(1),
         510  +
        )
         511  +
        .unwrap();
         512  +
        origin.state.lock().apply_demand_snapshot(
         513  +
            requesting_partition.id().partition(),
         514  +
            DemandSnapshot::active(
         515  +
                DemandId::from_u64(1),
         516  +
                SnapshotVersion::INITIAL.next(),
         517  +
                ProtocolRequirement::H1Compatible,
         518  +
                EligibilityGroup::Pool,
         519  +
            ),
         520  +
        );
         521  +
        delivery.refuse(Some(demand(1)));
         522  +
         523  +
        assert_eq!(1, origin.probe().available);
         524  +
        assert_eq!(0, origin.probe().ordered);
         525  +
    }
         526  +
         527  +
    #[test]
         528  +
    fn dropped_delivery_refunnels_capacity_and_preserves_order() {
         529  +
        let origin = OriginAdmission::for_test(NonZeroUsize::new(1).unwrap());
         530  +
        let first = cell(&origin, 1);
         531  +
        let second = cell(&origin, 2);
         532  +
        let (first_waiter, first_demand) =
         533  +
            first.register_waiter_without_publish(ProtocolRequirement::H1Compatible);
         534  +
        let (second_waiter, second_demand) =
         535  +
            second.register_waiter_without_publish(ProtocolRequirement::H1Compatible);
         536  +
        let delivery =
         537  +
            OriginAdmission::submit_without_running(&origin, first.id().partition(), first_demand)
         538  +
                .unwrap();
         539  +
        {
         540  +
            let mut state = origin.state.lock();
         541  +
            state.apply_demand_snapshot(second.id().partition(), second_demand);
         542  +
        }
         543  +
        drop(delivery);
         544  +
         545  +
        let first_lease = OriginCell::take_ready_lease(&first, first_waiter)
         546  +
            .expect("dropped delivery did not retry the original head");
         547  +
        assert!(OriginCell::take_ready_lease(&second, second_waiter).is_none());
         548  +
        assert_eq!(1, origin.probe().ordered);
         549  +
         550  +
        drop(first_lease);
         551  +
        let second_lease = OriginCell::take_ready_lease(&second, second_waiter)
         552  +
            .expect("younger demand did not run after the original head");
         553  +
        drop(second_lease);
         554  +
    }
         555  +
         556  +
    #[test]
         557  +
    fn expired_requesting_cell_refunnels_capacity() {
         558  +
        let origin = OriginAdmission::for_test(NonZeroUsize::new(1).unwrap());
         559  +
        let requesting_partition = cell(&origin, 1);
         560  +
        let requesting_cell_id = requesting_partition.id().partition();
         561  +
        let (_waiter, snapshot) =
         562  +
            requesting_partition.register_waiter_without_publish(ProtocolRequirement::H1Compatible);
         563  +
        let delivery =
         564  +
            OriginAdmission::submit_without_running(&origin, requesting_cell_id, snapshot).unwrap();
         565  +
         566  +
        drop(requesting_partition);
         567  +
        assert!(origin.cell(&requesting_cell_id).is_none());
         568  +
        OriginAdmission::run_action_chain(Some(AdmissionAction::Deliver(delivery)));
         569  +
         570  +
        let probe = origin.probe();
         571  +
        assert_eq!(1, probe.available);
         572  +
        assert_eq!(0, probe.assigned);
         573  +
        assert_eq!(0, probe.ordered);
  535    574   
    }
  536    575   
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-http-client/src/client/pool/admission/demand.rs

@@ -1,1 +1104,1196 @@
    9      9   
//! current head. That demand may be satisfied either by origin-wide connection
   10     10   
//! capacity or by an existing HTTP/2 connection in its eligibility group.
   11     11   
//! These resources require different orderings.
   12     12   
//!
   13     13   
//! For example, the origin order may contain `A(group X), B(group Y)` while
   14     14   
//! only group Y has a reusable HTTP/2 connection. A remains first for the next
   15     15   
//! available connection permit, while the group-Y connection can serve B
   16     16   
//! without consuming that permit or delaying A. The group order finds B
   17     17   
//! directly instead of scanning every partition.
   18     18   
//!
   19         -
//! The same demand occupies both orders because capacity and HTTP/2 publication
   20         -
//! can race to satisfy it. Reserving either position retains a fence in both
   21         -
//! orders until the requesting cell accepts or rejects the handoff. The other
   22         -
//! resource therefore cannot serve the same demand while the first handoff is
   23         -
//! running outside the admission lock.
   24         -
   25         -
use super::{
   26         -
    DeliveryAckResult, DeliveryId, DemandId, DemandSnapshot, DemandState, IntrusiveLinks,
   27         -
    IntrusiveOrder, Permit, ProtocolRequirement,
   28         -
};
          19  +
//! The same demand occupies both orders because capacity delivery and HTTP/2
          20  +
//! route installation can race to satisfy it. Assigning either position keeps
          21  +
//! both positions attached until the requesting cell accepts or refuses the
          22  +
//! handoff. The other resource cannot select the same demand while the first
          23  +
//! handoff runs outside the admission lock.
          24  +
          25  +
use super::{CapacityPermit, IntrusiveLinks, IntrusiveOrder};
   29     26   
use crate::client::pool::partition::{EligibilityGroup, PartitionId};
   30     27   
use std::collections::HashMap;
   31     28   
          29  +
/// Protocol capability required by the head waiter in a cell.
          30  +
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
          31  +
pub(in crate::client::pool) enum ProtocolRequirement {
          32  +
    /// The waiter requires HTTP/1 wire semantics.
          33  +
    H1Required,
          34  +
    /// The waiter may dispatch over HTTP/1 or HTTP/2.
          35  +
    H1Compatible,
          36  +
    /// The waiter requires HTTP/2.
          37  +
    H2Required,
          38  +
}
          39  +
          40  +
impl ProtocolRequirement {
          41  +
    pub(in crate::client::pool) fn accepts_h1(self) -> bool {
          42  +
        self != Self::H2Required
          43  +
    }
          44  +
          45  +
    pub(in crate::client::pool) fn accepts_h2(self) -> bool {
          46  +
        self != Self::H1Required
          47  +
    }
          48  +
}
          49  +
          50  +
/// Identity of one cell-local demand generation.
          51  +
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
          52  +
pub(in crate::client::pool) struct DemandId(u64);
          53  +
          54  +
impl DemandId {
          55  +
    pub(in crate::client::pool) const fn from_u64(value: u64) -> Self {
          56  +
        Self(value)
          57  +
    }
          58  +
}
          59  +
          60  +
/// Strict ordering of complete snapshots within one [`DemandId`].
          61  +
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
          62  +
pub(in crate::client::pool) struct SnapshotVersion(u64);
          63  +
          64  +
impl SnapshotVersion {
          65  +
    pub(in crate::client::pool) const INITIAL: Self = Self(0);
          66  +
          67  +
    pub(in crate::client::pool) fn next(self) -> Self {
          68  +
        Self(
          69  +
            self.0
          70  +
                .checked_add(1)
          71  +
                .expect("demand snapshot version exhausted"),
          72  +
        )
          73  +
    }
          74  +
}
          75  +
          76  +
/// Complete state submitted for one demand identity.
          77  +
#[derive(Clone, Debug, Eq, PartialEq)]
          78  +
pub(in crate::client::pool) enum DemandState {
          79  +
    Active {
          80  +
        requirement: ProtocolRequirement,
          81  +
        eligibility_group: EligibilityGroup,
          82  +
    },
          83  +
    Inactive,
          84  +
}
          85  +
          86  +
/// Versioned replacement state for one cell's current demand generation.
          87  +
#[derive(Clone, Debug, Eq, PartialEq)]
          88  +
pub(in crate::client::pool) struct DemandSnapshot {
          89  +
    pub(super) id: DemandId,
          90  +
    pub(super) version: SnapshotVersion,
          91  +
    pub(super) state: DemandState,
          92  +
}
          93  +
          94  +
impl DemandSnapshot {
          95  +
    pub(in crate::client::pool) fn active(
          96  +
        id: DemandId,
          97  +
        version: SnapshotVersion,
          98  +
        requirement: ProtocolRequirement,
          99  +
        eligibility_group: EligibilityGroup,
         100  +
    ) -> Self {
         101  +
        Self {
         102  +
            id,
         103  +
            version,
         104  +
            state: DemandState::Active {
         105  +
                requirement,
         106  +
                eligibility_group,
         107  +
            },
         108  +
        }
         109  +
    }
         110  +
         111  +
    pub(in crate::client::pool) fn accepts_h2(&self) -> bool {
         112  +
        matches!(
         113  +
            self.state,
         114  +
            DemandState::Active { requirement, .. } if requirement.accepts_h2()
         115  +
        )
         116  +
    }
         117  +
         118  +
    pub(in crate::client::pool) fn inactive(id: DemandId, version: SnapshotVersion) -> Self {
         119  +
        Self {
         120  +
            id,
         121  +
            version,
         122  +
            state: DemandState::Inactive,
         123  +
        }
         124  +
    }
         125  +
         126  +
    #[cfg(test)]
         127  +
    pub(in crate::client::pool) fn id_for_test(&self) -> DemandId {
         128  +
        self.id
         129  +
    }
         130  +
         131  +
    pub(in crate::client::pool) fn is_active(&self) -> bool {
         132  +
        matches!(self.state, DemandState::Active { .. })
         133  +
    }
         134  +
         135  +
    fn is_newer_than(&self, current: &Self) -> bool {
         136  +
        self.id > current.id || (self.id == current.id && self.version > current.version)
         137  +
    }
         138  +
}
         139  +
         140  +
/// Never-reused identity of one resource-to-demand assignment.
         141  +
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
         142  +
pub(super) struct DemandAssignmentId(pub(super) u64);
         143  +
         144  +
/// Exact demand temporarily assigned while a resource crosses lock domains.
         145  +
#[derive(Clone, Debug, Eq, PartialEq)]
         146  +
pub(super) struct DemandAssignment {
         147  +
    pub(super) id: DemandAssignmentId,
         148  +
    pub(super) requester: PartitionId,
         149  +
    pub(super) demand: DemandId,
         150  +
}
         151  +
         152  +
/// Admission's settlement of one detached demand assignment.
         153  +
#[derive(Clone, Debug, Eq, PartialEq)]
         154  +
pub(super) enum DemandAssignmentOutcome {
         155  +
    Accepted { successor: Option<DemandSnapshot> },
         156  +
    RetrySamePosition,
         157  +
    Refused { successor: Option<DemandSnapshot> },
         158  +
}
         159  +
   32    160   
/// Cross-cell demand records and their scheduling orders.
   33    161   
///
   34    162   
/// At every completed transition:
   35    163   
///
   36    164   
/// - `records` owns the newest snapshot for every retained cell.
   37    165   
/// - the origin order and the record's eligibility-group order contain exactly
   38         -
///   the `Queued` and `Delivering` records;
   39         -
/// - links for both views live inside those ordered residence variants;
   40         -
/// - an origin delivery fences the origin head; and
   41         -
/// - an HTTP/2 publication fences its eligibility-group head.
         166  +
///   the `Queued` and `PendingAssignment` records;
         167  +
/// - links for both orders live inside those schedule states;
         168  +
/// - an origin assignment owns the origin head; and
         169  +
/// - an HTTP/2 route assignment owns its eligibility-group head.
   42    170   
///
   43    171   
/// Admission coordinates capacity extraction with this schedule while holding
   44    172   
/// the same origin lock.
   45    173   
#[derive(Debug, Default)]
   46    174   
pub(super) struct DemandSchedule {
   47    175   
    /// Latest demand and scheduling residence for each retained cell.
   48    176   
    records: HashMap<PartitionId, DemandRecord>,
   49    177   
    /// Origin-wide order used by one-to-one capacity and HTTP/1 reuse.
   50    178   
    origin_order: IntrusiveOrder<PartitionId>,
   51    179   
    /// Reusable-HTTP/2 demand order for each connection-reuse group.
   52    180   
    group_orders: HashMap<EligibilityGroup, IntrusiveOrder<PartitionId>>,
   53    181   
}
   54    182   
   55    183   
/// Complete origin-order head used to choose one HTTP/1 reuse action.
   56    184   
#[derive(Clone, Debug)]
   57    185   
pub(super) struct QueuedDemand {
   58    186   
    /// Cell whose oldest waiter owns this demand generation.
   59         -
    pub(super) requesting_partition: PartitionId,
         187  +
    pub(super) requester: PartitionId,
   60    188   
    /// Demand identity revalidated at each crossing.
   61    189   
    pub(super) demand: DemandId,
   62    190   
    /// Protocol capability required by the requesting cell waiter.
   63    191   
    pub(super) requirement: ProtocolRequirement,
   64    192   
    /// Connection-owning cells whose H1 senders may satisfy this demand.
   65    193   
    pub(super) eligibility_group: EligibilityGroup,
   66    194   
}
   67    195   
   68    196   
/// Latest snapshot and scheduling residence for one stable cell.
   69    197   
#[derive(Debug)]
   70    198   
struct DemandRecord {
   71         -
    /// Newest complete publication observed for the cell.
   72         -
    pub(super) latest: DemandSnapshot,
   73         -
    /// Stable group retained while an inactive replacement crosses a fence.
   74         -
    group: Option<EligibilityGroup>,
         199  +
    /// Newest complete snapshot observed for the cell.
         200  +
    latest: DemandSnapshot,
         201  +
    /// Stable group retained while an inactive replacement crosses an assignment.
         202  +
    eligibility_group: Option<EligibilityGroup>,
   75    203   
    /// Scheduling residence, including links while ordered.
   76         -
    residence: DemandResidence,
         204  +
    schedule_state: DemandScheduleState,
   77    205   
}
   78    206   
   79    207   
/// Links retained by one demand in both scheduling views.
   80    208   
#[derive(Clone, Debug)]
   81    209   
struct DemandLinks {
   82    210   
    /// Position in origin-wide capacity and HTTP/1 order.
   83    211   
    origin: IntrusiveLinks<PartitionId>,
   84    212   
    /// Position in the demand's all-protocol eligibility-group order.
   85    213   
    group: IntrusiveLinks<PartitionId>,
   86    214   
}
   87    215   
   88         -
/// Order whose head is fenced by one delivery crossing.
         216  +
/// Order whose head is held by one detached demand assignment.
   89    217   
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
   90         -
enum DeliveryView {
         218  +
enum DemandOrder {
   91    219   
    /// Capacity or HTTP/1 delivery selected from origin order.
   92    220   
    Origin,
   93         -
    /// HTTP/2 publication selected from eligibility-group order.
   94         -
    Group,
   95         -
}
   96         -
   97         -
/// Selects one of a demand residence's intrusive link sets.
   98         -
#[derive(Clone, Copy)]
   99         -
enum DemandOrderView {
  100         -
    /// Origin-wide capacity and HTTP/1 order.
  101         -
    Origin,
  102         -
    /// Eligibility-group all-protocol order.
         221  +
    /// HTTP/2 route selected from eligibility-group order.
  103    222   
    Group,
  104    223   
}
  105    224   
  106         -
/// Admission residence for one partition's latest demand.
         225  +
/// Scheduling state for one partition's latest demand.
  107    226   
///
  108    227   
/// ```text
  109         -
/// Idle -- active publication ------------------------------> Queued
  110         -
/// Queued -- reserve head ----------------------------------> Delivering
  111         -
/// Queued -- inactive or replacement publication ----------> Idle
  112         -
/// Delivering -- retry unchanged demand --------------------> Queued
  113         -
/// Delivering -- accept, reject, or replacement retry ------> Idle
  114         -
/// Idle -- active successor remains ------------------------> Queued
         228  +
/// Unscheduled -- active snapshot --------------------------> Queued
         229  +
/// Queued -- prepare assignment ----------------------------> PendingAssignment
         230  +
/// Queued -- inactive or replacement snapshot -------------> Unscheduled
         231  +
/// PendingAssignment -- retry unchanged demand -------------> Queued
         232  +
/// PendingAssignment -- accept/refuse/replacement retry ----> Unscheduled
         233  +
/// Unscheduled -- active successor remains -----------------> Queued
  115    234   
/// ```
  116    235   
#[derive(Clone, Debug)]
  117         -
enum DemandResidence {
         236  +
enum DemandScheduleState {
  118    237   
    /// The cell has no demand represented in scheduling.
  119         -
    Idle,
         238  +
    Unscheduled,
  120    239   
    /// The demand is waiting in origin order.
  121    240   
    Queued {
  122    241   
        /// Demand generation represented by this residence.
  123    242   
        demand: DemandId,
  124    243   
        /// Origin-wide and eligibility-group scheduling links.
  125    244   
        links: DemandLinks,
  126    245   
    },
  127         -
    /// One delivery or publication guard fences this demand.
  128         -
    Delivering {
  129         -
        /// Demand generation fenced at one scheduling head.
  130         -
        demand: DemandId,
  131         -
        /// Snapshot version current when admission created the fence.
         246  +
    /// One delivery or route guard owns this demand assignment.
         247  +
    PendingAssignment {
         248  +
        /// Exact assignment allowed to settle this state.
         249  +
        assignment: DemandAssignment,
         250  +
        /// Snapshot version current when admission created the assignment.
  132    251   
        version: super::SnapshotVersion,
  133         -
        /// Delivery allowed to complete this fence.
  134         -
        delivery: DeliveryId,
  135         -
        /// Scheduling view whose head owns this crossing.
         252  +
        /// Scheduling order whose head selected this assignment.
  136    253   
        #[cfg_attr(
  137    254   
            not(debug_assertions),
  138    255   
            allow(
  139    256   
                dead_code,
  140    257   
                reason = "the scheduling view is retained for debug invariant checks"
  141    258   
            )
  142    259   
        )]
  143         -
        view: DeliveryView,
         260  +
        selected_order: DemandOrder,
  144    261   
        /// Both scheduling positions retained until acknowledgement.
  145    262   
        links: DemandLinks,
  146    263   
    },
  147    264   
}
  148    265   
  149         -
impl DemandResidence {
         266  +
impl DemandScheduleState {
  150    267   
    #[cfg(any(debug_assertions, test))]
  151    268   
    /// Borrows one view's links while this record is ordered.
  152         -
    fn links(&self, view: DemandOrderView) -> Option<&IntrusiveLinks<PartitionId>> {
         269  +
    fn links(&self, order: DemandOrder) -> Option<&IntrusiveLinks<PartitionId>> {
  153    270   
        let links = match self {
  154         -
            Self::Idle => return None,
  155         -
            Self::Queued { links, .. } | Self::Delivering { links, .. } => links,
         271  +
            Self::Unscheduled => return None,
         272  +
            Self::Queued { links, .. } | Self::PendingAssignment { links, .. } => links,
  156    273   
        };
  157         -
        match view {
  158         -
            DemandOrderView::Origin => Some(&links.origin),
  159         -
            DemandOrderView::Group => Some(&links.group),
         274  +
        match order {
         275  +
            DemandOrder::Origin => Some(&links.origin),
         276  +
            DemandOrder::Group => Some(&links.group),
  160    277   
        }
  161    278   
    }
  162    279   
  163    280   
    /// Mutably borrows one view's links from an ordered record.
  164    281   
    ///
  165    282   
    /// # Panics
  166    283   
    ///
  167    284   
    /// Panics when called for an idle record.
  168         -
    fn links_mut(&mut self, view: DemandOrderView) -> &mut IntrusiveLinks<PartitionId> {
         285  +
    fn links_mut(&mut self, order: DemandOrder) -> &mut IntrusiveLinks<PartitionId> {
  169    286   
        let links = match self {
  170         -
            Self::Idle => panic!("idle demand has no scheduling links"),
  171         -
            Self::Queued { links, .. } | Self::Delivering { links, .. } => links,
         287  +
            Self::Unscheduled => panic!("unscheduled demand has no scheduling links"),
         288  +
            Self::Queued { links, .. } | Self::PendingAssignment { links, .. } => links,
  172    289   
        };
  173         -
        match view {
  174         -
            DemandOrderView::Origin => &mut links.origin,
  175         -
            DemandOrderView::Group => &mut links.group,
         290  +
        match order {
         291  +
            DemandOrder::Origin => &mut links.origin,
         292  +
            DemandOrder::Group => &mut links.group,
  176    293   
        }
  177    294   
    }
  178    295   
  179    296   
    /// Detaches both link sets while moving a record out of scheduling.
  180    297   
    fn into_links(self) -> Option<DemandLinks> {
  181    298   
        match self {
  182         -
            Self::Idle => None,
  183         -
            Self::Queued { links, .. } | Self::Delivering { links, .. } => Some(links),
         299  +
            Self::Unscheduled => None,
         300  +
            Self::Queued { links, .. } | Self::PendingAssignment { links, .. } => Some(links),
  184    301   
        }
  185    302   
    }
  186    303   
}
  187    304   
  188         -
/// Demand reserved at the order head for one capacity delivery.
  189         -
pub(super) struct ScheduledDemand {
  190         -
    /// Selected destination cell.
  191         -
    pub(super) requesting_partition: PartitionId,
  192         -
    /// Demand identity current when the crossing was prepared.
  193         -
    pub(super) demand: DemandId,
  194         -
}
  195         -
  196    305   
/// Connection capacity extracted under admission lock before crossing to a cell.
  197    306   
#[derive(Debug)]
  198    307   
pub(super) struct PreparedCapacityDelivery {
  199         -
    /// Permit transferred into the delivery guard.
  200         -
    pub(super) permit: Permit,
  201         -
    /// Fence identity allocated for this crossing.
  202         -
    pub(super) delivery: DeliveryId,
  203         -
    /// Selected destination cell.
  204         -
    pub(super) requesting_partition: PartitionId,
  205         -
    /// Demand identity current when the crossing was prepared.
  206         -
    pub(super) demand: DemandId,
         308  +
    pub(super) assignment: DemandAssignment,
         309  +
    pub(super) permit: CapacityPermit,
  207    310   
}
  208    311   
  209    312   
impl DemandSchedule {
  210         -
    /// Applies a complete snapshot and updates its cell's scheduling residence.
  211         -
    pub(super) fn publish(&mut self, requesting_partition: PartitionId, snapshot: DemandSnapshot) {
  212         -
        if let Some(current) = self.records.get(&requesting_partition) {
         313  +
    /// Applies a complete snapshot and updates its cell's scheduling state.
         314  +
    pub(super) fn apply_snapshot(&mut self, requester: PartitionId, snapshot: DemandSnapshot) {
         315  +
        if let Some(current) = self.records.get(&requester) {
  213    316   
            if !snapshot.is_newer_than(&current.latest) {
  214    317   
                return;
  215    318   
            }
  216    319   
        } else {
  217    320   
            self.records.insert(
  218         -
                requesting_partition,
         321  +
                requester,
  219    322   
                DemandRecord {
  220    323   
                    latest: snapshot.clone(),
  221         -
                    group: None,
  222         -
                    residence: DemandResidence::Idle,
         324  +
                    eligibility_group: None,
         325  +
                    schedule_state: DemandScheduleState::Unscheduled,
  223    326   
                },
  224    327   
            );
  225    328   
        }
  226    329   
  227    330   
        let should_remove = matches!(
  228    331   
            &self
  229    332   
                .records
  230         -
                .get(&requesting_partition)
  231         -
                .expect("published demand record disappeared")
  232         -
                .residence,
  233         -
            DemandResidence::Queued { demand, .. }
         333  +
                .get(&requester)
         334  +
                .expect("demand record disappeared")
         335  +
                .schedule_state,
         336  +
            DemandScheduleState::Queued { demand, .. }
  234    337   
                if *demand != snapshot.id || !snapshot.is_active()
  235    338   
        );
  236    339   
        if should_remove {
  237         -
            self.remove_from_order(&requesting_partition);
         340  +
            self.remove_from_order(&requester);
  238    341   
        }
  239    342   
  240    343   
        if let DemandState::Active {
  241    344   
            eligibility_group, ..
  242    345   
        } = &snapshot.state
  243    346   
        {
  244    347   
            self.records
  245         -
                .get_mut(&requesting_partition)
  246         -
                .expect("published demand record disappeared")
  247         -
                .group = Some(eligibility_group.clone());
         348  +
                .get_mut(&requester)
         349  +
                .expect("demand record disappeared")
         350  +
                .eligibility_group = Some(eligibility_group.clone());
  248    351   
        }
  249    352   
        self.records
  250         -
            .get_mut(&requesting_partition)
  251         -
            .expect("published demand record disappeared")
         353  +
            .get_mut(&requester)
         354  +
            .expect("demand record disappeared")
  252    355   
            .latest = snapshot;
  253    356   
  254    357   
        let record = self
  255    358   
            .records
  256         -
            .get(&requesting_partition)
  257         -
            .expect("published demand record disappeared");
  258         -
        if record.latest.is_active() && matches!(&record.residence, DemandResidence::Idle) {
  259         -
            self.enqueue(requesting_partition);
         359  +
            .get(&requester)
         360  +
            .expect("demand record disappeared");
         361  +
        if record.latest.is_active()
         362  +
            && matches!(&record.schedule_state, DemandScheduleState::Unscheduled)
         363  +
        {
         364  +
            self.enqueue(requester);
  260    365   
        }
  261    366   
        self.assert_consistent();
  262    367   
    }
  263    368   
  264    369   
    /// Appends an idle active demand to both scheduling orders.
  265         -
    fn enqueue(&mut self, requesting_partition: PartitionId) {
         370  +
    fn enqueue(&mut self, requester: PartitionId) {
  266    371   
        let group = self
  267         -
            .group_for(&requesting_partition)
         372  +
            .group_for(&requester)
  268    373   
            .expect("enqueued demand was inactive");
  269         -
        let origin = self.origin_order.push_back(requesting_partition);
         374  +
        let origin = self.origin_order.push_back(requester);
  270    375   
        let group_links = self
  271    376   
            .group_orders
  272    377   
            .entry(group)
  273    378   
            .or_default()
  274         -
            .push_back(requesting_partition);
         379  +
            .push_back(requester);
  275    380   
        if let Some(previous) = origin.previous {
  276    381   
            self.records
  277    382   
                .get_mut(&previous)
  278    383   
                .expect("origin demand tail disappeared")
  279         -
                .residence
  280         -
                .links_mut(DemandOrderView::Origin)
  281         -
                .next = Some(requesting_partition);
         384  +
                .schedule_state
         385  +
                .links_mut(DemandOrder::Origin)
         386  +
                .next = Some(requester);
  282    387   
        }
  283    388   
        if let Some(previous) = group_links.previous {
  284    389   
            self.records
  285    390   
                .get_mut(&previous)
  286    391   
                .expect("group demand tail disappeared")
  287         -
                .residence
  288         -
                .links_mut(DemandOrderView::Group)
  289         -
                .next = Some(requesting_partition);
         392  +
                .schedule_state
         393  +
                .links_mut(DemandOrder::Group)
         394  +
                .next = Some(requester);
  290    395   
        }
  291    396   
  292    397   
        let record = self
  293    398   
            .records
  294         -
            .get_mut(&requesting_partition)
         399  +
            .get_mut(&requester)
  295    400   
            .expect("queued demand record disappeared");
  296         -
        debug_assert!(matches!(record.residence, DemandResidence::Idle));
         401  +
        debug_assert!(matches!(
         402  +
            record.schedule_state,
         403  +
            DemandScheduleState::Unscheduled
         404  +
        ));
  297    405   
        let demand = record.latest.id;
  298         -
        record.residence = DemandResidence::Queued {
         406  +
        record.schedule_state = DemandScheduleState::Queued {
  299    407   
            demand,
  300    408   
            links: DemandLinks {
  301    409   
                origin,
  302    410   
                group: group_links,
  303    411   
            },
  304    412   
        };
  305    413   
    }
  306    414   
  307    415   
    /// Removes an ordered demand from both views and leaves its record idle.
  308         -
    fn remove_from_order(&mut self, requesting_partition: &PartitionId) {
         416  +
    fn remove_from_order(&mut self, requester: &PartitionId) {
  309    417   
        let group = self
  310         -
            .group_for(requesting_partition)
         418  +
            .group_for(requester)
  311    419   
            .expect("removed demand had no eligibility group");
  312         -
        let residence = {
         420  +
        let schedule_state = {
  313    421   
            let record = self
  314    422   
                .records
  315         -
                .get_mut(requesting_partition)
         423  +
                .get_mut(requester)
  316    424   
                .expect("removed demand record disappeared");
  317         -
            std::mem::replace(&mut record.residence, DemandResidence::Idle)
         425  +
            std::mem::replace(&mut record.schedule_state, DemandScheduleState::Unscheduled)
  318    426   
        };
  319         -
        let links = residence
         427  +
        let links = schedule_state
  320    428   
            .into_links()
  321    429   
            .expect("removed demand had no scheduling links");
  322    430   
  323    431   
        if let Some(previous) = links.origin.previous {
  324    432   
            self.records
  325    433   
                .get_mut(&previous)
  326    434   
                .expect("previous origin demand disappeared")
  327         -
                .residence
  328         -
                .links_mut(DemandOrderView::Origin)
         435  +
                .schedule_state
         436  +
                .links_mut(DemandOrder::Origin)
  329    437   
                .next = links.origin.next;
  330    438   
        }
  331    439   
        if let Some(next) = links.origin.next {
  332    440   
            self.records
  333    441   
                .get_mut(&next)
  334    442   
                .expect("next origin demand disappeared")
  335         -
                .residence
  336         -
                .links_mut(DemandOrderView::Origin)
         443  +
                .schedule_state
         444  +
                .links_mut(DemandOrder::Origin)
  337    445   
                .previous = links.origin.previous;
  338    446   
        }
  339         -
        self.origin_order
  340         -
            .remove(*requesting_partition, links.origin);
         447  +
        self.origin_order.remove(*requester, links.origin);
  341    448   
  342    449   
        if let Some(previous) = links.group.previous {
  343    450   
            self.records
  344    451   
                .get_mut(&previous)
  345    452   
                .expect("previous group demand disappeared")
  346         -
                .residence
  347         -
                .links_mut(DemandOrderView::Group)
         453  +
                .schedule_state
         454  +
                .links_mut(DemandOrder::Group)
  348    455   
                .next = links.group.next;
  349    456   
        }
  350    457   
        if let Some(next) = links.group.next {
  351    458   
            self.records
  352    459   
                .get_mut(&next)
  353    460   
                .expect("next group demand disappeared")
  354         -
                .residence
  355         -
                .links_mut(DemandOrderView::Group)
         461  +
                .schedule_state
         462  +
                .links_mut(DemandOrder::Group)
  356    463   
                .previous = links.group.previous;
  357    464   
        }
  358    465   
        let order = self
  359    466   
            .group_orders
  360    467   
            .get_mut(&group)
  361    468   
            .expect("ordered demand lost its eligibility-group order");
  362         -
        order.remove(*requesting_partition, links.group);
         469  +
        order.remove(*requester, links.group);
  363    470   
        if order.len() == 0 {
  364    471   
            self.group_orders.remove(&group);
  365    472   
        }
  366    473   
    }
  367    474   
  368    475   
    /// Returns whether the head can begin a new one-to-one delivery.
  369    476   
    pub(super) fn head_is_queued(&self) -> bool {
  370    477   
        let Some(head) = self.origin_order.head() else {
  371    478   
            return false;
  372    479   
        };
  373    480   
        matches!(
  374    481   
            &self
  375    482   
                .records
  376    483   
                .get(&head)
  377    484   
                .expect("order head disappeared")
  378         -
                .residence,
  379         -
            DemandResidence::Queued { .. }
         485  +
                .schedule_state,
         486  +
            DemandScheduleState::Queued { .. }
  380    487   
        )
  381    488   
    }
  382    489   
  383    490   
    /// Returns the complete origin-order head when it may begin reuse.
  384    491   
    pub(super) fn queued_head(&self) -> Option<QueuedDemand> {
  385    492   
        let head = self.origin_order.head()?;
  386    493   
        let record = self.records.get(&head).expect("order head disappeared");
  387         -
        let DemandResidence::Queued { demand, .. } = &record.residence else {
         494  +
        let DemandScheduleState::Queued { demand, .. } = &record.schedule_state else {
  388    495   
            return None;
  389    496   
        };
  390    497   
        let DemandState::Active {
  391         -
            head: requirement,
         498  +
            requirement,
  392    499   
            eligibility_group,
  393    500   
        } = &record.latest.state
  394    501   
        else {
  395    502   
            unreachable!("queued demand became inactive");
  396    503   
        };
  397    504   
        Some(QueuedDemand {
  398         -
            requesting_partition: head,
         505  +
            requester: head,
  399    506   
            demand: *demand,
  400    507   
            requirement: *requirement,
  401    508   
            eligibility_group: eligibility_group.clone(),
  402    509   
        })
  403    510   
    }
  404    511   
  405    512   
    /// Returns one eligibility-group head when it may receive H2 visibility.
  406    513   
    pub(super) fn queued_group_head(&self, group: &EligibilityGroup) -> Option<QueuedDemand> {
  407    514   
        let head = self.group_orders.get(group)?.head()?;
  408    515   
        let record = self
  409    516   
            .records
  410    517   
            .get(&head)
  411    518   
            .expect("group demand head disappeared");
  412         -
        let DemandResidence::Queued { demand, .. } = &record.residence else {
         519  +
        let DemandScheduleState::Queued { demand, .. } = &record.schedule_state else {
  413    520   
            return None;
  414    521   
        };
  415    522   
        let DemandState::Active {
  416         -
            head: requirement,
         523  +
            requirement,
  417    524   
            eligibility_group,
  418    525   
        } = &record.latest.state
  419    526   
        else {
  420    527   
            unreachable!("queued group demand became inactive");
  421    528   
        };
  422    529   
        debug_assert_eq!(eligibility_group, group);
  423    530   
        Some(QueuedDemand {
  424         -
            requesting_partition: head,
         531  +
            requester: head,
  425    532   
            demand: *demand,
  426    533   
            requirement: *requirement,
  427    534   
            eligibility_group: eligibility_group.clone(),
  428    535   
        })
  429    536   
    }
  430    537   
  431    538   
    /// Returns the latest eligibility group retained for one cell.
  432         -
    pub(super) fn group_for(&self, requesting_partition: &PartitionId) -> Option<EligibilityGroup> {
         539  +
    pub(super) fn group_for(&self, requester: &PartitionId) -> Option<EligibilityGroup> {
  433    540   
        self.records
  434         -
            .get(requesting_partition)
  435         -
            .and_then(|record| record.group.clone())
         541  +
            .get(requester)
         542  +
            .and_then(|record| record.eligibility_group.clone())
  436    543   
    }
  437    544   
  438    545   
    /// Returns whether `requesting_partition` still has this demand queued for a new action.
  439         -
    pub(super) fn is_current_queued(
  440         -
        &self,
  441         -
        requesting_partition: &PartitionId,
  442         -
        demand: DemandId,
  443         -
    ) -> bool {
  444         -
        self.records
  445         -
            .get(requesting_partition)
  446         -
            .is_some_and(|record| {
  447         -
                record.latest.id == demand
  448         -
                    && record.latest.is_active()
  449         -
                    && matches!(
  450         -
                        record.residence,
  451         -
                        DemandResidence::Queued {
  452         -
                            demand: current,
  453         -
                            ..
  454         -
                        } if current == demand
  455         -
                    )
  456         -
            })
         546  +
    pub(super) fn is_current_queued(&self, requester: &PartitionId, demand: DemandId) -> bool {
         547  +
        self.records.get(requester).is_some_and(|record| {
         548  +
            record.latest.id == demand
         549  +
                && record.latest.is_active()
         550  +
                && matches!(
         551  +
                    record.schedule_state,
         552  +
                    DemandScheduleState::Queued {
         553  +
                        demand: current,
         554  +
                        ..
         555  +
                    } if current == demand
         556  +
                )
         557  +
        })
  457    558   
    }
  458    559   
  459         -
    /// Fences one reuse operation's demand while it remains the origin-order head.
  460         -
    pub(super) fn reserve_reuse_demand(
         560  +
    /// Assigns exact origin-head demand after an H1 match resolves.
         561  +
    pub(super) fn prepare_h1_assignment(
  461    562   
        &mut self,
  462         -
        requesting_partition: &PartitionId,
         563  +
        requester: &PartitionId,
  463    564   
        demand: DemandId,
  464         -
        delivery: DeliveryId,
  465         -
    ) -> Option<ScheduledDemand> {
  466         -
        if !self.is_current_queued(requesting_partition, demand) {
         565  +
        assignment_id: DemandAssignmentId,
         566  +
    ) -> Option<DemandAssignment> {
         567  +
        if !self.is_current_queued(requester, demand) || self.origin_order.head()? != *requester {
  467    568   
            return None;
  468    569   
        }
  469         -
        let head = self.origin_order.head()?;
  470         -
        if head != *requesting_partition {
  471         -
            return None;
  472         -
        }
  473         -
        self.reserve_origin_head(delivery)
         570  +
        self.prepare_assignment(*requester, assignment_id, DemandOrder::Origin)
  474    571   
    }
  475    572   
  476         -
    /// Fences one eligibility-group head for an H2 publication.
  477         -
    pub(super) fn reserve_group_head(
         573  +
    /// Assigns one exact eligibility-group head to an H2 route.
         574  +
    pub(super) fn prepare_group_assignment(
  478    575   
        &mut self,
  479         -
        group: &EligibilityGroup,
  480         -
        requesting_partition: &PartitionId,
         576  +
        eligibility_group: &EligibilityGroup,
         577  +
        requester: &PartitionId,
  481    578   
        demand: DemandId,
  482         -
        delivery: DeliveryId,
  483         -
    ) -> Option<ScheduledDemand> {
  484         -
        if !self.is_current_queued(requesting_partition, demand)
  485         -
            || self.group_orders.get(group)?.head() != Some(*requesting_partition)
         579  +
        assignment_id: DemandAssignmentId,
         580  +
    ) -> Option<DemandAssignment> {
         581  +
        if !self.is_current_queued(requester, demand)
         582  +
            || self.group_orders.get(eligibility_group)?.head() != Some(*requester)
  486    583   
        {
  487    584   
            return None;
  488    585   
        }
  489         -
        self.reserve(*requesting_partition, delivery, DeliveryView::Group)
         586  +
        self.prepare_assignment(*requester, assignment_id, DemandOrder::Group)
  490    587   
    }
  491    588   
  492         -
    /// Changes the origin head into a delivery fence at the same positions.
  493         -
    pub(super) fn reserve_origin_head(&mut self, delivery: DeliveryId) -> Option<ScheduledDemand> {
  494         -
        let head = self.origin_order.head()?;
  495         -
        self.reserve(head, delivery, DeliveryView::Origin)
         589  +
    /// Assigns the origin-order head to one capacity delivery.
         590  +
    pub(super) fn prepare_origin_assignment(
         591  +
        &mut self,
         592  +
        assignment_id: DemandAssignmentId,
         593  +
    ) -> Option<DemandAssignment> {
         594  +
        let requester = self.origin_order.head()?;
         595  +
        self.prepare_assignment(requester, assignment_id, DemandOrder::Origin)
  496    596   
    }
  497    597   
  498         -
    /// Changes one queued demand into a delivery fence.
  499         -
    fn reserve(
         598  +
    fn prepare_assignment(
  500    599   
        &mut self,
  501         -
        requesting_partition: PartitionId,
  502         -
        delivery: DeliveryId,
  503         -
        view: DeliveryView,
  504         -
    ) -> Option<ScheduledDemand> {
         600  +
        requester: PartitionId,
         601  +
        assignment_id: DemandAssignmentId,
         602  +
        selected_order: DemandOrder,
         603  +
    ) -> Option<DemandAssignment> {
  505    604   
        let record = self
  506    605   
            .records
  507         -
            .get_mut(&requesting_partition)
         606  +
            .get_mut(&requester)
  508    607   
            .expect("order head disappeared");
  509         -
        let residence = std::mem::replace(&mut record.residence, DemandResidence::Idle);
  510         -
        match residence {
  511         -
            DemandResidence::Queued { demand, links } => {
         608  +
        let schedule_state =
         609  +
            std::mem::replace(&mut record.schedule_state, DemandScheduleState::Unscheduled);
         610  +
        match schedule_state {
         611  +
            DemandScheduleState::Queued { demand, links } => {
  512    612   
                debug_assert_eq!(record.latest.id, demand);
  513    613   
                debug_assert!(record.latest.is_active());
  514         -
                record.residence = DemandResidence::Delivering {
         614  +
                let assignment = DemandAssignment {
         615  +
                    id: assignment_id,
         616  +
                    requester,
  515    617   
                    demand,
         618  +
                };
         619  +
                record.schedule_state = DemandScheduleState::PendingAssignment {
         620  +
                    assignment: assignment.clone(),
  516    621   
                    version: record.latest.version,
  517         -
                    delivery,
  518         -
                    view,
         622  +
                    selected_order,
  519    623   
                    links,
  520    624   
                };
  521    625   
                self.assert_consistent();
  522         -
                Some(ScheduledDemand {
  523         -
                    requesting_partition,
  524         -
                    demand,
  525         -
                })
         626  +
                Some(assignment)
  526    627   
            }
  527         -
            residence => {
  528         -
                record.residence = residence;
         628  +
            schedule_state => {
         629  +
                record.schedule_state = schedule_state;
  529    630   
                None
  530    631   
            }
  531    632   
        }
  532    633   
    }
  533    634   
  534         -
    /// Returns whether the test-observed delivery fence still names this demand.
  535         -
    ///
  536         -
    /// Production reservation revalidates the demand identity through
  537         -
    /// `AcquisitionQueue::reserve_delivery_waiter`; this helper only exposes
  538         -
    /// admission-side fence state to focused tests.
  539    635   
    #[cfg(test)]
  540         -
    pub(super) fn delivery_is_current(
  541         -
        &self,
  542         -
        delivery: DeliveryId,
  543         -
        requesting_partition: &PartitionId,
  544         -
        demand: DemandId,
  545         -
    ) -> bool {
  546         -
        let Some(record) = self.records.get(requesting_partition) else {
         636  +
    pub(super) fn assignment_is_current(&self, assignment: &DemandAssignment) -> bool {
         637  +
        let Some(record) = self.records.get(&assignment.requester) else {
  547    638   
            return false;
  548    639   
        };
  549    640   
        matches!(
  550         -
            &record.residence,
  551         -
            DemandResidence::Delivering {
  552         -
                demand: current_demand,
  553         -
                delivery: current_delivery,
  554         -
                ..
  555         -
            } if *current_delivery == delivery
  556         -
                && *current_demand == demand
  557         -
                && record.latest.id == demand
  558         -
                && record.latest.is_active()
         641  +
            &record.schedule_state,
         642  +
            DemandScheduleState::PendingAssignment { assignment: current, .. }
         643  +
                if current == assignment
         644  +
                    && record.latest.id == assignment.demand
         645  +
                    && record.latest.is_active()
  559    646   
        )
  560    647   
    }
  561    648   
  562         -
    /// Closes one delivery fence and resolves the demand's next residence.
  563         -
    ///
  564         -
    /// `Accepted` consumes the delivered generation and installs a newer
  565         -
    /// successor when the requesting cell supplied one. `RetrySameResidence`
  566         -
    /// restores the same generation at its existing order position when it
  567         -
    /// remains live; if it was replaced, the latest active generation is
  568         -
    /// appended as new demand. `Rejected` removes the fenced generation after
  569         -
    /// its permit has been refunnelled and applies the same successor
  570         -
    /// arbitration as acceptance.
  571         -
    pub(super) fn finish_delivery(
         649  +
    /// Settles one detached assignment and resolves the demand's next state.
         650  +
    pub(super) fn settle_assignment(
  572    651   
        &mut self,
  573         -
        delivery: DeliveryId,
  574         -
        requesting_partition: &PartitionId,
  575         -
        result: DeliveryAckResult,
         652  +
        assignment: &DemandAssignment,
         653  +
        outcome: DemandAssignmentOutcome,
  576    654   
    ) {
  577         -
        let Some(record) = self.records.get(requesting_partition) else {
         655  +
        let requester = &assignment.requester;
         656  +
        let Some(record) = self.records.get(requester) else {
  578    657   
            return;
  579    658   
        };
  580         -
        let delivered_demand = match &record.residence {
  581         -
            DemandResidence::Delivering {
  582         -
                demand,
         659  +
        let assigned = match &record.schedule_state {
         660  +
            DemandScheduleState::PendingAssignment {
         661  +
                assignment: current,
  583    662   
                version,
  584         -
                delivery: current,
  585    663   
                ..
  586         -
            } if *current == delivery => (*demand, *version),
         664  +
            } if current == assignment => (current.demand, *version),
  587    665   
            _ => return,
  588    666   
        };
  589         -
        let (delivered_demand, delivered_version) = delivered_demand;
         667  +
        let (assigned_demand, assigned_version) = assigned;
  590    668   
  591         -
        match result {
  592         -
            DeliveryAckResult::RetrySameResidence => {
         669  +
        match outcome {
         670  +
            DemandAssignmentOutcome::RetrySamePosition => {
  593    671   
                let record = self
  594    672   
                    .records
  595         -
                    .get(requesting_partition)
  596         -
                    .expect("delivery demand record disappeared");
  597         -
                if record.latest.id == delivered_demand && record.latest.is_active() {
         673  +
                    .get(requester)
         674  +
                    .expect("assigned demand record disappeared");
         675  +
                if record.latest.id == assigned_demand && record.latest.is_active() {
  598    676   
                    let record = self
  599    677   
                        .records
  600         -
                        .get_mut(requesting_partition)
  601         -
                        .expect("delivery demand record disappeared");
  602         -
                    let residence = std::mem::replace(&mut record.residence, DemandResidence::Idle);
  603         -
                    let DemandResidence::Delivering {
  604         -
                        demand,
  605         -
                        version: _,
  606         -
                        delivery: current,
  607         -
                        view: _,
         678  +
                        .get_mut(requester)
         679  +
                        .expect("assigned demand record disappeared");
         680  +
                    let schedule_state = std::mem::replace(
         681  +
                        &mut record.schedule_state,
         682  +
                        DemandScheduleState::Unscheduled,
         683  +
                    );
         684  +
                    let DemandScheduleState::PendingAssignment {
         685  +
                        assignment: current,
  608    686   
                        links,
  609         -
                    } = residence
         687  +
                        ..
         688  +
                    } = schedule_state
  610    689   
                    else {
  611         -
                        unreachable!("delivery fence disappeared");
         690  +
                        unreachable!("demand assignment disappeared");
         691  +
                    };
         692  +
                    debug_assert_eq!(current, *assignment);
         693  +
                    record.schedule_state = DemandScheduleState::Queued {
         694  +
                        demand: current.demand,
         695  +
                        links,
  612    696   
                    };
  613         -
                    debug_assert_eq!(current, delivery);
  614         -
                    record.residence = DemandResidence::Queued { demand, links };
  615    697   
                    self.assert_consistent();
  616    698   
                    return;
  617    699   
                }
  618    700   
  619         -
                self.remove_from_order(requesting_partition);
         701  +
                self.remove_from_order(requester);
  620    702   
                if self
  621    703   
                    .records
  622         -
                    .get(requesting_partition)
  623         -
                    .expect("delivery demand record disappeared")
         704  +
                    .get(requester)
         705  +
                    .expect("assigned demand record disappeared")
  624    706   
                    .latest
  625    707   
                    .is_active()
  626    708   
                {
  627         -
                    self.enqueue(*requesting_partition);
         709  +
                    self.enqueue(*requester);
  628    710   
                }
  629    711   
            }
  630         -
            DeliveryAckResult::Accepted { successor }
  631         -
            | DeliveryAckResult::Rejected { successor } => {
  632         -
                self.remove_from_order(requesting_partition);
         712  +
            DemandAssignmentOutcome::Accepted { successor }
         713  +
            | DemandAssignmentOutcome::Refused { successor } => {
         714  +
                self.remove_from_order(requester);
  633    715   
  634    716   
                let install_successor = successor.as_ref().is_some_and(|successor| {
  635         -
                    successor.id > delivered_demand
         717  +
                    successor.id > assigned_demand
  636    718   
                        && successor.is_newer_than(
  637    719   
                            &self
  638    720   
                                .records
  639         -
                                .get(requesting_partition)
  640         -
                                .expect("delivery demand record disappeared")
         721  +
                                .get(requester)
         722  +
                                .expect("assigned demand record disappeared")
  641    723   
                                .latest,
  642    724   
                        )
  643    725   
                });
  644    726   
                if install_successor {
  645    727   
                    self.records
  646         -
                        .get_mut(requesting_partition)
  647         -
                        .expect("delivery demand record disappeared")
         728  +
                        .get_mut(requester)
         729  +
                        .expect("assigned demand record disappeared")
  648    730   
                        .latest = successor.expect("validated successor disappeared");
  649    731   
                } else {
  650    732   
                    let retirement =
  651         -
                        DemandSnapshot::inactive(delivered_demand, delivered_version.next());
         733  +
                        DemandSnapshot::inactive(assigned_demand, assigned_version.next());
  652    734   
                    let record = self
  653    735   
                        .records
  654         -
                        .get_mut(requesting_partition)
  655         -
                        .expect("delivery demand record disappeared");
         736  +
                        .get_mut(requester)
         737  +
                        .expect("assigned demand record disappeared");
  656    738   
                    if retirement.is_newer_than(&record.latest) {
  657    739   
                        record.latest = retirement;
  658    740   
                    }
  659    741   
                }
  660    742   
  661    743   
                if self
  662    744   
                    .records
  663         -
                    .get(requesting_partition)
  664         -
                    .expect("delivery demand record disappeared")
         745  +
                    .get(requester)
         746  +
                    .expect("assigned demand record disappeared")
  665    747   
                    .latest
  666    748   
                    .is_active()
  667    749   
                {
  668         -
                    self.enqueue(*requesting_partition);
         750  +
                    self.enqueue(*requester);
  669    751   
                }
  670    752   
            }
  671    753   
        }
  672    754   
        self.assert_consistent();
  673    755   
    }
  674    756   
  675         -
    /// Returns the latest complete snapshot retained for `requesting_partition`.
         757  +
    /// Returns the latest complete snapshot retained for `requester`.
  676    758   
    #[cfg(test)]
  677         -
    pub(super) fn latest_for_test(
  678         -
        &self,
  679         -
        requesting_partition: &PartitionId,
  680         -
    ) -> Option<&DemandSnapshot> {
  681         -
        self.records
  682         -
            .get(requesting_partition)
  683         -
            .map(|record| &record.latest)
         759  +
    pub(super) fn latest_for_test(&self, requester: &PartitionId) -> Option<&DemandSnapshot> {
         760  +
        self.records.get(requester).map(|record| &record.latest)
  684    761   
    }
  685    762   
  686    763   
    #[cfg(test)]
  687    764   
    pub(super) fn len(&self) -> usize {
  688    765   
        self.origin_order.len()
  689    766   
    }
  690    767   
  691    768   
    #[cfg(test)]
  692    769   
    pub(super) fn queued_len(&self) -> usize {
  693    770   
        self.records
  694    771   
            .values()
  695         -
            .filter(|record| matches!(&record.residence, DemandResidence::Queued { .. }))
         772  +
            .filter(|record| matches!(&record.schedule_state, DemandScheduleState::Queued { .. }))
  696    773   
            .count()
  697    774   
    }
  698    775   
  699    776   
    #[cfg(test)]
  700         -
    pub(super) fn delivering_len(&self) -> usize {
         777  +
    pub(super) fn pending_assignment_count(&self) -> usize {
  701    778   
        self.records
  702    779   
            .values()
  703         -
            .filter(|record| matches!(&record.residence, DemandResidence::Delivering { .. }))
         780  +
            .filter(|record| {
         781  +
                matches!(
         782  +
                    &record.schedule_state,
         783  +
                    DemandScheduleState::PendingAssignment { .. }
         784  +
                )
         785  +
            })
  704    786   
            .count()
  705    787   
    }
  706    788   
  707         -
    /// Checks residence, link, length, group, and fence relationships.
         789  +
    /// Checks residence, link, length, group, and assignment relationships.
  708    790   
    fn assert_consistent(&self) {
  709    791   
        #[cfg(any(debug_assertions, test))]
  710    792   
        {
  711    793   
            if std::thread::panicking() {
  712    794   
                return;
  713    795   
            }
  714    796   
            self.assert_consistent_debug();
  715    797   
        }
  716    798   
    }
  717    799   
  718    800   
    #[cfg(any(debug_assertions, test))]
  719    801   
    fn assert_consistent_debug(&self) {
  720    802   
        let ordered_records = self
  721    803   
            .records
  722    804   
            .values()
  723         -
            .filter(|record| record.residence.links(DemandOrderView::Origin).is_some())
         805  +
            .filter(|record| record.schedule_state.links(DemandOrder::Origin).is_some())
  724    806   
            .count();
  725         -
        let origin_deliveries = self
         807  +
        let origin_assignments = self
  726    808   
            .records
  727    809   
            .values()
  728    810   
            .filter(|record| {
  729    811   
                matches!(
  730         -
                    record.residence,
  731         -
                    DemandResidence::Delivering {
  732         -
                        view: DeliveryView::Origin,
         812  +
                    record.schedule_state,
         813  +
                    DemandScheduleState::PendingAssignment {
         814  +
                        selected_order: DemandOrder::Origin,
  733    815   
                        ..
  734    816   
                    }
  735    817   
                )
  736    818   
            })
  737    819   
            .count();
  738    820   
        assert!(
  739         -
            origin_deliveries <= 1,
  740         -
            "more than one origin delivery fence was active"
         821  +
            origin_assignments <= 1,
         822  +
            "more than one origin demand assignment was active"
  741    823   
        );
  742    824   
        self.origin_order.assert_consistent(
  743    825   
            ordered_records,
  744    826   
            self.records.len(),
  745    827   
            "origin demand order",
  746    828   
            |requesting_partition| {
  747    829   
                let record = self
  748    830   
                    .records
  749    831   
                    .get(&requesting_partition)
  750    832   
                    .expect("origin-ordered demand disappeared");
  751         -
                match &record.residence {
  752         -
                    DemandResidence::Idle => {
  753         -
                        unreachable!("origin-ordered demand became idle")
         833  +
                match &record.schedule_state {
         834  +
                    DemandScheduleState::Unscheduled => {
         835  +
                        unreachable!("origin-ordered demand became unscheduled")
  754    836   
                    }
  755         -
                    DemandResidence::Queued { demand, .. } => {
         837  +
                    DemandScheduleState::Queued { demand, .. } => {
  756    838   
                        assert!(record.latest.is_active(), "queued demand became inactive");
  757    839   
                        assert_eq!(
  758    840   
                            record.latest.id, *demand,
  759         -
                            "queued residence did not match its latest demand"
         841  +
                            "queued schedule state did not match its latest demand"
  760    842   
                        );
  761    843   
                    }
  762         -
                    DemandResidence::Delivering { demand, view, .. } => {
  763         -
                        if *view == DeliveryView::Origin {
         844  +
                    DemandScheduleState::PendingAssignment {
         845  +
                        assignment,
         846  +
                        selected_order,
         847  +
                        ..
         848  +
                    } => {
         849  +
                        if *selected_order == DemandOrder::Origin {
  764    850   
                            assert_eq!(
  765    851   
                                Some(requesting_partition),
  766    852   
                                self.origin_order.head(),
  767         -
                                "origin delivery fence moved away from its head"
         853  +
                                "origin demand assignment moved away from its head"
  768    854   
                            );
  769    855   
                        }
  770    856   
                        assert!(
  771         -
                            record.latest.id >= *demand,
  772         -
                            "delivery fence named a future demand"
         857  +
                            record.latest.id >= assignment.demand,
         858  +
                            "demand assignment named a future demand"
  773    859   
                        );
  774    860   
                    }
  775    861   
                }
  776    862   
                *record
  777         -
                    .residence
  778         -
                    .links(DemandOrderView::Origin)
         863  +
                    .schedule_state
         864  +
                    .links(DemandOrder::Origin)
  779    865   
                    .expect("origin-ordered demand lost its links")
  780    866   
            },
  781    867   
        );
  782    868   
  783    869   
        let group_ordered_records = self
  784    870   
            .records
  785    871   
            .values()
  786         -
            .filter(|record| record.residence.links(DemandOrderView::Group).is_some())
         872  +
            .filter(|record| record.schedule_state.links(DemandOrder::Group).is_some())
  787    873   
            .count();
  788    874   
        for record in self
  789    875   
            .records
  790    876   
            .values()
  791         -
            .filter(|record| record.residence.links(DemandOrderView::Group).is_some())
         877  +
            .filter(|record| record.schedule_state.links(DemandOrder::Group).is_some())
  792    878   
        {
  793    879   
            let group = record
  794         -
                .group
         880  +
                .eligibility_group
  795    881   
                .as_ref()
  796    882   
                .expect("group-ordered demand lost its eligibility group");
  797    883   
            assert!(
  798    884   
                self.group_orders.contains_key(group),
  799    885   
                "ordered demand lost its eligibility-group order"
  800    886   
            );
  801    887   
        }
  802    888   
        assert_eq!(
  803    889   
            group_ordered_records,
  804    890   
            self.group_orders
  805    891   
                .values()
  806    892   
                .map(IntrusiveOrder::len)
  807    893   
                .sum::<usize>(),
  808    894   
            "eligibility-group orders did not contain every ordered demand"
  809    895   
        );
  810    896   
  811    897   
        for (group, order) in &self.group_orders {
  812         -
            let group_deliveries = self
         898  +
            let group_assignments = self
  813    899   
                .records
  814    900   
                .values()
  815    901   
                .filter(|record| {
  816         -
                    record.group.as_ref() == Some(group)
         902  +
                    record.eligibility_group.as_ref() == Some(group)
  817    903   
                        && matches!(
  818         -
                            record.residence,
  819         -
                            DemandResidence::Delivering {
  820         -
                                view: DeliveryView::Group,
         904  +
                            record.schedule_state,
         905  +
                            DemandScheduleState::PendingAssignment {
         906  +
                                selected_order: DemandOrder::Group,
  821    907   
                                ..
  822    908   
                            }
  823    909   
                        )
  824    910   
                })
  825    911   
                .count();
  826    912   
            assert!(
  827         -
                group_deliveries <= 1,
  828         -
                "more than one group delivery fence was active"
         913  +
                group_assignments <= 1,
         914  +
                "more than one group demand assignment was active"
  829    915   
            );
  830    916   
            let expected = self
  831    917   
                .records
  832    918   
                .values()
  833    919   
                .filter(|record| {
  834         -
                    record.residence.links(DemandOrderView::Group).is_some()
  835         -
                        && record.group.as_ref() == Some(group)
         920  +
                    record.schedule_state.links(DemandOrder::Group).is_some()
         921  +
                        && record.eligibility_group.as_ref() == Some(group)
  836    922   
                })
  837    923   
                .count();
  838    924   
            order.assert_consistent(
  839    925   
                expected,
  840    926   
                self.records.len(),
  841    927   
                "eligibility-group demand order",
  842    928   
                |requesting_partition| {
  843    929   
                    let record = self
  844    930   
                        .records
  845    931   
                        .get(&requesting_partition)
  846    932   
                        .expect("group-ordered demand disappeared");
  847    933   
                    assert_eq!(
  848         -
                        record.group.as_ref(),
         934  +
                        record.eligibility_group.as_ref(),
  849    935   
                        Some(group),
  850    936   
                        "demand occupied the wrong eligibility-group order"
  851    937   
                    );
  852    938   
                    if matches!(
  853         -
                        record.residence,
  854         -
                        DemandResidence::Delivering {
  855         -
                            view: DeliveryView::Group,
         939  +
                        record.schedule_state,
         940  +
                        DemandScheduleState::PendingAssignment {
         941  +
                            selected_order: DemandOrder::Group,
  856    942   
                            ..
  857    943   
                        }
  858    944   
                    ) {
  859    945   
                        assert_eq!(
  860    946   
                            Some(requesting_partition),
  861    947   
                            order.head(),
  862         -
                            "group publication fence moved away from its head"
         948  +
                            "group route assignment moved away from its head"
  863    949   
                        );
  864    950   
                    }
  865    951   
                    *record
  866         -
                        .residence
  867         -
                        .links(DemandOrderView::Group)
         952  +
                        .schedule_state
         953  +
                        .links(DemandOrder::Group)
  868    954   
                        .expect("group-ordered demand lost its links")
  869    955   
                },
  870    956   
            );
  871    957   
        }
  872    958   
    }
  873    959   
}
  874    960   
  875    961   
#[cfg(all(test, not(smithy_http_client_loom)))]
  876    962   
mod tests {
  877    963   
    use super::*;
  878    964   
  879    965   
    fn partition(index: usize) -> PartitionId {
  880    966   
        PartitionId::from_index(index)
  881    967   
    }
  882    968   
  883    969   
    fn active(id: u64, group: EligibilityGroup) -> DemandSnapshot {
  884    970   
        DemandSnapshot::active(
  885    971   
            DemandId::from_u64(id),
  886    972   
            super::super::SnapshotVersion::INITIAL,
  887    973   
            ProtocolRequirement::H1Compatible,
  888    974   
            group,
  889    975   
        )
  890    976   
    }
  891    977   
  892    978   
    #[test]
  893    979   
    fn origin_and_group_orders_repair_independently() {
  894    980   
        let pool = EligibilityGroup::Pool;
  895    981   
        let isolated = EligibilityGroup::Partition(partition(2));
  896    982   
        let mut schedule = DemandSchedule::default();
  897         -
        schedule.publish(partition(1), active(1, pool.clone()));
  898         -
        schedule.publish(partition(2), active(2, isolated.clone()));
  899         -
        schedule.publish(partition(3), active(3, pool.clone()));
         983  +
        schedule.apply_snapshot(partition(1), active(1, pool.clone()));
         984  +
        schedule.apply_snapshot(partition(2), active(2, isolated.clone()));
         985  +
        schedule.apply_snapshot(partition(3), active(3, pool.clone()));
  900    986   
  901    987   
        assert_eq!(
  902    988   
            Some(partition(1)),
  903         -
            schedule.queued_head().map(|head| head.requesting_partition)
         989  +
            schedule.queued_head().map(|head| head.requester)
  904    990   
        );
  905    991   
        assert_eq!(
  906    992   
            Some(partition(1)),
  907         -
            schedule
  908         -
                .queued_group_head(&pool)
  909         -
                .map(|head| head.requesting_partition)
         993  +
            schedule.queued_group_head(&pool).map(|head| head.requester)
  910    994   
        );
  911    995   
        assert_eq!(
  912    996   
            Some(partition(2)),
  913    997   
            schedule
  914    998   
                .queued_group_head(&isolated)
  915         -
                .map(|head| head.requesting_partition)
         999  +
                .map(|head| head.requester)
  916   1000   
        );
  917   1001   
  918         -
        let delivery = DeliveryId(7);
  919         -
        schedule
  920         -
            .reserve_group_head(&pool, &partition(1), DemandId::from_u64(1), delivery)
        1002  +
        let assignment = schedule
        1003  +
            .prepare_group_assignment(
        1004  +
                &pool,
        1005  +
                &partition(1),
        1006  +
                DemandId::from_u64(1),
        1007  +
                DemandAssignmentId(7),
        1008  +
            )
  921   1009   
            .expect("pool group head should reserve");
  922   1010   
        assert!(schedule.queued_group_head(&pool).is_none());
  923   1011   
        assert_eq!(
  924   1012   
            Some(partition(2)),
  925   1013   
            schedule
  926   1014   
                .queued_group_head(&isolated)
  927         -
                .map(|head| head.requesting_partition)
        1015  +
                .map(|head| head.requester)
  928   1016   
        );
  929   1017   
        assert!(schedule.queued_head().is_none());
  930   1018   
  931         -
        schedule.finish_delivery(
  932         -
            delivery,
  933         -
            &partition(1),
  934         -
            DeliveryAckResult::Accepted { successor: None },
        1019  +
        schedule.settle_assignment(
        1020  +
            &assignment,
        1021  +
            DemandAssignmentOutcome::Accepted { successor: None },
  935   1022   
        );
  936   1023   
        assert_eq!(
  937   1024   
            Some(partition(2)),
  938         -
            schedule.queued_head().map(|head| head.requesting_partition)
        1025  +
            schedule.queued_head().map(|head| head.requester)
  939   1026   
        );
  940   1027   
        assert_eq!(
  941   1028   
            Some(partition(3)),
  942         -
            schedule
  943         -
                .queued_group_head(&pool)
  944         -
                .map(|head| head.requesting_partition)
        1029  +
            schedule.queued_group_head(&pool).map(|head| head.requester)
  945   1030   
        );
  946   1031   
    }
  947   1032   
  948   1033   
    #[test]
  949   1034   
    fn retry_preserves_both_order_positions() {
  950   1035   
        let group = EligibilityGroup::Pool;
  951   1036   
        let mut schedule = DemandSchedule::default();
  952         -
        schedule.publish(partition(1), active(1, group.clone()));
  953         -
        schedule.publish(partition(2), active(2, group.clone()));
        1037  +
        schedule.apply_snapshot(partition(1), active(1, group.clone()));
        1038  +
        schedule.apply_snapshot(partition(2), active(2, group.clone()));
  954   1039   
  955         -
        let delivery = DeliveryId(9);
  956         -
        schedule
  957         -
            .reserve_group_head(&group, &partition(1), DemandId::from_u64(1), delivery)
        1040  +
        let assignment = schedule
        1041  +
            .prepare_group_assignment(
        1042  +
                &group,
        1043  +
                &partition(1),
        1044  +
                DemandId::from_u64(1),
        1045  +
                DemandAssignmentId(9),
        1046  +
            )
  958   1047   
            .expect("group head should reserve");
  959         -
        schedule.finish_delivery(
  960         -
            delivery,
  961         -
            &partition(1),
  962         -
            DeliveryAckResult::RetrySameResidence,
  963         -
        );
        1048  +
        schedule.settle_assignment(&assignment, DemandAssignmentOutcome::RetrySamePosition);
  964   1049   
  965   1050   
        assert_eq!(
  966   1051   
            Some(partition(1)),
  967         -
            schedule.queued_head().map(|head| head.requesting_partition)
        1052  +
            schedule.queued_head().map(|head| head.requester)
  968   1053   
        );
  969   1054   
        assert_eq!(
  970   1055   
            Some(partition(1)),
  971   1056   
            schedule
  972   1057   
                .queued_group_head(&group)
  973         -
                .map(|head| head.requesting_partition)
        1058  +
                .map(|head| head.requester)
  974   1059   
        );
  975   1060   
    }
  976   1061   
  977   1062   
    #[test]
  978         -
    fn inactive_snapshot_during_group_fence_retires_without_losing_group() {
        1063  +
    fn inactive_snapshot_during_group_assignment_retires_without_losing_group() {
  979   1064   
        let group = EligibilityGroup::Pool;
  980   1065   
        let mut schedule = DemandSchedule::default();
  981         -
        schedule.publish(partition(1), active(1, group.clone()));
  982         -
        let delivery = DeliveryId(11);
  983         -
        schedule
  984         -
            .reserve_group_head(&group, &partition(1), DemandId::from_u64(1), delivery)
        1066  +
        schedule.apply_snapshot(partition(1), active(1, group.clone()));
        1067  +
        let assignment = schedule
        1068  +
            .prepare_group_assignment(
        1069  +
                &group,
        1070  +
                &partition(1),
        1071  +
                DemandId::from_u64(1),
        1072  +
                DemandAssignmentId(11),
        1073  +
            )
  985   1074   
            .expect("group head should reserve");
  986         -
        schedule.publish(
        1075  +
        schedule.apply_snapshot(
  987   1076   
            partition(1),
  988   1077   
            DemandSnapshot::inactive(
  989   1078   
                DemandId::from_u64(1),
  990   1079   
                super::super::SnapshotVersion::INITIAL.next(),
  991   1080   
            ),
  992   1081   
        );
  993   1082   
  994         -
        schedule.finish_delivery(
  995         -
            delivery,
  996         -
            &partition(1),
  997         -
            DeliveryAckResult::RetrySameResidence,
  998         -
        );
        1083  +
        schedule.settle_assignment(&assignment, DemandAssignmentOutcome::RetrySamePosition);
  999   1084   
        assert_eq!(0, schedule.len());
 1000   1085   
        assert!(schedule.queued_group_head(&group).is_none());
 1001   1086   
    }
 1002   1087   
 1003   1088   
    #[test]
 1004         -
    fn accepted_fence_does_not_retire_a_newer_active_publication() {
        1089  +
    fn accepted_assignment_does_not_retire_a_newer_active_snapshot() {
 1005   1090   
        let group = EligibilityGroup::Pool;
 1006   1091   
        let partition = partition(1);
 1007   1092   
        let demand = DemandId::from_u64(1);
 1008   1093   
        let initial = super::super::SnapshotVersion::INITIAL;
 1009   1094   
        let mut schedule = DemandSchedule::default();
 1010         -
        schedule.publish(
        1095  +
        schedule.apply_snapshot(
 1011   1096   
            partition,
 1012   1097   
            DemandSnapshot::active(
 1013   1098   
                demand,
 1014   1099   
                initial,
 1015   1100   
                ProtocolRequirement::H2Required,
 1016   1101   
                group.clone(),
 1017   1102   
            ),
 1018   1103   
        );
 1019         -
        let delivery = DeliveryId(12);
 1020         -
        schedule
 1021         -
            .reserve_group_head(&group, &partition, demand, delivery)
        1104  +
        let assignment = schedule
        1105  +
            .prepare_group_assignment(&group, &partition, demand, DemandAssignmentId(12))
 1022   1106   
            .expect("group head should reserve");
 1023   1107   
        let republished = DemandSnapshot::active(
 1024   1108   
            demand,
 1025   1109   
            initial.next().next(),
 1026   1110   
            ProtocolRequirement::H2Required,
 1027   1111   
            group.clone(),
 1028   1112   
        );
 1029         -
        schedule.publish(partition, republished.clone());
        1113  +
        schedule.apply_snapshot(partition, republished.clone());
 1030   1114   
 1031         -
        schedule.finish_delivery(
 1032         -
            delivery,
 1033         -
            &partition,
 1034         -
            DeliveryAckResult::Accepted { successor: None },
        1115  +
        schedule.settle_assignment(
        1116  +
            &assignment,
        1117  +
            DemandAssignmentOutcome::Accepted { successor: None },
 1035   1118   
        );
 1036   1119   
 1037   1120   
        assert_eq!(Some(&republished), schedule.latest_for_test(&partition));
 1038   1121   
        assert_eq!(
 1039   1122   
            Some(partition),
 1040         -
            schedule.queued_head().map(|head| head.requesting_partition)
        1123  +
            schedule.queued_head().map(|head| head.requester)
 1041   1124   
        );
 1042   1125   
        assert_eq!(
 1043   1126   
            Some(partition),
 1044   1127   
            schedule
 1045   1128   
                .queued_group_head(&group)
 1046         -
                .map(|head| head.requesting_partition)
        1129  +
                .map(|head| head.requester)
 1047   1130   
        );
 1048   1131   
    }
 1049   1132   
 1050   1133   
    #[test]
 1051         -
    fn group_reservation_rejects_a_stale_demand_identity() {
        1134  +
    fn group_assignment_rejects_a_stale_demand_identity() {
 1052   1135   
        let group = EligibilityGroup::Pool;
 1053   1136   
        let partition = partition(1);
 1054   1137   
        let mut schedule = DemandSchedule::default();
 1055         -
        schedule.publish(partition, active(1, group.clone()));
 1056         -
        schedule.publish(partition, active(2, group.clone()));
        1138  +
        schedule.apply_snapshot(partition, active(1, group.clone()));
        1139  +
        schedule.apply_snapshot(partition, active(2, group.clone()));
 1057   1140   
 1058   1141   
        assert!(schedule
 1059         -
            .reserve_group_head(&group, &partition, DemandId::from_u64(1), DeliveryId(13),)
        1142  +
            .prepare_group_assignment(
        1143  +
                &group,
        1144  +
                &partition,
        1145  +
                DemandId::from_u64(1),
        1146  +
                DemandAssignmentId(13),
        1147  +
            )
 1060   1148   
            .is_none());
 1061   1149   
        assert_eq!(
 1062   1150   
            Some(DemandId::from_u64(2)),
 1063   1151   
            schedule
 1064   1152   
                .queued_group_head(&group)
 1065   1153   
                .map(|queued| queued.demand)
 1066   1154   
        );
 1067   1155   
    }
 1068   1156   
 1069   1157   
    #[test]
 1070         -
    fn stale_acknowledgement_does_not_close_a_newer_delivery_fence() {
        1158  +
    fn stale_settlement_does_not_close_a_newer_assignment() {
 1071   1159   
        let group = EligibilityGroup::Pool;
 1072   1160   
        let partition = partition(1);
 1073   1161   
        let demand = DemandId::from_u64(1);
 1074   1162   
        let mut schedule = DemandSchedule::default();
 1075         -
        schedule.publish(partition, active(1, group.clone()));
 1076         -
        schedule
 1077         -
            .reserve_group_head(&group, &partition, demand, DeliveryId(14))
        1163  +
        schedule.apply_snapshot(partition, active(1, group.clone()));
        1164  +
        let assignment = schedule
        1165  +
            .prepare_group_assignment(&group, &partition, demand, DemandAssignmentId(14))
 1078   1166   
            .expect("group head should reserve");
        1167  +
        let stale = DemandAssignment {
        1168  +
            id: DemandAssignmentId(15),
        1169  +
            requester: partition,
        1170  +
            demand,
        1171  +
        };
 1079   1172   
 1080         -
        schedule.finish_delivery(
 1081         -
            DeliveryId(15),
 1082         -
            &partition,
 1083         -
            DeliveryAckResult::Accepted { successor: None },
        1173  +
        schedule.settle_assignment(
        1174  +
            &stale,
        1175  +
            DemandAssignmentOutcome::Accepted { successor: None },
 1084   1176   
        );
 1085   1177   
 1086         -
        assert!(schedule.delivery_is_current(DeliveryId(14), &partition, demand));
 1087         -
        assert!(!schedule.delivery_is_current(DeliveryId(15), &partition, demand));
        1178  +
        assert!(schedule.assignment_is_current(&assignment));
        1179  +
        assert!(!schedule.assignment_is_current(&stale));
 1088   1180   
        assert_eq!(
 1089   1181   
            Some(&active(1, group)),
 1090   1182   
            schedule.latest_for_test(&partition)
 1091   1183   
        );
 1092   1184   
    }
 1093   1185   
 1094   1186   
    #[test]
 1095   1187   
    #[should_panic(expected = "ordered demand lost its eligibility-group order")]
 1096   1188   
    fn consistency_check_rejects_an_orphaned_group_link() {
 1097   1189   
        let group = EligibilityGroup::Pool;
 1098   1190   
        let mut schedule = DemandSchedule::default();
 1099         -
        schedule.publish(partition(1), active(1, group.clone()));
        1191  +
        schedule.apply_snapshot(partition(1), active(1, group.clone()));
 1100   1192   
 1101   1193   
        schedule.group_orders.remove(&group);
 1102   1194   
        schedule.assert_consistent();
 1103   1195   
    }
 1104   1196   
}