カテゴリ: Ruby 更新日: 2026/04/03

Rubyのタイムアウトとリトライ制御を徹底解説!loopとtimeoutでエラーに強いプログラムを作る

タイムアウト・リトライ制御:Kernel#loop と timeout の設計例
タイムアウト・リトライ制御:Kernel#loop と timeout の設計例

先生と生徒の会話形式で理解しよう

生徒

「Rubyでインターネットからデータを取ってくるプログラムを作ったのですが、通信が遅いときにずっと止まったままになってしまいます。どうすればいいですか?」

先生

「それは『タイムアウト』の設定が必要ですね。制限時間を決めて、それを過ぎたら処理を切り上げる仕組みです。」

生徒

「なるほど!でも、たまたま一度だけ失敗した場合は、もう一度やり直して(リトライして)ほしいんですけど……。」

先生

「それなら『loop』と『timeout』を組み合わせれば完璧です!失敗しても自動で再挑戦し、あまりに時間がかかるなら諦める、という賢いプログラムの書き方を教えますね。」

1. タイムアウトとリトライとは?プログラムの「待ち」を制御する

1. タイムアウトとリトライとは?プログラムの「待ち」を制御する
1. タイムアウトとリトライとは?プログラムの「待ち」を制御する

プログラムの世界では、自分の力だけではどうにもならない待ち時間が発生することがあります。例えば、遠く離れた場所にあるコンピュータ(サーバー)にデータを送ったり、大きなファイルを読み込んだりするときです。

タイムアウトとは、「この処理は10秒以内に終わらせてね。もし終わらなかったら、諦めて中止して!」と制限時間を設けることです。これを設定しないと、プログラムはいつまでも返事を待ち続け、フリーズしたような状態になってしまいます。

一方、リトライとは、「一度失敗しても、もう一回だけ試してみて!」という再挑戦の仕組みです。通信環境が一瞬だけ悪くなっただけなら、二回目は成功するかもしれませんよね。

この二つを組み合わせることで、エラーが起きても止まらない、粘り強くかつスマートなプログラムを作ることができるようになります。

Rubyの文法を基礎からしっかり固めたい人や、 現場で役立つ「テスト駆動開発」の考え方まで身につけたい人には、 評価の高いこの一冊がおすすめです。

プロを目指す人のためのRuby入門をAmazonで見る

※ Amazon広告リンク

2. Kernel#loopの使い方!ずっと繰り返して再挑戦

2. Kernel#loopの使い方!ずっと繰り返して再挑戦
2. Kernel#loopの使い方!ずっと繰り返して再挑戦

Rubyで「何度もやり直す」ために便利なのがloopメソッドです。これは無限ループを作るための命令ですが、ただ闇雲に繰り返すのではなく、成功した瞬間に「break」を使って外へ抜け出すのが正しい使い方です。

未経験の方にとって、「無限」という言葉は少し怖いかもしれませんが、出口をしっかり作ってあげれば大丈夫です。身近な例で言えば、目覚まし時計が鳴って「起きるまで5分おきに鳴り続ける(スヌーズ機能)」ようなものだと考えてください。


# 成功するまで何度も繰り返す
loop do
  puts "通信を開始します..."
  # ここに通信の処理があると仮定します
  success = [true, false].sample # ランダムで成功か失敗を決める

  if success
    puts "成功しました!ループを抜けます。"
    break # これでループが終了します
  else
    puts "失敗しました。もう一度やり直します。"
  end
end

このように、成功するまで諦めずに繰り返す土台を作ることができます。

3. timeoutライブラリで時間制限を設ける

3. timeoutライブラリで時間制限を設ける
3. timeoutライブラリで時間制限を設ける

次に、制限時間を測るための道具を準備しましょう。Rubyには「timeout」という便利な標準ライブラリ(最初から用意されている道具セット)があります。これを使うには、コードの最初にrequire 'timeout'と書く必要があります。

Timeout.timeout(秒数)というブロックの中に、時間がかかるかもしれない処理を書きます。もし指定した秒数以内に終わらなければ、Rubyが「時間切れです!」という例外(エラー)を発生させてくれます。


require 'timeout'

