Опыт разработки на языке Rust

от автора

Вот так Chat GPT представила человека, если бы это был язык Rust

Вот так Chat GPT представила человека, если бы это был язык Rust

Я CEO своей компании MediaRise (компания только начала развиваться), с техническим бэкграундом. Сам люблю писать на разных языках, а вернее пробовать работать с ними. Давно уже слышал о таком языке как Rust.

Rust — это современный системный язык программирования, разработанный для обеспечения высокой производительности и безопасности, особенно при работе с конкурентными процессами. Изначально он был разработан компанией Mozilla, а сейчас поддерживается фондом Rust Foundation. Rust приобретает все большую популярность благодаря своей надежности и эффективности.

Ключевые особенности Rust:

Ключевые особенности Rust:

  1. Безопасность памяти: Rust устраняет общие ошибки программирования, такие как разыменование нулевого указателя и переполнение буфера, благодаря строгой проверке на этапе компиляции, без использования сборщика мусора.

  2. Система владения: Уникальная система владения Rust обеспечивает безопасность памяти без необходимости в сборщике мусора. Она использует систему владения с правилами, которые проверяются компилятором на этапе компиляции.

  3. Конкурентность: Rust упрощает написание конкурентных программ, предотвращая состояния гонки на этапе компиляции благодаря концепциям владения и заимствования.

  4. Производительность: Rust разрабатывался с целью быть таким же быстрым, как и C++, и часто демонстрирует сопоставимую производительность. Он может использоваться для системного программирования, где критична производительность.

  5. Выразительная типовая система: Rust обладает мощной типовой системой, включающей такие возможности, как сопоставление с образцом, алгебраические типы данных и обобщенные типы на основе трейтов, что позволяет писать более выразительный и безопасный код.

  6. Cargo: Rust поставляется с Cargo, системой сборки и менеджером пакетов, который упрощает управление зависимостями, сборку и распространение кода.

  7. Экосистема: Экосистема Rust включает растущую коллекцию библиотек и инструментов, которые помогают разработчикам писать надежный и эффективный код. Официальный реестр пакетов, crates.io, содержит тысячи библиотек с открытым исходным кодом.

Сферы применения Rust:

  1. Системное программирование: Rust идеально подходит для написания операционных систем, драйверов устройств и других низкоуровневых задач, где критичны контроль над оборудованием и производительность.

  2. WebAssembly: Rust может компилироваться в WebAssembly, что позволяет запускать код Rust в веб-браузерах с производительностью, близкой к нативной.

  3. Сетевое программирование: Особенности безопасности и производительность Rust делают его подходящим для написания сетевого ПО, включая веб-серверы и клиенты.

  4. Разработка игр: Производственные характеристики Rust делают его хорошим выбором для разработки игр, где скорость и эффективность критичны.

  5. Командные утилиты: Менеджер пакетов Cargo упрощает создание и распространение командных утилит.

Известные проекты, использующие Rust:

  1. Firefox Quantum: Mozilla использовала Rust для переписывания частей их движка браузера, что привело к значительному улучшению производительности.

  2. Dropbox: Dropbox использует Rust для некоторых своих серверных сервисов.

  3. Cloudflare: Cloudflare использует Rust для нескольких своих производительно критичных сервисов.

  4. Rustlings: Образовательный проект, который помогает изучать Rust через небольшие упражнения.

Комбинация безопасности, производительности и поддержки конкурентности делает Rust привлекательным выбором для многих видов разработки программного обеспечения. Его растущая популярность и активное сообщество гарантируют, что Rust продолжит развиваться и улучшаться.

Думал над идеей, что бы такого реализовать на языке Rust. Мне захотелось написать Telegram-бота, который бы двунаправленно переводил сообщения в чате группы с русского на тайский и наоборот.

Понимаю, что существуют готовые решения, но захотелось создать свой «велосипед» и опробовать новый для себя язык — Rust.

Идея есть, с созданием Telegram-бота проблем нет, но возникла проблема с сервисом, который будет переводить с одного языка на другой. Выбор пал на LibreTranslate. Чтобы использовать его бесплатно, необходимо развернуть приложение на своем сервере. Я так и сделал: установил зависимости и развернул в Docker-контейнере. Проблем не возникло, единственное, что приложение необходимо запускать с флагом: `./run.sh —api-keys`, чтобы можно было получить `api_key`. Подробнее о настройке и получении `api-key` для LibreTranslate можно прочитать на официальном сайте.

Развернув сервер LibreTranslate и получив токен для Telegram-бота, осталось реализовать приложение. Просмотрев официальную документацию по Rust и наработки на GitHub, я начал творить. Установил Rust и Cargo (регистр/менеджер пакетов для Rust). Изучив документацию библиотеки teloxide для создания Telegram-ботов на Rust, написал обработчик для событий сообщений в чате.

