یک عامل صوتی ممکن است در یک نوبت چند درخواست ابزار بسازد. برای آزمودن مرز پذیرش این درخواست‌ها، می‌توان ظرفیت جهش و نرخ بازپرشدن بودجه را جدا تعریف کرد. این درس یک سطل توکن کوچک با زمان ساختگی می‌سازد و پاسخ‌هایش را با حساب دستی و مرجع کسری مستقل می‌سنجد. برنامه هیچ ابزار، صف، تماس یا سرویس واقعی اجرا نمی‌کند؛ accepted فقط تصمیم مدل دربارهٔ بودجهٔ فرضی است.

۱. ظرفیت جهش، نرخ پایدار و هزینهٔ درخواست را جدا کنیم

جداسازی ظرفیت جهش از نرخ بازپرشدن اعتبار
تصویر مفهومی: جداسازی ظرفیت جهش از نرخ بازپرشدن اعتبار؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

ظرفیت نمونه سه واحد بودجه و نرخ بازپرشدن دو واحد در ثانیه است. سطل در زمان صفر پُر شروع می‌شود. یک درخواست می‌تواند یک یا چند واحد هزینهٔ قراردادی داشته باشد؛ در مثال نخست، هزینه دو واحد است. این واحدها توکنِ مدل زبانی، هزینهٔ پولی یا مدت اجرای ابزار نیستند. وقتی همهٔ درخواست‌ها هزینهٔ یک داشته باشند، شمار واحد مصرف‌شده با شمار درخواست پذیرفته‌شده برابر می‌شود.

ضمیمهٔ A.4 در RFC 3290 مدلی ریاضی برای ظرفیت B، نرخ R و اعتبار موجود بیان می‌کند: اعتبار با زمان زیاد می‌شود، در B سقف می‌خورد و فقط برای ورودیِ پذیرفته‌شده کم می‌شود. آن سند دربارهٔ مدل شبکه است؛ ما واحد بودجهٔ درخواستِ ساختگی را انتخاب کرده‌ایم. این کد مسیریاب، پروتکل شبکه یا پیاده‌سازی سازگار با تمام آن سند نیست.

در شروع، سه درخواست تک‌واحدی در یک زمان می‌توانند پذیرفته شوند؛ چهارمی باید رد شود، هرچند نرخ بازپرشدن دو واحد در ثانیه است. ظرفیت اولیه امکان جهش می‌دهد. بنابراین عبارت «دو درخواست در ثانیه» بدون توضیح ظرفیت و هزینه، رفتار کوتاه‌مدت این مدل را کامل توصیف نمی‌کند. اندازه و نرخِ مثال، تنظیم پیشنهادی برای سامانهٔ واقعی شما نیستند.

۲. اعتبار صحیح را با زمان میلی‌ثانیه حساب کنیم

اعتبار صحیح و مرز زمان ساختگی پذیرش
تصویر مفهومی: اعتبار صحیح و مرز زمان ساختگی پذیرش؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

برای حفظ کسر واحدها، هر واحد را هزار میلی‌واحد می‌گیریم. ظرفیت سه، ۳۰۰۰ میلی‌واحد است. اگر نرخ دو واحد در ثانیه باشد، گذشت هر میلی‌ثانیه دو میلی‌واحد اضافه می‌کند. پس بازپرشدن با ضرب نرخ در فاصلهٔ صحیحِ میلی‌ثانیه انجام می‌شود و برای این شبکهٔ زمانی نیازی به گردکردن شناور نداریم. زمان‌های مساوی به ترتیب فراخوانی پردازش می‌شوند.

قاعدهٔ به‌روزرسانی، کمینهٔ ظرفیت و اعتبار قبلی به‌علاوهٔ بازپرشدن فاصلهٔ گذشته است. پس از سکوت طولانی، سطل بیشتر از ظرفیت ذخیره نمی‌کند؛ اعتبارِ سرریز برای جهش بزرگ‌تر آینده کنار گذاشته نمی‌شود. درخواست ردشده نیز زمان آخرین بررسی و اعتبارِ بازپرشده را ثبت می‌کند، اما هزینه را کم نمی‌کند. در نتیجه، بررسی‌های پیاپی یک فاصلهٔ زمانی را دو بار به حساب نمی‌آورند.

زمان در این مثال عدد صحیح از صفر تا توان شصت‌وسومِ دو منهای یک میلی‌ثانیه است و عقب نمی‌رود؛ این مبدأ، تاریخ تقویمی یا ساعت تهران نیست. ظرفیت و نرخ اعداد صحیح مثبت تا ده‌هزار و هزینه از یک تا ظرفیت‌اند. هزینهٔ بزرگ‌تر از ظرفیت خطای قرارداد است، چون با صبر کردن در همین سطل جا نمی‌شود. نوع bool، عدد شناور و رشته برای این فیلدها پذیرفته نیستند.

۳. جواب دستیِ پذیرش، رد و کمترین فاصلهٔ انتظار

رد درخواست بدون مصرف اعتبار مورد نیاز
تصویر مفهومی: رد درخواست بدون مصرف اعتبار مورد نیاز؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

در زمان صفر، درخواست دوواحدی پذیرفته و هزار میلی‌واحد باقی می‌ماند. درخواست دوواحدیِ دوم در همان زمان رد می‌شود و همان هزار باقی است. تا زمان ۴۹۹، ۹۹۸ میلی‌واحد دیگر جمع شده و موجودی ۱۹۹۸ است؛ هنوز دو میلی‌واحد کم داریم. در زمان ۵۰۰، اعتبار به ۲۰۰۰ می‌رسد و درخواست دوواحدی پذیرفته می‌شود. موجودی پس از آن صفر است.

در زمان ۷۵۰، فقط ۵۰۰ میلی‌واحد داریم؛ درخواست تک‌واحدی رد می‌شود و ۲۵۰ میلی‌ثانیهٔ دیگر لازم دارد. در زمان هزار، همان درخواست با موجودی کامل یک واحد پذیرفته می‌شود. پاسخ retry_after_ms از سقفِ تقسیم کسری اعتبار بر نرخ محاسبه می‌شود. این کمترین فاصلهٔ صحیح برای همان هزینه، با فرض نبود مصرفِ پذیرفته‌شدهٔ میان‌راهی و ادامهٔ زمان مجاز است؛ جای رزرو نوبت یا تضمین اجرای آینده را نمی‌گیرد.

در آزمون جدا با ظرفیت دو و نرخ سه، ابتدا دو واحد را مصرف می‌کنیم. برای یک واحد تازه، ۳۳۳ میلی‌ثانیه فقط ۹۹۹ میلی‌واحد می‌سازد؛ باید یک میلی‌ثانیهٔ دیگر صبر کرد. در ۳۳۴، درخواست پذیرفته و دو میلی‌واحد باقی می‌ماند. این مرز نشان می‌دهد گردکردن فاصله به پایین، درخواست را زودتر از بودجهٔ لازم مجاز می‌کند.

۴. کد کامل و مرجع کسری برای هجده بررسی

مرجع کسری مستقل برای آزمون سطل توکن
تصویر مفهومی: مرجع کسری مستقل برای آزمون سطل توکن؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

فایل tool_token_bucket.py با Python 3.14.5 و کتابخانهٔ استاندارد اجرا شده است. پیاده‌سازی اصلی فقط عدد صحیحِ میلی‌واحد دارد. مرجع مستقل با Fraction پایتون، خود واحد بودجه را به شکل کسر نگه می‌دارد و فاصلهٔ زمان را بر هزار تقسیم می‌کند. در پایان هر گام، خروجی کامل دو مسیر با هم مقایسه می‌شود.

"""Sequential offline admission model with exact integer milliunit credit.

No actual tool, queue, HTTP service, sleeping, model billing or authentication.
"""
from fractions import Fraction
import json
import math
import platform

MAX_MS=2**63-1


def bounded_integer(value,lower,upper,name):
    if type(value) is not int or not lower<=value<=upper:
        raise ValueError(name)
    return value


class ToolBudget:
    def __init__(self,capacity_units,rate_units_per_second):
        self.capacity=bounded_integer(capacity_units,1,10_000,'capacity')
        self.rate=bounded_integer(rate_units_per_second,1,10_000,'rate')
        self.last_ms=0
        self._credit=1000*self.capacity

    def admit(self,at_ms,cost_units=1):
        bounded_integer(at_ms,0,MAX_MS,'time_ms')
        bounded_integer(cost_units,1,self.capacity,'cost_units')
        if at_ms<self.last_ms:
            raise ValueError('backward_time')
        self._credit=min(1000*self.capacity,self._credit+self.rate*(at_ms-self.last_ms))
        self.last_ms=at_ms
        need=1000*cost_units
        accepted=self._credit>=need
        if accepted:
            self._credit-=need
            delay=0
        else:
            deficit=need-self._credit
            delay=(deficit+self.rate-1)//self.rate
        return {'at_ms':at_ms,'accepted':accepted,'cost_units':cost_units,
                'remaining_milliunits':self._credit,'retry_after_ms':delay}

    def snapshot(self):
        return {'last_ms':self.last_ms,'remaining_milliunits':self._credit}


def exact_fraction_oracle(capacity,rate,events):
    """Independent unit-level rational model; no scaled integer implementation calls."""
    balance=Fraction(capacity)
    previous=0
    trace=[]
    for at,cost in events:
        balance=min(Fraction(capacity),balance+Fraction(rate*(at-previous),1000))
        previous=at
        if balance>=cost:
            accepted=True
            balance-=cost
            delay=0
        else:
            accepted=False
            delay=math.ceil((cost-balance)*1000/rate)
        assert (balance*1000).denominator==1
        trace.append({'at_ms':at,'accepted':accepted,'cost_units':cost,
                      'remaining_milliunits':int(balance*1000),'retry_after_ms':delay})
    return trace


def rejects(call,message):
    try:
        call()
    except ValueError as error:
        return str(error)==message
    return False


def run_example():
    events=[(0,2),(0,2),(499,2),(500,2),(750,1),(1000,1)]
    budget=ToolBudget(3,2)
    trace=[budget.admit(t,cost) for t,cost in events]
    hand=[
      {'at_ms':0,'accepted':True,'cost_units':2,'remaining_milliunits':1000,'retry_after_ms':0},
      {'at_ms':0,'accepted':False,'cost_units':2,'remaining_milliunits':1000,'retry_after_ms':500},
      {'at_ms':499,'accepted':False,'cost_units':2,'remaining_milliunits':1998,'retry_after_ms':1},
      {'at_ms':500,'accepted':True,'cost_units':2,'remaining_milliunits':0,'retry_after_ms':0},
      {'at_ms':750,'accepted':False,'cost_units':1,'remaining_milliunits':500,'retry_after_ms':250},
      {'at_ms':1000,'accepted':True,'cost_units':1,'remaining_milliunits':0,'retry_after_ms':0},
    ]
    burst=ToolBudget(3,2)
    burst_results=[burst.admit(0) for _ in range(4)]
    idle=ToolBudget(3,2)
    idle_first=idle.admit(1_000_000,3)
    idle_next=idle.admit(1_000_000,1)
    thirds=ToolBudget(2,3)
    thirds.admit(0,2)
    thirds_denied=thirds.admit(0)
    thirds_333=thirds.admit(333)
    thirds_334=thirds.admit(334)
    repeated=ToolBudget(3,2)
    repeated.admit(0,3)
    deny100=repeated.admit(100)
    deny200=repeated.admit(200)
    invalid=ToolBudget(3,2)
    invalid.admit(100,1)
    invalid_before=invalid.snapshot()
    bad_times=all(rejects(lambda value=value:invalid.admit(value),'time_ms')
                  for value in (-1,True,1.0,'1',None,MAX_MS+1))
    state_after_bad_times=invalid.snapshot()
    backwards_rejected=rejects(lambda:invalid.admit(99),'backward_time')
    after_backwards=invalid.snapshot()
    bad_costs=all(rejects(lambda value=value:invalid.admit(200,value),'cost_units')
                  for value in (0,-1,4,True,1.0,'1',None))
    state_after_bad_costs=invalid.snapshot()
    oracle_ok=True
    envelope_ok=True
    case_count=0
    gaps=[0,333,1,499,500,1000]
    for capacity in range(1,5):
      for rate in range(1,5):
       for variant in range(5):
        time=0
        scenario=[]
        for index in range(6):
            time+=gaps[(index+variant)%len(gaps)]
            scenario.append((time,1+(index+variant)%capacity))
        tested=ToolBudget(capacity,rate)
        actual=[tested.admit(t,cost) for t,cost in scenario]
        oracle_ok=oracle_ok and actual==exact_fraction_oracle(capacity,rate,scenario)
        for left in range(len(actual)):
         for right in range(left,len(actual)):
            admitted=sum(row['cost_units'] for row in actual[left:right+1] if row['accepted'])
            envelope=Fraction(capacity)+Fraction(rate*(actual[right]['at_ms']-actual[left]['at_ms']),1000)
            envelope_ok=envelope_ok and admitted<=envelope
        case_count+=1
    left,right=ToolBudget(1,1),ToolBudget(1,1)
    left.admit(0)
    left_again,right_first=left.admit(0),right.admit(0)
    repeat=ToolBudget(3,2)
    repeated_trace=[repeat.admit(t,cost) for t,cost in events]
    returned=repeat.admit(1000,1)
    returned['remaining_milliunits']=999999
    checks={
      'hand_first_weighted_request_consumes_two_of_three_units':trace[0]==hand[0],
      'same_time_request_denied_without_consuming_remaining_unit':trace[1]==hand[1],
      'one_ms_before_boundary_has1998milliunits_and_one_ms_wait':trace[2]==hand[2],
      'exact500ms_boundary_accepts_weighted_cost_and_drains_credit':trace[3]==hand[3],
      'fractional_half_unit_at750ms_is_preserved_after_denial':trace[4]==hand[4],
      'next_complete_unit_at1000ms_matches_hand_and_fraction_oracle':trace[5]==hand[5] and trace==exact_fraction_oracle(3,2,events),
      'initial_same_timestamp_burst_is_capacity_not_refill_rate': [x['accepted'] for x in burst_results]==[True,True,True,False] and burst_results[-1]['retry_after_ms']==500,
      'idle_refill_caps_at_capacity_without_banking_excess':idle_first['accepted'] and idle_first['remaining_milliunits']==0 and not idle_next['accepted'] and idle_next['retry_after_ms']==500,
      'retry_delay_rounds_up_and_333_334ms_boundary_is_explicit':thirds_denied['retry_after_ms']==334 and thirds_333=={'at_ms':333,'accepted':False,'cost_units':1,'remaining_milliunits':999,'retry_after_ms':1} and thirds_334=={'at_ms':334,'accepted':True,'cost_units':1,'remaining_milliunits':2,'retry_after_ms':0},
      'denied_requests_refill_elapsed_time_once_and_never_charge_cost':deny100['remaining_milliunits']==200 and deny200['remaining_milliunits']==400 and not deny100['accepted'] and not deny200['accepted'],
      'invalid_time_types_and_range_do_not_mutate_state':bad_times and state_after_bad_times==invalid_before,
      'backward_time_is_rejected_without_credit_or_clock_change':backwards_rejected and after_backwards==invalid_before,
      'configuration_requires_positive_bounded_exact_integers':all(rejects(lambda value=value:ToolBudget(value,2),'capacity') for value in (0,-1,10001,True,1.0,'1')) and all(rejects(lambda value=value:ToolBudget(3,value),'rate') for value in (0,-1,10001,False,2.0,'2')),
      'cost_must_fit_bucket_and_validation_does_not_advance_clock':bad_costs and state_after_bad_costs==invalid_before,
      'eighty_small_scenarios_equal_independent_rational_unit_oracle':oracle_ok and case_count==80,
      'admitted_cost_obeys_capacity_plus_rate_times_window_in_all_cases':envelope_ok and case_count==80,
      'separate_objects_have_separate_credit_not_authenticated_client_isolation':not left_again['accepted'] and right_first['accepted'],
      'same_schedule_repeats_and_mutating_reply_does_not_change_bucket':repeated_trace==trace and repeat.snapshot()=={'last_ms':1000,'remaining_milliunits':0},
    }
    assert len(checks)==18 and all(type(value)is bool and value for value in checks.values()),checks
    return {'python':platform.python_version(),'dependencies':'standard library only',
            'scope':'Sequential offline weighted admission; fixed integer milliseconds and milliunits, no queue, service, actual action, wall clock, sleep, concurrency, authorization or language-model token billing',
            'capacity_units':3,'refill_units_per_second':2,'events':[[t,c] for t,c in events],
            'hand_timeline':hand,'observed_timeline':trace,'thirds_boundary':[thirds_denied,thirds_333,thirds_334],
            'oracle_scenarios':case_count,'checks':checks}


if __name__=='__main__':
    print(json.dumps(run_example(),ensure_ascii=False,indent=2,allow_nan=False))

هشتاد برنامهٔ کوچک با ظرفیت، نرخ، فاصله و هزینهٔ متفاوت ساخته شده‌اند؛ هر برنامه شش درخواست دارد. مقایسهٔ کامل با مرجع کسری، یک گروه بررسی است. گروه دیگری در همهٔ پنجره‌های متوالی همان داده‌ها کنترل می‌کند که هزینهٔ پذیرفته‌شده از ظرفیت به‌علاوهٔ نرخ ضرب در زمان بیشتر نشود. این زیرحالت‌ها به تعداد هجده گروه نام‌دار اضافه نمی‌شوند؛ اجرای دوباره هم بررسی جدید محسوب نمی‌شود.

{
  "python": "3.14.5",
  "dependencies": "standard library only",
  "scope": "Sequential offline weighted admission; fixed integer milliseconds and milliunits, no queue, service, actual action, wall clock, sleep, concurrency, authorization or language-model token billing",
  "capacity_units": 3,
  "refill_units_per_second": 2,
  "events": [
    [
      0,
      2
    ],
    [
      0,
      2
    ],
    [
      499,
      2
    ],
    [
      500,
      2
    ],
    [
      750,
      1
    ],
    [
      1000,
      1
    ]
  ],
  "hand_timeline": [
    {
      "at_ms": 0,
      "accepted": true,
      "cost_units": 2,
      "remaining_milliunits": 1000,
      "retry_after_ms": 0
    },
    {
      "at_ms": 0,
      "accepted": false,
      "cost_units": 2,
      "remaining_milliunits": 1000,
      "retry_after_ms": 500
    },
    {
      "at_ms": 499,
      "accepted": false,
      "cost_units": 2,
      "remaining_milliunits": 1998,
      "retry_after_ms": 1
    },
    {
      "at_ms": 500,
      "accepted": true,
      "cost_units": 2,
      "remaining_milliunits": 0,
      "retry_after_ms": 0
    },
    {
      "at_ms": 750,
      "accepted": false,
      "cost_units": 1,
      "remaining_milliunits": 500,
      "retry_after_ms": 250
    },
    {
      "at_ms": 1000,
      "accepted": true,
      "cost_units": 1,
      "remaining_milliunits": 0,
      "retry_after_ms": 0
    }
  ],
  "observed_timeline": [
    {
      "at_ms": 0,
      "accepted": true,
      "cost_units": 2,
      "remaining_milliunits": 1000,
      "retry_after_ms": 0
    },
    {
      "at_ms": 0,
      "accepted": false,
      "cost_units": 2,
      "remaining_milliunits": 1000,
      "retry_after_ms": 500
    },
    {
      "at_ms": 499,
      "accepted": false,
      "cost_units": 2,
      "remaining_milliunits": 1998,
      "retry_after_ms": 1
    },
    {
      "at_ms": 500,
      "accepted": true,
      "cost_units": 2,
      "remaining_milliunits": 0,
      "retry_after_ms": 0
    },
    {
      "at_ms": 750,
      "accepted": false,
      "cost_units": 1,
      "remaining_milliunits": 500,
      "retry_after_ms": 250
    },
    {
      "at_ms": 1000,
      "accepted": true,
      "cost_units": 1,
      "remaining_milliunits": 0,
      "retry_after_ms": 0
    }
  ],
  "thirds_boundary": [
    {
      "at_ms": 0,
      "accepted": false,
      "cost_units": 1,
      "remaining_milliunits": 0,
      "retry_after_ms": 334
    },
    {
      "at_ms": 333,
      "accepted": false,
      "cost_units": 1,
      "remaining_milliunits": 999,
      "retry_after_ms": 1
    },
    {
      "at_ms": 334,
      "accepted": true,
      "cost_units": 1,
      "remaining_milliunits": 2,
      "retry_after_ms": 0
    }
  ],
  "oracle_scenarios": 80,
  "checks": {
    "hand_first_weighted_request_consumes_two_of_three_units": true,
    "same_time_request_denied_without_consuming_remaining_unit": true,
    "one_ms_before_boundary_has1998milliunits_and_one_ms_wait": true,
    "exact500ms_boundary_accepts_weighted_cost_and_drains_credit": true,
    "fractional_half_unit_at750ms_is_preserved_after_denial": true,
    "next_complete_unit_at1000ms_matches_hand_and_fraction_oracle": true,
    "initial_same_timestamp_burst_is_capacity_not_refill_rate": true,
    "idle_refill_caps_at_capacity_without_banking_excess": true,
    "retry_delay_rounds_up_and_333_334ms_boundary_is_explicit": true,
    "denied_requests_refill_elapsed_time_once_and_never_charge_cost": true,
    "invalid_time_types_and_range_do_not_mutate_state": true,
    "backward_time_is_rejected_without_credit_or_clock_change": true,
    "configuration_requires_positive_bounded_exact_integers": true,
    "cost_must_fit_bucket_and_validation_does_not_advance_clock": true,
    "eighty_small_scenarios_equal_independent_rational_unit_oracle": true,
    "admitted_cost_obeys_capacity_plus_rate_times_window_in_all_cases": true,
    "separate_objects_have_separate_credit_not_authenticated_client_isolation": true,
    "same_schedule_repeats_and_mutating_reply_does_not_change_bucket": true
  }
}

خطای ورودی و زمان عقب‌رونده، اعتبار و ساعت مدل را تغییر نمی‌دهد. این خاصیت با تصویر وضعیت پیش و پس از فراخوانی نامعتبر آزموده شده است. دو شیء جدا نیز بودجه‌های جدا دارند؛ این جدایی حافظه‌ای، احراز هویت مشتری یا کنترل دسترسی نیست. تابع فقط پاسخ می‌دهد و نه درخواست ردشده را در صف می‌گذارد، نه sleep می‌کند و نه خودش دوباره تلاش می‌کند.

۵. محدودیت عملی و چهار پرسش پاسخ‌دار

محدودیت نرخ در برابر صف و مجوز اجرای واقعی
تصویر مفهومی: محدودیت نرخ در برابر صف و مجوز اجرای واقعی؛ بدون مقیاس عددی و مستقل از نتایج اجرای کد.

مستندات HTTP API در AWS کاربرد سطل توکن برای نرخ و جهش درخواست و ماهیت بهترین‌تلاشِ محدودیت‌های آن سرویس را توضیح می‌دهد. مدل ترتیبی ما تنظیم یا آزمایش AWS نیست. در سامانهٔ چندفرایندی، ثبت اتمی اعتبار، انتخاب ساعت، بازیابی خرابی و اشتراک بودجه نیاز به طراحی جدا دارند؛ قبولی این تمرین به‌تنهایی چنین قابلیت‌هایی ایجاد نمی‌کند.

پرسش اول: چرا با نرخ دو، سه درخواست در زمان صفر پذیرفته می‌شوند؟ پاسخ: ظرفیت اولیه سه است و سطل پُر شروع می‌شود. نرخ، سرعت اعتبارگیریِ بعدی را تعیین می‌کند؛ جهش اولیه به ظرفیت وابسته است.

پرسش دوم: آیا رد درخواست، اعتبار باقی‌مانده را صفر می‌کند؟ پاسخ: خیر؛ فقط گذشت زمان یک بار حساب می‌شود و هزینه کم نمی‌شود. نمونهٔ ۴۹۹ میلی‌ثانیه ۱۹۹۸ میلی‌واحد را نگه می‌دارد تا در ۵۰۰ مرز پذیرش برسد.

پرسش سوم: آیا درخواست پذیرفته‌شده برای اجرای ابزار مجاز و بی‌تکرار است؟ پاسخ: این خروجی فقط دربارهٔ بودجه است. قرارداد و مجوز ابزار و هویت درخواست و بازپخش نتیجه قواعد جدا دارند. این مدل حتی هویت درخواست را نگه نمی‌دارد و یک تکرارِ پذیرفته‌شده می‌تواند دوباره اعتبار مصرف کند.

پرسش چهارم: آیا retry_after_ms زمان اجرای قطعی است؟ پاسخ: خیر؛ فقط فاصلهٔ لازم طبق فرض‌های اعلام‌شده است. ورود مصرف‌کنندهٔ دیگر یا تغییر سیاست می‌تواند وضعیت را عوض کند و هیچ صف یا رزروی ساخته نشده است. منابع در ۲۴ مهر ۱۴۰۵ خوانده شدند؛ RFC 3290 سند اطلاعاتی مه ۲۰۰۲ است و این مطلب آموزش پایهٔ تألیفی، بدون ادعای خبر تازه یا ظرفیت واقعی سرویس است.

منابع و مطالعهٔ بیشتر

بررسی منابع: ۲۴ مهر ۱۴۰۵. تحلیل‌ها و پیشنهادهای اجرایی، جمع‌بندی نویسنده‌اند.