見出し画像

Go開発者必見!gocronでタスクを毎日・週次・月次で効率的に実行する方法

簡単で流暢なGoのcronスケジューリング。これはjasonlvhit/gocronからのフォークです。

crontab guruからの画像

Goプログラミング言語自体を使用して、タスクを毎日、毎週、毎月、一回限り、またはcronを使用して実行するようにスケジュールすることができます。
私はmicronaut[Javaフレームワーク]の@Scheduledアノテーションに慣れており、Java世界では本当に素晴らしいものでした。しかし、Go言語の世界では、私はginフレームワークを使用していました。毎日午前12時にタスクを実行する必要がありました。3つの解決策がありました:

  1. *nixのcronを使用する

  2. スケジューラを自分で実装する

  3. サードパーティのパッケージを使用する

はい、私はオプション3を選択しました。なぜなら、それが簡単で、車輪を再発明する必要がないからです。

私は2つのパッケージを見つけました:

  1. https://github.com/jasonlvhit/gocron: [最終更新は3年前]

  2. https://github.com/go-co-op/gocron: [上記パッケージのフォークで定期的にメンテナンスされています]

現在のメンテナーからの注意事項:このプロジェクトの現在メンテナンスされているフォークはhttps://github.com/go-co-op/gocronに移行されました

免責事項:私たち(メンテナー)は、新しいメンテナーを追加するか、プロジェクトを組織内に移すために、Jason(リポジトリの所有者)に連絡を取ろうとしましたが、残念ながら成功しませんでした。彼は数ヶ月間(2020年3月)返信をしていません。そこで、できるだけ多くの人々からプロジェクトの発展を継続するために、プロジェクトを新しいリポジトリ(上記の通り)に移行することを決定しました。お気軽にご連絡ください!

バックエンドWebサーバーのスケジューラを使用する方が、OSのcronjobよりも優れている理由:

  • 環境に依存しない、つまりバックエンド言語がサポートされているすべてのオペレーティングシステムで動作する

  • 様々な環境でのデプロイメントと運用が簡素化される

  • アプリケーションのコードベースと設定ファイルに統合される(バージョン管理される)

  • 動的なスケーリング要件により適応的

  • アプリケーションの一部として実行されるため、バックエンドスケジューラはアプリケーションのコンテキスト、リソース、サービスに直接アクセスできる

  • より優れたエラー処理とログ記録

  • 標準的なテスト手法を使用してアプリケーションと共にテストできる

  • アプリケーションのセキュリティコンテキスト内で動作し、権限管理を簡素化し、個別または特権的な権限に関連するセキュリティ問題のリスクを低減する

  • すべての*nix環境がenhanced cronをサポートしているわけではない

  • PaaSを使用している場合で、PaaSがスケジューリングやcronを提供していない場合でも、タスクをスケジュールできる

理解を深めましょう。

gocronを使用するために知っておく必要がある4つの概念があります。

  1. タスク

  2. ジョブ

  3. スケジューラ

  4. エグゼキューター

タスク:

  • ジョブによって実行される必要のあるGo関数です。

gocron.NewTask(
   func(a string, b int) {
    // do things
   },
   "hello",
   1,
  ),
  
a and b are the parameter
we are passing "hello" and 1 to the function

ジョブ:

  • ジョブはタスクをカプセル化します

  • タスクをいつ実行すべきかの情報を含みます:

  • Duration: 固定のtime.Durationで実行

  • Random Duration: 最小値と最大値の間のランダムなtime.Durationで実行

  • Cron: crontabを使用して実行

  • Daily: 特定の時間に x 日ごとに実行

  • Weekly: 特定の曜日と時間に x 週ごとに実行

  • Monthly: 特定の日付と時間に x ヶ月ごとに実行

  • One Time: 特定の時間に一回だけ実行。これらは非繰り返しジョブです。

スケジューラ:

  • スケジューラはすべてのジョブを追跡し、実行準備ができたときに各ジョブをエグゼキューターに送信します。

エグゼキューター:

  • エグゼキューターはジョブのタスクを呼び出し、異なるジョブ実行タイミング要件の複雑さを管理します(例:互いに重複して実行されるべきではないシングルトン、実行中のジョブの最大数の制限など)

