Я сделал Rust 1. job_scheduler

Надеюсь, что я беру на себя обязательство делать каждую неделю, в этом первом эпизоде ​​мы поговорим о библиотеке планирования ржавчины. Мой любимый вариант использования — совет и предостережение.

Быстрая прелюдия

Привет, меня зовут Самуэль. Я хочу взять на себя обязательство еженедельно проводить обзор/объяснение/обзор/демонстрацию библиотеки ржавчины. Где я постараюсь показать вам крутую библиотеку/проект для использования на работе или для следующего любимого проекта, чтобы собрать пыль. У меня есть несколько причин сделать это, в том числе:

  • Проверка моего навыка ржавчины
  • Пробуем новые библиотеки/проекты rust
  • Улучшить мое письмо

Последнее, вероятно, больше всего нуждается в доработке. Потому что я из Словакии, маленькой славянской страны в Центральной Европе. Я разработчик-самоучка, интересующийся: Wasm, встроенными системами, музыкой.

Ладно, это прелюдия. Оформим заказ job-scheduler

Взглянув на страницу crates.io, вы можете предположить, что это мертвая библиотека и не имеет прецедентов в сегодняшних кодовых базах.

Однако не ведитесь на последнюю дату обновления. Это одна из моих любимых библиотек для использования

Хорошо, ну что это такое?

Как следует из названия, это расписание работы. Он использует спецификатор интервала, подобный cron, который прост в использовании из-за его широкого использования в дистрибутивах Linux. Для запуска вашей функции («Задание») с точным интервалом/временем. Ключевым словом здесь является точность, и это одна из вещей, которые мне нравятся в этой библиотеке. Я не собираюсь копировать и вставлять сюда документацию библиотеки, во-первых, потому что я предлагаю вам проверить ее самостоятельно, а во-вторых, чтобы продемонстрировать мои любимые функции. Точность, да! Как я уже упоминал, мне нравится реализация планировщика этой библиотеки из-за того, что она предоставляет функцию tick(), которая при каждом вызове проверяет, не пора ли выполнить вашу работу. Если пришло время хорошо запустить функцию, она запустит вашу функцию, да?

Таким образом, вы сами отвечаете за то, насколько точным должен быть ваш планировщик. Если вам нужен чрезвычайно точный планировщик, просто вызывайте tick() все время следующим образом:

let scheduler = JobScheduler::new();
loop {
    scheduler.tick(); 
}

Однако, как упоминалось в документах библиотеки, это неэффективно, потому что вам не нужно указывать точность менее 300 миллисекунд, в основном из-за того, что расписание cron не поддерживает миллисекундные интервалы.

Неблокирующие задания:

Идея этого примера заключается в выполнении длинной задачи или, точнее, блокировке задачи без блокировки других задач в том же потоке. Возможно, вы знаете блокирующие и неблокирующие термины из асинхронной ржавчины. Но мы ни в коем случае не будем говорить об асинхронности в этом посте. Весь этот код в основном предназначен для использования в параллельных приложениях. Однако я думаю, что можно внести некоторые изменения в библиотеку, чтобы ее можно было использовать в асинхронном контексте. Кроме того, когда я писал это, я заметил этот драгоценный камень, который я мог бы сделать в эпизоде, поскольку он выглядит очень предназначенным для асинхронного контекста, если вы ищете в основном асинхронную реализацию этой идеи.

Предупреждения:

Первая проблема, которая возникнет, когда вы попытаетесь реализовать это, вероятно, будет заключаться в том, что вам нужно всегда клонировать/копировать переменные, чтобы проверка заимствования была счастлива. Позвольте мне показать вам плохой код:

Это приведет к довольно подробной ошибке:

error[E0507]: cannot move out of `user.name`, a captured variable in an `FnMut` closure
  --> src/lib.rs:21:27
   |
15 |           let mut user = User {
   |               -------- captured outer variable
...
20 |           let job = Job::new(schedule, move || {
   |  ______________________________________-
21 | |             thread::spawn(move || {
   | |                           ^^^^^^^ move out of `user.name` occurs here
22 | |                 user.name = String::from("Daniel");
   | |                 ---------
   | |                 |
   | |                 variable moved due to use in closure
   | |                 move occurs because `user.name` has type `String`, which does not implement the `Copy` trait
23 | |             }) ;
24 | |         });
   | |_________- captured by this `FnMut` closure

Честно говоря, я не совсем понимаю это сообщение об ошибке, но я постараюсь сделать все возможное в надежде, что кто-нибудь исправит мое объяснение, если это необходимо. Таким образом, по сути, вы пытаетесь переместить часть структуры из закрытия («закрытие задания») в закрытие потока. Но наше «пользовательское» значение захватывается замыканием («закрытие задания») по ключевому слову «переместить» , а средство проверки заимствования не позволяет захватывать значение замыкания, полученное из другой области.

Чтобы исправить это, мы должны дать закрытию потока некоторую конкретную переменную, которую можно захватить. Кроме того, это не может быть ссылкой из-за перемещения «закрытия задания», оно делает то, что сказано, перемещает значение, и даже изменяемая ссылка становится проблемой, потому что вам нужно будет указать ее время жизни, и это насколько мое понимание идет, невозможно. Но вы можете клонировать или копировать и сделать что-то вроде этого:

Хорошо, это все, что у меня есть. Надеюсь, вы что-то вынесли из этого. Было бы здорово, если бы вы подписались на меня, так как я хочу набрать 100 подписчиков и попасть в партнерскую программу. Спасибо, до свидания