14
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

interval.tickはsleepではない

Last updated at Posted at 2025-12-17

この記事は、 セゾンテクノロジー Advent Calendar 2025 の記事です。
シリーズ2では HULFTDataSpider の開発メンバーによる投稿をお届けします:dove:
18日目はHULFT10 for Container Servicesの開発者が担当します🙌

公式のドキュメントはちゃんと読みましょうという話

経緯

開発中、エラー発生後のリトライ処理の間隔が異様に短い事象が発生しました。

調査

事象が起きているリトライ処理のコードを見ると以下のようになっていました。

事象発生コードのサンプル
async fn some_func(retry_count_limit: u32, retry_interval: u64) -> Result<(), Err>
{
    let mut count = 0;
    let mut interval = tokio::time::interval(tokio::time::Duration::from_millis(retry_interval));

    // リトライ回数まで処理を繰り返し
    loop {
        interval.tick().await;

        // なんかの処理

        if count >= retry_count_limit {
            return Err(error);
        }
        count += 1;
    }
}

リトライごとにintervalがしっかり挟まれるようになっているので問題なさそうに見える……?

公式ドキュメント

とりあえずドキュメントを読みに行ってみます。
tokioクレートのドキュメントのintervalの説明には以下の記載があります。

The difference between interval and sleep is that an Interval measures the time since the last tick, which means that .tick().await may wait for a shorter time than the duration specified for the interval if some time has passed between calls to .tick().await.
インターバルとスリープの違いは、インターバルが前回のティックからの経過時間を測定する点にあります。つまり、.tick().awaitの呼び出し間に時間が経過している場合、.tick().awaitが待機する時間はインターバルに指定された期間よりも短くなる可能性があります。

絶対これじゃんね👀

お試しコード

つまり、interval.tickとtickの間の処理に時間がかかると、その処理の時間分interval.tickの待ち時間は減るよ!ということ。
一応試してみましょう。

intervalで再現させてみるコード
use tokio::time;

async fn sleep(sec: u64) {
    println!("{}: sleep {sec} sec", chrono::Local::now());
    time::sleep(time::Duration::from_secs(sec)).await
}

async fn tick(interval: &mut tokio::time::Interval) {
    println!("{}: tick", chrono::Local::now());
    interval.tick().await;
}

#[tokio::main]
async fn main() {
    let mut interval = time::interval(time::Duration::from_secs(1));
    tick(&mut interval).await;
    tick(&mut interval).await;
    sleep(5).await;
    for _i in 0..10 {
        tick(&mut interval).await;
    }
}

tickの間に5秒かかる処理(sleep)を入れてます。
intervalは1秒なので、5回分のinterval.tickが一瞬で戻って来るはずです。

実行結果
2025-12-16 16:03:59.955151227 +09:00: tick
2025-12-16 16:03:59.959304102 +09:00: tick
2025-12-16 16:04:00.965694303 +09:00: sleep 5 sec
2025-12-16 16:04:05.967936955 +09:00: tick
2025-12-16 16:04:05.968032108 +09:00: tick
2025-12-16 16:04:05.968710180 +09:00: tick
2025-12-16 16:04:05.968745905 +09:00: tick
2025-12-16 16:04:05.968770629 +09:00: tick
2025-12-16 16:04:05.968793959 +09:00: tick
2025-12-16 16:04:06.961001121 +09:00: tick
2025-12-16 16:04:07.960254985 +09:00: tick
2025-12-16 16:04:08.958859889 +09:00: tick
2025-12-16 16:04:09.958618855 +09:00: tick

想定通りsleep後、5回分のtickが一瞬で終わってしまいました。

まとめ

  • 処理完了から一定時間待機したいならsleepを使いましょう
  • 英語から逃げずにドキュメントはちゃんと読みましょう(n敗)
    • おまえが日本語記事書くんだよ意識
14
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?