:詳細については、ドキュメントをお読みください。

コーディングを始めましょう。

手順:

  • gocronパッケージをインストール

go get github.com/go-co-op/gocron/v2
  • スケジューラのインスタンスを作成

s, err := gocron.NewScheduler()
  • タスクを作成:

task := gocron.NewTask(
 func(a string, b int) {
  // do things
 },
 "hello",
 1,
)
  • ジョブにタスクを割り当て:

j, err := s.NewJob(
 gocron.DurationJob(
  10*time.Second,
 ),
 gocron.NewTask(task),
)
  • スケジュールを開始

s.Start()

以下のケースを実装してみましょう:
— タスクは毎日午前12時に実行する必要があり、タイムゾーンはAsia/Kathmandu。

package main

import (
 "fmt"
 "time"

 "github.com/go-co-op/gocron/v2"
)

func main() {
  // time location of Asia/Kathmandu
  ktmLocation, err := time.LoadLocation("Asia/Kathmandu")
  if err != nil {
  // handle error
 }
 
 // create a scheduler
 // assign time to our location
 s, err := gocron.NewScheduler(
  gocron.WithLocation(
   ktmLocation,
  ),
 )
 if err != nil {
  // handle error
 }
 
 task := gocron.NewTask(
  func(a string, b int) {
   // do things
   // your business logic
  },
  "hello",
  1,
 )
 
 // cron tab which run at 12am
 // 2nd argument boolean is used for enhance cron
 // check below for detail
 jobType := gocron.CronJob(
   "0 0 * * *",
   false,
 )

 // add a job to the scheduler
 j, err := s.NewJob(jobType, task)
 if err != nil {
  // handle error
 }
 
 // each job has a unique id
 fmt.Println(j.ID())

 // start the scheduler
 s.Start()

 // block until you are ready to shut down
 select {
 case <-time.After(time.Minute):
 }

 // when you're done, shut it down
 err = s.Shutdown()
 if err != nil {
  // handle error
 }
}

完了です。本当に簡単ですよね。
CRON:

  1. 従来のCron(分レベルの精度):分レベルの精度で動作し、毎秒を指定することはできません

  2. Enhanced Cron(秒レベルの精度)[gocronもこれをサポート]:QuartzスケジューラやモダンなCronライクなタスクスケジューラ(例:プログラミングライブラリの一部の実装)のような一部のシステムは、秒レベルのスケジューリングを可能にします

ドキュメントを参照してください。使用方法は本当に簡単です。
README: https://github.com/go-co-op/gocron?tab=readme-ov-file#gocron-a-golang-job-scheduling-package
Go Docs: https://pkg.go.dev/github.com/go-co-op/gocron/v2#section-readme

gocronのその他の機能:

  • 分散インスタンスをサポート

  • ジョブイベントはアクションをトリガーできる(リスナーをジョブに追加可能)

  • 多くのジョブとスケジューラオプションが利用可能:

  • ジョブオプション:NewJobに引数を渡す

  • グローバルジョブオプションNewSchedulerのWithGlobalJobOptionsオプションに引数を渡す

  • スケジューラオプションNewSchedulerに引数を渡す

  • ログを有効化可能:Loggerインターフェースを実装するだけ

  • モニター:各ジョブの実行からメトリクスを収集可能。

  • テストをサポート

ありがとうございました!


この記事は、2024 年 6 月に弊社のエンジニア Mukesh Kumar Chaudhary が執筆し、日本語に翻訳したものです。
英語版はこちらをクリックしてください。
https://articles.wesionary.team/gocron-schedule-your-task-using-golang-4b110d6ec862


採用情報

私たちはプロダクト共創の仕組み化に取り組んでいます。プロダクト共創をリードするプロダクト・マネージャー、そして、私たちのビジョンを市場に届ける営業メンバーを募集しています!


開発パートナーをお探しの企業様へ

弊社は、グローバル開発のメリットを活かし、高い費用対効果と品質を両立しています。経験豊富で多様性のあるチームが、課題を正しく理解し、最適なシステムと優れた体験を実現します。業務システムの開発、新規事業の開発、業務効率化やDX化に関するお困りごと、ぜひ弊社にご相談ください。