#[tokio::main] async fn main() -> ResponseResult<()> {     dotenv().ok();     env_logger::init();     let token_bot = env::var("TELEGRAM_BOT_KEY").expect("TELEGRAM_BOT_KEY not found");      let bot = teloxide::Bot::new(&token_bot).parse_mode(ParseMode::Html);      // Create a handler for our bot, that will process updates from Telegram     let handler = dptree::entry()         .inspect(|u: Update| {                     eprintln!("{u:#?}"); // Print the update to the console with inspect         })     ...          .branch(             Update::filter_message()                 .branch(                     dptree::endpoint(translate_message),                 )         );      // Create a dispatcher for our bot     Dispatcher::builder(bot, handler).enable_ctrlc_handler().build().dispatch().await;      Ok(()) }  async fn translate_message(bot: Bot, msg: Message) -> ResponseResult<()> {     if let Some(text) = msg.text() {          match translate(text).await {             Ok(translated_word) => {                 bot.send_message(msg.chat.id, translated_word).await?;             }             Err(e) => {                 bot.send_message(msg.chat.id, format!("Translation error: {}", e)).await?;             }         }     } else {         bot.send_message(msg.chat.id, "Send me plain text.").await?;     }      Ok(()) }

Далее саму функцию для запроса перевода с API LiberTranslate. Приложение по переводу определяет на каком языке сообщение и переводит на необходимый (ru -> th, th -> ru)

async fn translate(text: &str) -> ResponseResult<String> {     let client = reqwest::Client::new();      let api_translate_url = env::var("API_TRANSLATE_URL").expect("API_TRANSLATE_URL not found");     let api_translate_key = env::var("API_TRANSLATE_KEY").expect("API_TRANSLATE_KEY not found");     let api_detect_url = env::var("API_DETECT_URL").expect("API_DETECT_URL not found");     eprintln!("{text:#?}");      let detect_request = DetectRequest {         q: String::from(text),         api_key: String::from(api_translate_key.clone()),     };      let res = client.post(api_detect_url)         .header("Content-Type", "application/x-www-form-urlencoded")         .form(&detect_request)         .send()         .await?;     let resp_json = res.json::<Vec<DetectResponse>>().await?;      let lang = &resp_json[0].language;      eprintln!("{lang:#?}");     let target_lang = if lang == "ru" { "th" } else { "ru" };      let json_object = json!({                 "q": text,                 "source": "auto",                 "target": target_lang,                 "format": "text",                 "alternatives": 3,                 "api_key": api_translate_key             });      let json_string = serde_json::to_string(&json_object).unwrap();       let res = client.post(api_translate_url)         .body(json_string)         .header("Content-Type", "application/json")         .send()         .await?;      let resp_json = res.json::<TranslateResult>().await?;     let translated_word = resp_json.translatedText;     Ok(translated_word) }

Результат в Telegram чате

Изображение с чата

Изображение с чата

Были проблемы с багами, которые были из-за того, что я использовал старые библиотеки на Rust, когда пытался проблему решить с помощью ChatGPT. Но больше помог живой опыт разработчиков с GitHub, где я смотрел реализацию какого либо функционала: API документация бота, работа с env (файлами окружения), примеры работы с json, отправка rest запросов и также работу конструкции языка.

Я очень рад рабочему приложению, потому что ранее не писал на Rust и это меня вдохновило изучать его дальше. Опытные разработчики наверняка подскажут, как можно оптимизировать код, чему я буду очень рад.

Осталось сбилдить приложение и запустить его в режиме демона на сервере

Настройка systemd

Соберите ваше приложение с помощью команды:

cargo build --release

Создайте файл юнита для systemd. Например, создадим файл /etc/systemd/system/translate_bot.service

[Unit] Description=Translate Bot After=network.target  [Service] ExecStart=/path/to/your/application Restart=always User=yourusername Group=yourgroupname Environment=/path/to/your/.env WorkingDirectory=/path/to/your/application/directory  [Install] WantedBy=multi-user.target 

Перезагрузите конфигурацию systemd, чтобы он узнал о новом сервисе:

sudo systemctl daemon-reload

Запустите сервис:

sudo systemctl start translate_bot

Убедитесь, что сервис запущен и работает:

sudo systemctl status translate_bot

Чтобы ваш сервис автоматически запускался при старте системы, выполните команду:

sudo systemctl enable rust_service

Ваше приложение на Rust будет работать как системный сервис, управляемый systemd. Вы можете контролировать его с помощью стандартных команд systemd, таких как start, stop, restart, и status.

P.S. Хотел бы также решить проблему с env файлами, чтобы доступ к ним был в функции из main.

Далее в планах: я бы хотел реализовать обработку события, если в чате появится новый user (а также ливнет). User может выбрать язык, на котором бы он хотел получать перевод. Сами юзеры и их настройки будут храниться в базе PostgreSQL

Всем спасибо за внимание! Исходники выложил на GitHub.

Исходник на GitHub


ссылка на оригинал статьи https://habr.com/ru/articles/830336/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *