Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Завершение
Чем ack, drop, retry и retry_after становятся в
NATS: подтверждением, на которое действует сервер JetStream, и копиями, которые рантайм публикует в
Core.
Схема текстом
- Обработчик: ack(); retry(); retry_after(d); drop(); нет исхода до ack_wait
- Отправлено: +ACK; -NAK; -NAK {"delay": …}; +TERM; ничего; В Core NATS любой исход возвращает AckError::Unsupported: сервер ничего не завершает
- Сервер: готово, больше не отправляется; снова сразу, delivered + 1; ждёт d, затем снова, delivered + 1; прекращено, больше не отправляется; снова после ack_wait, delivered + 1
- ack() → +ACK
- +ACK → готово, больше не отправляется
- retry() → -NAK
- -NAK → снова сразу, delivered + 1
- retry_after(d) → -NAK {"delay": …}
- -NAK {"delay": …} → ждёт d, затем снова, delivered + 1
- drop() → +TERM
- +TERM → прекращено, больше не отправляется
- нет исхода до ack_wait → ничего
- ничего → снова после ack_wait, delivered + 1
Доставка JetStream завершается на сервере. Ответ уходит в субъект подтверждения доставки, и
консьюмер поступает с ним так, как показывает страница Консьюмеры.
retry_after помещает задержку в само отрицательное подтверждение. Сервер придерживает сообщение
и повторно доставляет его тому же консьюмеру, с тем же номером в стриме и счётчиком delivered на
единицу больше. Ничего не публикуется, и копия не создаётся.
Доставку Core завершать нечем. ack, retry и drop возвращают AckError::Unsupported, и
рантайм записывает это в журнал. Сервер не хранит ничего для повторной доставки, и рантайм
возвращает сообщение только копией, которую публикует сам. Это доставка
at-most-once.
| Исход | Core NATS |
|---|---|
ack, drop | AckError::Unsupported |
retry() | AckError::Unsupported; при объявленном пределе копия публикуется сразу |
retry_after(d) | копия публикуется через d |
| нет исхода | ничего |
Переобработка
Схема текстом
- Ниже предела: JetStream: -NAK с задержкой, сервер придерживает; Субъект Core: копия публикуется в этот субъект; Шаблон Core: копия в субъект из точки монтирования
- На пределе: Субъект для недоставленных: доставка уходит как пришла; Без такого субъекта: +TERM в JetStream, ничего в Core
- Доставка JetStream считает доставки, в Core счёт в заголовке → Обработчик возвращает retry_after(delay) или retry() при объявлении: обработана
- Обработчик возвращает retry_after(delay) или retry() при объявлении → max_attempts: попытка ниже предела?: переобработка
- max_attempts: попытка ниже предела? → Ниже предела: ниже
- max_attempts: попытка ниже предела? → На пределе: на пределе
- Копия Core ждёт задержку внутри процесса: остановка до срабатывания таймера её теряет
Предел объявляется в точке монтирования через
max_attempts, и первая доставка считается
первой попыткой. В JetStream счёт ведёт сам сервер в своём delivered, поэтому доставка, которая
не уложилась в ack_wait, тоже учитывается. В Core рантайм считает опубликованные копии в
заголовке копии x-ruststream-retry-count.
Ниже предела каждая модель возвращает сообщение по-своему. JetStream повторно доставляет его из
стрима. В Core рантайм публикует копию по адресу, который сообщает дескриптор.
CoreSubject сообщает свой субъект.
CoreWildcard подходит ко многим субъектам и не
публикует ни в один из них, поэтому его регистрация называет
субъект для копии, иначе приложение не запустится.
На пределе доставка уходит в субъект для недоставленных сообщений
в том виде, в каком пришла: полезная нагрузка и заголовки не меняются. Если субъект для
недоставленных не объявлен, доставка JetStream прекращается через +TERM, а доставку Core рантайм просто
отпускает.
Крейт ничего не объявляет серверу: max_deliver остаётся незаданным, потому что у JetStream нет
места, куда отправить сообщение, исчерпавшее доставки. Путь рантайма покрывает обе модели.