begin
  # 3秒以内に終わらなければエラーにする
  Timeout.timeout(3) do
    puts "重い処理を開始します..."
    sleep 5 # 5秒間わざと眠らせる(時間をかける)
    puts "処理が完了しました!"
  end
rescue Timeout::Error
  puts "時間切れになりました。処理を強制終了します。"
end

この「begin」と「rescue」は、エラーが起きたときにプログラムを異常終了させず、優しくキャッチするための網のような役割をしています。

4. loopとtimeoutを合体!設計の黄金パターン

4. loopとtimeoutを合体!設計の黄金パターン
4. loopとtimeoutを合体!設計の黄金パターン

それでは、いよいよ本番です。何度もやり直す「loop」と、時間を見張る「timeout」を組み合わせてみましょう。

「3回までは再挑戦するけれど、1回の挑戦につき5秒以上かかったら次へ行く」という、とても実用的な設計例をご紹介します。


require 'timeout'

retry_count = 0

loop do
  begin
    # 2秒以内に終わるかチェック
    Timeout.timeout(2) do
      puts "#{retry_count + 1}回目の挑戦です..."
      # ここで時間がかかる処理
      sleep(rand(1..3)) # 1から3秒ランダムで待つ
      puts "無事に完了しました!"
      break # 成功したらループ脱出!
    end
  rescue Timeout::Error
    retry_count += 1
    puts "タイムアウトしました。"

    if retry_count >= 3
      puts "3回試しましたがダメでした。諦めます。"
      break # 回数制限を超えたので脱出
    end
    
    puts "少し待ってから再試行します..."
    sleep 1 # すぐにやるとまた失敗するので少し待つ
  end
end

このように設計することで、通信の一時的な不調にも対応でき、かつ永遠に止まってしまうこともない安全なプログラムになります。

5. sleepを入れる理由!コンピュータを休ませる思いやり

5. sleepを入れる理由!コンピュータを休ませる思いやり
5. sleepを入れる理由!コンピュータを休ませる思いやり

リトライの処理の中で、sleep 1のように少し待機する時間を入れています。これは非常に大切なポイントです。

もし失敗した瞬間に、目にも止まらぬ速さで次の挑戦を始めると、相手のサーバーに大きな負担をかけてしまいます。最悪の場合、攻撃だと勘違いされてアクセス禁止になってしまうこともあるかもしれません。

また、ネットワークのトラブルは数秒待てば解消されることも多いです。少しの間をおくことで、成功率を高める効果もあります。これを専門用語で「ウェイトを入れる」と言ったりしますが、要は「一呼吸置いてからやり直す」という優しさが大切なのです。

6. 複雑な条件分岐を防ぐ!リトライ専用メソッドの作成

6. 複雑な条件分岐を防ぐ!リトライ専用メソッドの作成
6. 複雑な条件分岐を防ぐ!リトライ専用メソッドの作成

毎回この長いコードを書くのは大変ですよね。そんな時は、再利用できるように「自分専用のリトライ命令」を作っておくと便利です。


require 'timeout'

# リトライ専用のメソッドを定義
def with_retry(limit: 3, wait: 1, timeout: 5)
  count = 0
  loop do
    begin
      return Timeout.timeout(timeout) { yield }
    rescue Timeout::Error, StandardError => e
      count += 1
      if count >= limit
        puts "最終エラー: #{e.message}"
        raise # 諦めてエラーを報告
      end
      puts "再試行中... (#{count}/#{limit})"
      sleep wait
    end
  end
end

# 使い方
with_retry(limit: 2, timeout: 3) do
  puts "Webサイトから情報を読み込んでいます..."
  # ここに実際の処理を書く
end

yieldというのは、後から渡した処理の中身を実行する合言葉です。これを使えば、どんな処理に対しても簡単にリトライ機能を付け足すことができます。

7. タイムアウト値の決め方!短すぎず長すぎず

7. タイムアウト値の決め方!短すぎず長すぎず
7. タイムアウト値の決め方!短すぎず長すぎず

タイムアウトを何秒に設定するかは、非常に悩ましい問題です。

短すぎると、本当は成功するはずだった処理を途中で切ってしまいます。逆に長すぎると、利用者が「このアプリ、固まってるな」と不快に感じてしまいます。

一般的な目安としては、ネットの通信なら3秒から10秒、パソコンの中の計算なら1秒以内、といった具合に、その処理が普通ならどれくらいで終わるかを基準に決めます。まずは長めに設定してみて、慣れてきたら最適な数字に調整していきましょう。

8. 異常系への意識!「もしも」を考えるのがプロの道

8. 異常系への意識!「もしも」を考えるのがプロの道
8. 異常系への意識!「もしも」を考えるのがプロの道

プログラミング未経験の方が最初に覚えるのは「正しい動かし方」ですが、一歩先に進むために必要なのは「うまくいかなかった時の備え」です。

これを異常系(いじょうけい)と呼びます。世界中の有名なアプリやサービスも、実は中身の半分以上はこの異常系への対策でできています。

「もしインターネットが切れたら?」「もしファイルが壊れていたら?」といった意地悪な質問を自分のプログラムに投げかけてみてください。タイムアウトとリトライは、その質問に対する力強い回答になります。

9. 学習のポイントと注意点

9. 学習のポイントと注意点
9. 学習のポイントと注意点

最後に、今回学んだことの重要なポイントを振り返りましょう。

  • timeoutは必ずrescueする: 時間切れのまま放置するとプログラムが止まってしまいます。
  • リトライ回数には上限を: 永遠にやり直すと、パソコンの電池や通信量を使い果たしてしまいます。
  • 重要なデータ操作は慎重に: 銀行の振り込みのような「二回やってはいけない処理」にリトライを使うときは、注意が必要です。

これらの道具を正しく使いこなせば、あなたの作るRubyプログラムの信頼性は一気に高まります!

10. 粘り強いプログラムで快適な開発を

10. 粘り強いプログラムで快適な開発を
10. 粘り強いプログラムで快適な開発を

パソコンを触ったことがない方にとって、今日の話は「失敗すること」を前提にした少し不思議な話だったかもしれません。

でも、プログラミングにおいて失敗は友達です。失敗が起きることを最初から予想して、それに対処する「loop」や「timeout」を組み込んでおけば、どんな荒波の中でも動き続ける逞しいアプリが作れます。

Rubyという言語は、こうした複雑な制御もまるで英語を読んでいるかのように直感的に書けるのが魅力です。今日学んだ設計パターンを参考に、ぜひあなたも「エラーに負けない強いプログラム」への第一歩を踏み出してくださいね!

関連記事:
カテゴリの一覧へ
新着記事
New1
データベース
データベースのダーティリードとは?SQLトランザクションの仕組みを初心者向けに徹底図解
New2
Ruby
Rubyのタイムアウトとリトライ制御を徹底解説!loopとtimeoutでエラーに強いプログラムを作る
New3
Ruby
Ruby配列の破壊的メソッドと非破壊的メソッドを完全理解!初心者でも安全に使える配列操作
New4
Rails
Railsのアソシエーション基礎を完全ガイド!初心者でもわかるbelongs_to・has_many・has_oneと外部キー
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyの真偽値とnilを徹底解説!初心者が知っておくべき判定ルールと安全な書き方
No.2
Java&Spring記事人気No2
データベース
SQLで複数テーブルを結合する方法を徹底解説!初心者でも図解でわかるJOINと集計の基本
No.3
Java&Spring記事人気No3
Rails
Hotwire超入門:Turbo Drive / Turbo Frames / Turbo Streams を一気に理解【Rails 7 / Rails 8】
No.4
Java&Spring記事人気No4
Ruby
WindowsでRubyをインストールする方法!RubyInstallerとMSYS2を使った完全ガイド
No.5
Java&Spring記事人気No5
データベース
SQLのJOIN(結合)を完全攻略!INNER JOINとLEFT JOINの違いを初心者向けに徹底解説
No.6
Java&Spring記事人気No6
データベース
SQLのWHERE句とは?初心者でもわかる条件指定の基本を徹底解説
No.7
Java&Spring記事人気No7
Ruby
Rubyのcatchとthrowを徹底解説!複雑な多重ループから一気に脱出する方法
No.8
Java&Spring記事人気No8
Ruby
Rubyの論理演算子をマスター!and/orと&&/||の違いと優先順位の罠