Whenever gem扩展开发指南:构建自定义Ruby定时任务插件
【免费下载链接】whenever Cron jobs in Ruby 项目地址: https://gitcode.com/gh_mirrors/wh/whenever
1. 插件开发基础
Whenever是一个Ruby gem,提供了清晰的语法来编写和部署cron任务。通过扩展Whenever,你可以创建自定义的任务类型和功能,以满足特定的业务需求。本指南将详细介绍如何开发Whenever插件,包括核心概念、扩展点和实际示例。
1.1 核心概念
- Job(任务):Whenever的基本执行单元,由lib/whenever/job.rb定义
- Job Type(任务类型):预定义的任务模板,如command、runner和rake
- Schedule(调度):任务的时间规划,通过config/schedule.rb文件配置
- Cron Syntax(Cron语法):任务调度的时间表达式,由Whenever自动转换
1.2 扩展点
Whenever提供了多个扩展点:
- 自定义Job Type:通过
job_type方法定义新的任务类型 - 任务模板覆盖:修改默认的任务执行模板
- Cron生成逻辑:扩展时间解析和Cron表达式生成
- Capistrano集成:自定义部署流程,相关代码在lib/whenever/capistrano/
2. 开发环境搭建
2.1 项目结构
首先,确保你的开发环境包含以下结构:
your-plugin/
├── lib/
│ ├── whenever/
│ │ └── plugins/
│ │ └── your_plugin.rb
│ └── whenever-your-plugin.rb
├── spec/
│ └── your_plugin_spec.rb
├── Gemfile
└── your-plugin.gemspec
2.2 依赖配置
在你的gemspec文件中添加依赖:
spec.add_dependency 'whenever', '~> 1.0'
spec.add_development_dependency 'rspec', '~> 3.0'
3. 自定义Job Type开发
3.1 基础示例
自定义Job Type是最常见的扩展方式。例如,创建一个用于发送邮件的任务类型:
# config/schedule.rb
require 'whenever/plugins/email_job'
job_type :email, 'sendmail -t <<EMAIL
To: :recipient
Subject: :subject
:body
EMAIL'
every 1.day, at: '9:00 am' do
email recipient: 'admin@example.com',
subject: 'Daily Report',
body: 'Here is your daily report...'
end
3.2 实现原理
每当定义新的job_type时,Whenever会创建一个模板,该模板会在生成cron任务时被处理。核心处理逻辑在lib/whenever/job.rb的process_template方法中:
def process_template(template, options)
template.gsub(/:\w+/) do |key|
before_and_after = [$`[-1..-1], $'[0..0]]
option = options[key.sub(':', '').to_sym] || key
if before_and_after.all? { |c| c == "'" }
escape_single_quotes(option)
elsif before_and_after.all? { |c| c == '"' }
escape_double_quotes(option)
else
option
end
end.gsub(/\s+/m, " ").strip
end
4. 高级扩展技术
4.1 修改任务执行模板
你可以通过设置:job_template来自定义任务的执行环境:
# config/schedule.rb
set :job_template, "bash -l -c ':job'"
every :day, at: '3:00 am' do
runner "Report.generate"
end
这会生成如下的cron任务:
0 3 * * * bash -l -c 'cd /path/to/app && bin/rails runner -e production '\''Report.generate'\'''
4.2 时间解析扩展
Whenever使用Chronic gem解析时间表达式。你可以通过设置:chronic_options来自定义解析行为:
# config/schedule.rb
set :chronic_options, hours24: true
every 1.day, at: '18:00' do
runner "DailyReport.send"
end
5. 测试与调试
5.1 测试工具
使用whenever-test gem来测试你的调度配置:
# spec/schedule_spec.rb
require 'whenever/test'
describe "Schedule" do
it "should run daily report at 9am" do
schedule = Whenever::Test::Schedule.new
expect(schedule.jobs).to include(
a_job_with(command: "sendmail -t <<EMAIL", at: "9:00 am")
)
end
end
5.2 调试技巧
使用whenever命令查看生成的cron表达式:
bundle exec whenever --set 'environment=development'
6. 部署与集成
6.1 Capistrano集成
通过Capistrano自动部署你的定时任务:
# config/deploy.rb
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
set :whenever_roles, [:app, :db]
Capistrano集成代码位于lib/whenever/capistrano/目录下,支持Capistrano v2和v3版本。
6.2 多环境配置
为不同环境配置不同的任务:
# config/schedule.rb
case @environment
when 'production'
every 1.hour do
runner "Analytics.track"
end
when 'development'
every 10.minutes do
runner "Analytics.track"
end
end
7. 实战示例:API监控插件
下面是一个完整的插件示例,用于监控API端点:
# lib/whenever/plugins/api_monitor.rb
module Whenever
module Plugins
module ApiMonitor
def self.register
Whenever::JobType.add :api_monitor, <<~JOB
curl -s :url | grep -q :expected_content || echo "API failure" | mail -s "API Alert" :alert_email
JOB
end
end
end
end
Whenever::Plugins::ApiMonitor.register
使用方法:
# config/schedule.rb
require 'whenever/plugins/api_monitor'
every 5.minutes do
api_monitor url: 'https://api.example.com/health',
expected_content: 'OK',
alert_email: 'admin@example.com'
end
8. 总结与最佳实践
8.1 最佳实践
- 保持任务简洁:每个任务只做一件事,复杂逻辑封装到单独的Ruby类中
- 错误处理:确保任务有完善的错误处理和日志记录
- 测试覆盖:为自定义任务编写单元测试和集成测试
- 环境隔离:不同环境使用不同的调度策略
8.2 扩展方向
- 任务依赖管理:实现任务间的依赖关系
- 高级时间表达式:支持更复杂的调度模式
- 任务执行状态跟踪:记录任务执行结果和状态
通过本文介绍的方法,你可以构建强大的自定义定时任务插件,扩展Whenever的功能以满足各种复杂需求。开始创建你的第一个插件,提升Ruby应用的定时任务管理能力吧!
【免费下载链接】whenever Cron jobs in Ruby 项目地址: https://gitcode.com/gh_mirrors/wh/whenever
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



