Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Путь
Путь одного сообщения через сервис RustStream, на файле потока и в канале: чтение, очередь, обработчик, ответ и запись.
Схема текстом
- Файл потока: Консьюмер клиента читает файл; Управляющая задача метит поколением; Очередь на 64; FileSubscriber отсев старых поколений; Сборка пакета под batch(n); FileContext, затем декодирование; Обработчик-подписчик #[subscriber] fn; FilePublisher конверт при заголовках; Дозапись и сброс в файл
- Канал: Поток stdin разбирает строку; Задача чтения подписки; Очередь на 64; StdioSubscriber по сообщению на опрос; Сборка пакета под batch(n); Декодирование; Обработчик-подписчик #[subscriber] fn; StdioPublisher конверт, если нужно; Поток stdout пишет строку
- Консьюмер клиента читает файл → Управляющая задача метит поколением
- Управляющая задача метит поколением → Очередь на 64
- Очередь на 64 → FileSubscriber отсев старых поколений
- FileSubscriber отсев старых поколений → Сборка пакета под batch(n)
- Сборка пакета под batch(n) → FileContext, затем декодирование
- FileContext, затем декодирование → Обработчик-подписчик #[subscriber] fn
- Обработчик-подписчик #[subscriber] fn → FilePublisher конверт при заголовках
- FilePublisher конверт при заголовках → Дозапись и сброс в файл
- Поток stdin разбирает строку → Задача чтения подписки
- Задача чтения подписки → Очередь на 64
- Очередь на 64 → StdioSubscriber по сообщению на опрос
- StdioSubscriber по сообщению на опрос → Сборка пакета под batch(n)
- Сборка пакета под batch(n) → Декодирование
- Декодирование → Обработчик-подписчик #[subscriber] fn
- Обработчик-подписчик #[subscriber] fn → StdioPublisher конверт, если нужно
- StdioPublisher конверт, если нужно → Поток stdout пишет строку
Задача подписки читает с опережением обработчика. Она забирает у клиента каждое сообщение,
открывает конверт и копирует полезную нагрузку в собственный буфер. Номер сообщения
она добавляет в заголовок stream-sequence и ставит доставку в очередь, в которой помещается до 64
доставок. Обработчик читает из этой очереди, поэтому следующее сообщение уже прочитано из файла,
пока обрабатывается текущее.
На файле каждая доставка несёт поколение, в котором был читатель, когда её прочитал. Перемотка открывает новое поколение, и подписка отбрасывает то, что стоит в очереди под старым. Доставка также держит разделяемую ссылку на дескриптор перемотки подписки, поэтому построение её контекста на каждом сообщении только увеличивает счётчик ссылок.
Ответ обработчика кодируется в буфер, который цикл диспетчеризации использует повторно. Издатель копирует эти байты в сообщение, которое передаёт клиенту. В конверт он их помещает, только когда у сообщения есть заголовки, или в канале, когда строка изменила бы полезную нагрузку. Публикация в файл возвращается, когда дозапись сброшена в файл. Ответ, записанный в тот файл, который читает подписка, её читатель пропускает: ответ лежит под другим ключом потока.
Доставка завершается после ответа. На обоих транспортах ack и nack возвращают ошибку: операция не поддерживается. Это показывает страница Завершение.