Перейти к содержанию

Быстрый старт

Нормативная версия документации - английская

Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.

Самый быстрый путь к работающему сервису - сгенерировать заготовку через cargo generate.

Заготовка проекта

cargo install cargo-generate
cargo generate --git https://github.com/powersemmi/ruststream templates/memory --name my-service
cd my-service

Для генерации нужен только cargo generate. templates/memory - стартовый шаблон на in-memory брокере. Крейт брокера, у которого шаблон есть, разворачивается так же: указывают его репозиторий и путь к шаблону (например, --git https://github.com/powersemmi/ruststream-nats templates/nats); какие шаблоны есть у брокера, сказано в его собственной документации. cargo generate создаёт идиоматичный проект из нескольких файлов:

my-service/
├── Cargo.toml
└── src/
    ├── main.rs      # #[ruststream::app] строит сервис и монтирует роутер
    ├── orders.rs    # обработчики как функции #[subscriber] (один публикует ответ)
    └── routes.rs    # собирает обработчики в Router

Запуск

#[ruststream::app] генерирует main, поэтому бинарник уже понимает команды фреймворка:

cargo run -- run                # или: ruststream run, если установлен CLI

cargo run -- run запускает рантайм tokio. Сервис работает, пока вы не нажмёте ++ctrl+c++. Внешний брокер для запуска не нужен.

Генерация AsyncAPI-документа

cargo run -- asyncapi gen

Команда печатает AsyncAPI-документ в формате JSON. Флаги вывода (-o, --yaml) и сам документ разобраны в модуле asyncapi.

Как выглядит точка входа

src/main.rs
mod orders;
mod routes;

use ruststream::memory::MemoryBroker;
use ruststream::runtime::{AppInfo, RustStream};

#[ruststream::app]
fn app() -> RustStream {
    RustStream::new(AppInfo::new("orders-service", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
        let router = routes::orders();
        b.include_router(router);
    })
}
src/main.rs
mod orders;
mod routes;

use std::error::Error;

use ruststream::memory::prelude::*;

fn app() -> RustStream {
    RustStream::new(AppInfo::new("orders-service", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
        let router = routes::orders();
        b.include_router(router);
    })
}

// What `#[ruststream::app]` wraps around the builder: the runtime entry point. Its CLI
// (`run`, `asyncapi gen`) is what a hand-written `main` gives up.
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    app().run().await?;
    Ok(())
}

Вы пишете функцию, которая собирает сервис, а #[ruststream::app] превращает её в main.

Что дальше

  • Разобраться в каждой части по учебнику.
  • Изучить формы обработчиков в разделе Подписчики.
  • Управлять сервисом из CLI.