Giter Site home page Giter Site logo

sidekiq-cron / sidekiq-cron Goto Github PK

View Code? Open in Web Editor NEW
1.8K 1.8K 274.0 1.11 MB

Scheduler / Cron for Sidekiq jobs

License: MIT License

Ruby 92.19% HTML 7.52% Dockerfile 0.29%
cron-jobs ruby ruby-gem ruby-on-rails scheduled-jobs scheduler sidekiq sidekiq-cron sidekiq-jobs sidekiq-workers

sidekiq-cron's Introduction

Sidekiq-Cron

Gem Version Build Status codecov

A scheduling add-on for Sidekiq

๐ŸŽฌ Introduction video about Sidekiq-Cron by Drifting Ruby

Sidekiq-Cron runs a thread alongside Sidekiq workers to schedule jobs at specified times (using cron notation * * * * * parsed by Fugit).

Checks for new jobs to schedule every 30 seconds and doesn't schedule the same job multiple times when more than one Sidekiq process is running.

Scheduling jobs are added only when at least one Sidekiq process is running, but it is safe to use Sidekiq-Cron in environments where multiple Sidekiq processes or nodes are running.

If you want to know how scheduling work, check out under the hood.

Works with ActiveJob (Rails 4.2+).

You don't need Sidekiq PRO, you can use this gem with plain Sidekiq.

Changelog

Before upgrading to a new version, please read our Changelog.

Installation

Install the gem:

$ gem install sidekiq-cron

Or add to your Gemfile and run bundle install:

gem "sidekiq-cron"

NOTE If you are not using Rails, you need to add require 'sidekiq-cron' somewhere after require 'sidekiq'.

Getting Started

Job properties

{
  # MANDATORY
  'name' => 'name_of_job', # must be uniq!
  'cron' => '1 * * * *',  # execute at 1 minute of every hour, ex: 12:01, 13:01, 14:01, ...
  'class' => 'MyClass',
  # OPTIONAL
  'namespace' => 'YourNamespace', # groups jobs together in a namespace (Default value is 'default'),
  'source' => 'dynamic', # source of the job, `schedule`/`dynamic` (default: `dynamic`)
  'queue' => 'name of queue',
  'args' => '[Array or Hash] of arguments which will be passed to perform method',
  'date_as_argument' => true, # add the time of execution as last argument of the perform method
  'active_job' => true,  # enqueue job through Rails 4.2+ Active Job interface
  'queue_name_prefix' => 'prefix', # Rails 4.2+ Active Job queue with prefix
  'queue_name_delimiter' => '.', # Rails 4.2+ Active Job queue with custom delimiter (default: '_')
  'description' => 'A sentence describing what work this job performs'
  'status' => 'disabled' # default: enabled
}

NOTE The status of a job does not get changed in Redis when a job gets reloaded unless the status property is explicitly set.

Time, cron and Sidekiq-Cron

For testing your cron notation you can use crontab.guru.

Sidekiq-Cron uses Fugit to parse the cronline. So please, check Fugit documentation for further information about allowed formats.

If using Rails, this is evaluated against the timezone configured in Rails, otherwise the default is UTC.

If you want to have your jobs enqueued based on a different time zone you can specify a timezone in the cronline, like this '0 22 * * 1-5 America/Chicago'.

Natural-language formats

Since sidekiq-cron v1.7.0, you can use the natural-language formats supported by Fugit, such as:

"every day at five" # => '0 5 * * *'
"every 3 hours"     # => '0 */3 * * *'

See the relevant part of Fugit documentation for details.

There are multiple modes that determine how natural-language cron strings will be parsed.

  1. :single (default)
Sidekiq::Cron.configure do |config|
  # Note: This doesn't need to be specified since it's the default.
  config.natural_cron_parsing_mode = :single
end

This parses the first possible cron line from the given string and then ignores any additional cron lines.

Ex. every day at 3:15 and 4:30

  • Equivalent to 15 3 * * *.
  • 30 4 * * * gets ignored.
  1. :strict
Sidekiq::Cron.configure do |config|
  config.natural_cron_parsing_mode = :strict
end

This throws an error if the given string would be parsed into multiple cron lines.

Ex. every day at 3:15 and 4:30

  • Would throw an error and the associated cron job would be invalid

Second-precision (sub-minute) cronlines

In addition to the standard 5-parameter cronline format, sidekiq-cron supports scheduling jobs with second-precision using a modified 6-parameter cronline format:

Seconds Minutes Hours Days Months DayOfWeek

For example: "*/30 * * * * *" would schedule a job to run every 30 seconds.

Note that if you plan to schedule jobs with second precision you may need to override the default schedule poll interval so it is lower than the interval of your jobs:

Sidekiq::Options[:cron_poll_interval] = 10

The default value at time of writing is 30 seconds. See under the hood for more details.

Namespacing

Default namespace

When not giving a namespace, the default one will be used.

In the case you'd like to change this value, create a new initializer like so:

config/initializers/sidekiq-cron.rb:

Sidekiq::Cron.configure do |config|
  config.default_namespace = 'statics'
end

Usage

When creating a new job, you can optionally give a namespace attribute, and then you can pass it too in the find or destroy methods.

Sidekiq::Cron::Job.create(
  name: 'Hard worker - every 5min',
  namespace: 'Foo',
  cron: '*/5 * * * *',
  class: 'HardWorker'
)
# INFO: Cron Jobs - add job with name Hard worker - every 5min in the namespace Foo

# Without specifying the namespace, Sidekiq::Cron use the `default` one, therefore `count` return 0.
Sidekiq::Cron::Job.count
#=> 0

# Searching in the job's namespace returns 1.
Sidekiq::Cron::Job.count 'Foo'
#=> 1

# Same applies to `all`. Without a namespace, no jobs found.
Sidekiq::Cron::Job.all

# But giving the job's namespace returns it.
Sidekiq::Cron::Job.all 'Foo'
#=> [#<Sidekiq::Cron::Job:0x00007f7848a326a0 ... @name="Hard worker - every 5min", @namespace="Foo", @cron="*/5 * * * *", @klass="HardWorker", @status="enabled" ... >]

# If you'd like to get all the jobs across all the namespaces then pass an asterisk:
Sidekiq::Cron::Job.all '*'
#=> [#<Sidekiq::Cron::Job ...>]

job = Sidekiq::Cron::Job.find('Hard worker - every 5min', 'Foo').first
job.destroy
# INFO: Cron Jobs - deleted job with name Hard worker - every 5min from namespace Foo
#=> true

What objects/classes can be scheduled

Sidekiq Worker

In this example, we are using HardWorker which looks like:

class HardWorker
  include Sidekiq::Worker

  def perform(*args)
    # do something
  end
end

For Sidekiq workers, symbolize_args: true in Sidekiq::Cron::Job.create or in Hash configuration is gonna be ignored as Sidekiq currently only allows for simple JSON datatypes.

Active Job

You can schedule ExampleJob which looks like:

class ExampleJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    # Do something
  end
end

For Active jobs you can use symbolize_args: true in Sidekiq::Cron::Job.create or in Hash configuration, which will ensure that arguments you are passing to it will be symbolized when passed back to perform method in worker.

Adding Cron jobs

Refer to Schedule vs Dynamic jobs to understand the difference.

class HardWorker
  include Sidekiq::Worker

  def perform(name, count)
    # do something
  end
end

Sidekiq::Cron::Job.create(name: 'Hard worker - every 5min', cron: '*/5 * * * *', class: 'HardWorker') # execute at every 5 minutes
# => true

create method will return only true/false if job was saved or not.

job = Sidekiq::Cron::Job.new(name: 'Hard worker - every 5min', cron: '*/5 * * * *', class: 'HardWorker')

if job.valid?
  job.save
else
  puts job.errors
end

# or simple
unless job.save
  puts job.errors # will return array of errors
end

Use ActiveRecord models as arguments:

class Person < ApplicationRecord
end

class HardWorker < ActiveJob::Base
  queue_as :default

  def perform(person)
    puts "person: #{person}"
  end
end

person = Person.create(id: 1)
Sidekiq::Cron::Job.create(name: 'Hard worker - every 5min', cron: '*/5 * * * *', class: 'HardWorker', args: person)
# => true

Load more jobs from hash:

hash = {
  'name_of_job' => {
    'class' => 'MyClass',
    'cron'  => '1 * * * *',
    'args'  => '(OPTIONAL) [Array or Hash]'
  },
  'My super iber cool job' => {
    'class' => 'SecondClass',
    'cron'  => '*/5 * * * *'
  }
}

Sidekiq::Cron::Job.load_from_hash hash

Load more jobs from array:

array = [
  {
    'name'  => 'name_of_job',
    'class' => 'MyClass',
    'cron'  => '1 * * * *',
    'args'  => '(OPTIONAL) [Array or Hash]'
  },
  {
    'name'  => 'Cool Job for Second Class',
    'class' => 'SecondClass',
    'cron'  => '*/5 * * * *'
  }
]

Sidekiq::Cron::Job.load_from_array array

Bang-suffixed methods will remove jobs where source is schedule and are not present in the given hash/array, update jobs that have the same names, and create new ones when the names are previously unknown.

Sidekiq::Cron::Job.load_from_hash! hash
Sidekiq::Cron::Job.load_from_array! array

Loading jobs from schedule file

You can also load multiple jobs from a YAML (same notation as Resque-scheduler) file:

# config/schedule.yml

my_first_job:
  cron: "*/5 * * * *"
  class: "HardWorker"
  queue: hard_worker

second_job:
  cron: "*/30 * * * *" # execute at every 30 minutes
  class: "HardWorker"
  queue: hard_worker_long
  args:
    hard: "stuff"

There are multiple ways to load the jobs from a YAML file

  1. The gem will automatically load the jobs mentioned in config/schedule.yml file (it supports ERB)
  2. When you want to load jobs from a different filename, mention the filename in sidekiq configuration, i.e. cron_schedule_file: "config/users_schedule.yml"
  3. Load the file manually as follows:
# config/initializers/sidekiq.rb

Sidekiq.configure_server do |config|
  config.on(:startup) do
    schedule_file = "config/users_schedule.yml"

    if File.exist?(schedule_file)
      schedule = YAML.load_file(schedule_file)

      Sidekiq::Cron::Job.load_from_hash!(schedule, source: "schedule")
    end
  end
end

Finding jobs

# return array of all jobs
Sidekiq::Cron::Job.all

# return one job by its unique name - case sensitive
Sidekiq::Cron::Job.find "Job Name"

# return one job by its unique name - you can use hash with 'name' key
Sidekiq::Cron::Job.find name: "Job Name"

# if job can't be found nil is returned

Destroy jobs

# destroy all jobs
Sidekiq::Cron::Job.destroy_all!

# destroy job by its name
Sidekiq::Cron::Job.destroy "Job Name"

# destroy found job
Sidekiq::Cron::Job.find('Job name').destroy

Work with job

job = Sidekiq::Cron::Job.find('Job name')

# disable cron scheduling
job.disable!

# enable cron scheduling
job.enable!

# get status of job:
job.status
# => enabled/disabled

# enqueue job right now!
job.enque!

Schedule vs Dynamic jobs

There are two potential job sources: schedule and dynamic. Jobs associated with schedule files are labeled as schedule as their source, whereas jobs created at runtime without the source=schedule argument are classified as dynamic.

The key distinction lies in how these jobs are managed. When a schedule is loaded, any stale schedule jobs are automatically removed to ensure synchronization within the schedule. The dynamic jobs remain unaffected by this process.

How to start scheduling?

Just start Sidekiq workers by running:

$ bundle exec sidekiq

Web UI for Cron Jobs

If you are using Sidekiq's web UI and you would like to add cron jobs too to this web UI, add require 'sidekiq/cron/web' after require 'sidekiq/web'.

With this, you will get:

Web UI

Under the hood

When you start the Sidekiq process, it starts one thread with Sidekiq::Poller instance, which perform the adding of scheduled jobs to queues, retries etc.

Sidekiq-Cron adds itself into this start procedure and starts another thread with Sidekiq::Cron::Poller which checks all enabled Sidekiq cron jobs every 30 seconds, if they should be added to queue (their cronline matches time of check).

Sidekiq-Cron is checking jobs to be enqueued every 30s by default, you can change it by setting:

Sidekiq::Options[:cron_poll_interval] = 10

When sidekiq (and sidekiq-cron) is not used in zero-downtime deployments, after the deployment is done sidekiq-cron starts to catch up. It will consider older jobs that missed their schedules during that time. By default, only jobs that should have started less than 1 minute ago are considered. This is problematic for some jobs, e.g., jobs that run once a day. If on average sidekiq is shut down for 10 minutes during deployments, you can configure sidekiq-cron to consider jobs that were about to be scheduled during that time:

# config/initializers/sidekiq-cron.rb

Sidekiq::Cron.configure do |config|
  config.reschedule_grace_period = 600 # 10 minutes in seconds
end

Sidekiq-Cron is safe to use with multiple Sidekiq processes or nodes. It uses a Redis sorted set to determine that only the first process who asks can enqueue scheduled jobs into the queue.

When running with many Sidekiq processes, the polling can add significant load to Redis. You can disable polling on some processes by setting Sidekiq::Options[:cron_poll_interval] = 0 on these processes.

Contributing

Thanks to all contributors, youโ€™re awesome and this wouldnโ€™t be possible without you!

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so we don't break it in a future version unintentionally.
  • Open a pull request!

Testing

You can execute the test suite by running:

$ bundle exec rake test

Using Docker

Docker allows you to run things in containers easing the development process.

This project uses Docker Compose in order to orchestrate containers and get the test suite running on you local machine, and here you find the commands to run in order to get a complete environment to build and test this gem:

  1. Build the Docker image (only the first time):
docker compose -f docker/docker-compose.yml build
  1. Run the test suite:
docker compose -f docker/docker-compose.yml run --rm tests

This command will download the first time the project's dependencies (Redis so far), create the containers and run the default command to run the tests.

Running other commands

In the case you need to run a command in the gem's container, you would do it like so:

docker compose -f docker/docker-compose.yml run --rm tests <HERE IS YOUR COMMAND>

Note that tests is the Docker Compose service name defined in the docker/docker-compose.yml file.

Running a single test file

Given you only want to run the tests from the test/unit/web_extension_test.rb file, you need to pass its path with the TEST env variable, so here is the command:

docker compose -f docker/docker-compose.yml run --rm --env TEST=test/unit/web_extension_test.rb tests

License

Copyright (c) 2013 Ondrej Bartas. See LICENSE for further details.

sidekiq-cron's People

Contributors

284km avatar adrianobarroso avatar cabello avatar dwarburt avatar engwan avatar fatkodima avatar felixbuenemann avatar giriss avatar jmettraux avatar kevinrobell-st avatar le0pard avatar lepfhty avatar markets avatar mikerogers0 avatar mmartyn avatar mrchucho avatar n00dle avatar ngouy avatar ondrejbartas avatar ox0rigin avatar petergoldstein avatar safeforge avatar sandip-mane avatar serprex avatar stanhu avatar stephankaag avatar sue445 avatar tfluehmann avatar vsuhachev avatar ybiquitous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sidekiq-cron's Issues

Possible sidekiq 3.4.2 issue - views need csrf_tag

I could confirm by changing this in the code - the forms just need a new <%= csrf_tag %> input element added to them.

I couldn't do this by myself and send you a pull request because your tests don't pass if I just do a rake test - I haven't worked enough with Sinatra apps and standalone gems to figure out if I should have done something else to get the tests to pass. If you can tell me that I'm happy to do this on my own and send you a PR.

Using 0 * * * * * results in a job that runs every minute, versus every hour.

Using

      name: 'RedactedWorker',
      cron: '0 * * * * * ',
      class: 'RedactedWorker',
      args: [])

results in this job being queued every minute instead of every hour which is what the cron format of '0 * * * * *' means from my understanding.

016-04-12T11:49:01Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:50:01Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:51:01Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:52:01Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:53:02Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:54:02Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker
2016-04-12T11:55:02Z 19075 TID-oxri47l10 INFO: Cron Jobs - add job with name: RedactedWorker

Jobs not running with sidekiq 3.2.4

I have tried adding jobs via a direct code calls in my worker class:

class TestWorker
  include Sidekiq::Worker

  def perform
    logger.info "TestWorker perform"
  end
end

Sidekiq::Cron::Job.create( name: 'TestWorker_Job', cron: '* * * * *', klass: 'TestWorker')

Per another issue, I also setup a yaml file and loaded it with Sidekiq::Cron::Job.load_from_hash:

# in initializers/sidekiq.rb
def configure_cron
  rails_root = File.dirname(__FILE__) + '/../..'
  schedule_file = rails_root + "/config/sidekiq_cron.yml"
  if File.exists?(schedule_file)
    sidekiq_cron = YAML.load_file(schedule_file)
    Sidekiq::Cron::Job.load_from_hash sidekiq_cron
  end
end


Sidekiq.configure_server do |config|
  configure_cron
end

In the latter case, I see the job being scheduled when sidekiq boots, but the job never runs:

2014-11-09T23:28:27.845Z 95862 TID-znsr8o INFO: Booting Sidekiq 3.2.4 with redis options {:url=>"redis://127.0.0.1:6379"}
2014-11-09T23:28:27.849Z 95862 TID-znsr8o INFO: Cron Jobs - add job with name: test_worker
2014-11-09T23:28:28.531Z 95862 TID-znsr8o INFO: Running in ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
2014-11-09T23:28:28.531Z 95862 TID-znsr8o INFO: See LICENSE and the LGPL-3.0 for licensing details.
2014-11-09T23:28:28.531Z 95862 TID-znsr8o INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org/pro
2014-11-09T23:28:28.531Z 95862 TID-znsr8o INFO: Starting processing, hit Ctrl-C to stop
2014-11-09T23:28:28.532Z 95862 TID-119yr80 DEBUG: {:queues=>["default"], :labels=>[], :concurrency=>25, :require=>".", :environment=>nil, :timeout=>8, :error_handlers=>[#], :lifecycle_events=>{:startup=>[], :quiet=>[], :shutdown=>[]}, :verbose=>true, :strict=>true, :tag=>"totem-webapp"}

When sidekiq boots, I do see all the cron_job redis activity that seems correct:

1415575816.535592 [0 127.0.0.1:56999] "exists" "cron_job:test_worker"
1415575816.535819 [0 127.0.0.1:56999] "hget" "cron_job:test_worker" "status"
1415575816.535993 [0 127.0.0.1:56999] "exists" "cron_job:test_worker"
1415575816.536155 [0 127.0.0.1:56999] "hget" "cron_job:test_worker" "last_enqueue_time"
1415575816.537319 [0 127.0.0.1:56999] "sadd" "cron_jobs" "cron_job:test_worker"
1415575816.537582 [0 127.0.0.1:56999] "hmset" "cron_job:test_worker" "name" "test_worker" "klass" "TestWorker" "cron" "* * * * *" "args" "[]" "message" "{\"retry\":true,\"queue\":\"default\",\"class\":\"TestWorker\",\"args\":[]}" "status" "enabled" "last_enqueue_time" ""
1415575816.537972 [0 127.0.0.1:56999] "zadd" "cron_job:test_worker:enqueued" "1415575816.5377338" "2014-11-09 23:30:00 UTC"

But the jobs never execute...

Could it be a sidekiq 3.2 compatibility issue?

Feature request: Enqueue every x seconds

Hi,

At first: Thanks for your great work!

And here is my feature request:

It would be nice if you could add somehow the option, to run tasks not only for example once per minute, but for example every ten seconds. I don't know how it will fit to the cron syntax, but maybe there is a way?

What do you think?

Thanks!

error when i try create a job

when i try create a job in a console:
job = Sidekiq::Cron::Job.new( name: 'Hard worker - every 5min', cron: '*/5 * * * *', klass: 'HardWorker')
job.valid? - false
job.errors - ["'cron' -> */5 * * * *: uninitialized constant Rufus::Scheduler::CronLine"]
job.save - false
the same problem with in yml file

Help me

3 tests fail with sidekiq-cron 0.4.2

RUBYLIB=/home/pravi/forge/debian/gitlab/ruby-sidekiq-cron-0.4.2/debian/ruby-sidekiq-cron/usr/lib/ruby/vendor_ruby:. rake2.2 -f debian/ruby-tests.rake
/usr/bin/ruby2.2 -I"test"  "/usr/lib/ruby/vendor_ruby/rake/rake_test_loader.rb" "test/unit/job_test.rb" "test/unit/poller_test.rb" "test/unit/web_extesion_test.rb" "test/test_helper.rb" -v
Run options: -v --seed 16733

# Running:

.......FFF.....................................................................WARN: tilt autoloading 'tilt/erubis' in a non thread-safe way; explicit require 'tilt/erubis' suggested.
........

   1) enqueue job
      Queue should have 1 job.
      Expected: 1
        Actual: 0
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest/utils/extension.rb:6
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:163
      # test/unit/web_extesion_test.rb:72
      # /usr/lib/ruby/vendor_ruby/sidekiq.rb:84
      # /usr/lib/ruby/vendor_ruby/connection_pool.rb:64
      # /usr/lib/ruby/vendor_ruby/connection_pool.rb:63
      # /usr/lib/ruby/vendor_ruby/connection_pool.rb:63
      # /usr/lib/ruby/vendor_ruby/connection_pool.rb:60
      # /usr/lib/ruby/vendor_ruby/connection_pool.rb:60
      # /usr/lib/ruby/vendor_ruby/sidekiq.rb:81
      # test/unit/web_extesion_test.rb:71
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:108
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:205
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:105
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:256
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:104
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:276
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:103
      # /usr/lib/ruby/vendor_ruby/minitest.rb:781
      # /usr/lib/ruby/vendor_ruby/minitest.rb:308
      # /usr/lib/ruby/vendor_ruby/minitest.rb:296
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest.rb:321
      # /usr/lib/ruby/vendor_ruby/minitest.rb:294
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest.rb:56

   2) disable and enable cron job
      Expected: "enabled"
        Actual: "disabled"
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest/utils/extension.rb:6
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:163
      # test/unit/web_extesion_test.rb:58
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:108
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:205
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:105
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:256
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:104
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:276
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:103
      # /usr/lib/ruby/vendor_ruby/minitest.rb:781
      # /usr/lib/ruby/vendor_ruby/minitest.rb:308
      # /usr/lib/ruby/vendor_ruby/minitest.rb:296
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest.rb:321
      # /usr/lib/ruby/vendor_ruby/minitest.rb:294
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest.rb:56

   3) destroy job
      Should have zero jobs.
      Expected: 1
        Actual: 0
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest/utils/extension.rb:6
      # /usr/lib/ruby/vendor_ruby/minitest/assertions.rb:163
      # test/unit/web_extesion_test.rb:86
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:108
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:205
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:105
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:256
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:104
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:276
      # /usr/lib/ruby/vendor_ruby/minitest/test.rb:103
      # /usr/lib/ruby/vendor_ruby/minitest.rb:781
      # /usr/lib/ruby/vendor_ruby/minitest.rb:308
      # /usr/lib/ruby/vendor_ruby/minitest.rb:296
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:295
      # /usr/lib/ruby/vendor_ruby/minitest.rb:334
      # /usr/lib/ruby/vendor_ruby/minitest.rb:321
      # /usr/lib/ruby/vendor_ruby/minitest.rb:294
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:155
      # /usr/lib/ruby/vendor_ruby/minitest.rb:129
      # /usr/lib/ruby/vendor_ruby/minitest.rb:56

Finished in 1.064134s, 81.7566 runs/s, 179.4887 assertions/s.
87 runs, 191 assertions, 3 failures, no errors, no skips

Failed Tests:

rake TEST=/home/pravi/forge/debian/gitlab/ruby-sidekiq-cron-0.4.2/test/unit/web_extesion_test.rb TESTOPTS="--name=test_0002_enqueue job"
rake TEST=/home/pravi/forge/debian/gitlab/ruby-sidekiq-cron-0.4.2/test/unit/web_extesion_test.rb TESTOPTS="--name=test_0001_disable and enable cron job"
rake TEST=/home/pravi/forge/debian/gitlab/ruby-sidekiq-cron-0.4.2/test/unit/web_extesion_test.rb TESTOPTS="--name=test_0003_destroy job"

Non-unique Cron Jobs

I โค๏ธ the fact that sidekiq-cron automatically makes sure that each job gets run just a single time across many nodes of my application, but is there room in this gem for a feature that lets you run a given cron on each instance of your application?

I'm thinking of a cron that cleans up old files so instead of running it once across a cluster of application instances I would like to have it run once on each instance.

I didn't see any discussion in previous issues. Is this a feature that has been discussed or thought about?

Clicking Enqueue Now on Sidekiq web dashboard schedules the same job

On the Sidekiq web dashboard. Clicking the "Enqueue Now" button schedules the same job. Which means, multiple jobs of the same kind are run concurrently.

Readme says "Checks for new jobs to schedule every 10 seconds and doesn't schedule the same job multiple times when more than one Sidekiq worker is running."

Wondering if this this the expected behaviour?

Clicking buttons in web ui return 'Forbidden'

After upgrade sidekiq to 3.4.2, clicking 'EnqueueNow', 'Disable', 'Enable' and 'Delete' button returns 'Forbidden'.

It may be caused by the new sidekiq requiring authenticity token for the post forms.

Expiring a cron job?

I'm looking at a use-case where we want to run a job every ten minutes, say, for a month. Any thoughts on the best way to go about that?

I see that sidekiq pro has support for expiring jobs, but that's not an option at the moment.

Would be happy to implement against sidekiq-cron and PR, but curious if anyone has thoughts.

Not an issue, suppressing the output

Is there a simple way to suppress the output when a job is created?

Currently my TravisCI logs are filled with output (we have a lot of tests which rely on events which in turn rely on this).

Asset compilation hanging

This is a weird one. I have the following in an initializer:

schedule_file = "config/jobs_schedule.yml"
if File.exists?(schedule_file) && !Rails.env.test?
  Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
end

When I try to compile assets, the rake task hangs. However, if I comment out the schedule loading, everything is fine. The jobs file is as you would expect:

sitemap:
  cron: "1 0 * * *"
  class: "SitataJobs::MaintenanceSitemapJob"

Nothing really out of the ordinary and the jobs run well. I haven't had to compile assets for a while and so I did not notice this immediately. I'm running jruby 1.7.11 with Rails 3.2.17.

Any help is greatly appreciated.

Jobs loading displayed when I'm running console

The following appear when I'm running console:

$ bundle exec rails c p
2015-10-23T08:19:07.894Z 23914 TID-os3mbtvuw INFO: Cron Jobs - add job with name: batch_mirror_ftp_files_job
2015-10-23T08:19:07.897Z 23914 TID-os3mbtvuw INFO: Cron Jobs - add job with name: batch_rename_processed_ftp_files
Loading production environment (Rails 4.2.4)
irb(main):001:0>
# config/initializers/sidekiq.rb
 schedule_file = "config/schedule.yml"

if File.exists?(schedule_file) && Rails.env.production?
  Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
end

Not able to run a job at a specific hour every day

Hello

I am not able to run a job at a specific hour every day.
My time zone is utc + 1
In my config/application.rb :

config.time_zone = 'Paris'
config.active_record.default_timezone = :local

Here is a sample of my cron for a task running every day, every minutes at 1pm utc+1:
* 12 * * * *

I tried like this too
* 12 * * * * Etc/UTC
and like this
* 13 * * * * Europe/Paris

To be sure I have tried * 13 * * * * and 0 13 * * * * too but without any success

I have nothing in last enque

If I try with something like * * * * * * or 5 * * * * *, it works fine
If I click on "Enqueue now" it works fine

Do you have any advice about how I can find what is wrong or any lead on how to make this work?

Jobs run half as often as they should

After upgrading sidekiq to > 4.0 and sidekiq-cron to > 0.3.1, all of our scheduled jobs executed at exactly or almost exactly half of the frequency that they should have. For example, a job that runs once per minute would simply run once every two minutes. I'm not sure what the cause of this is, but reverting back to 0.3.1 with sidekiq 3.5.4 fixed it.

ActiveJob compatibility

I'm using sidekiq as backend for AJ. All works fine except enqueueing:

2015-03-19T20:20:00.916Z 9752 TID-owfr4v32w WARN: {"retry"=>true, "queue"=>"high", "class"=>"ParseRepoJob", "args"=>["self"], "jid"=>"8759e3380b726d242347f1d0", "enqueued_at"=>1426796400.914447}
2015-03-19T20:20:00.916Z 9752 TID-owfrvkf88 INFO: Cron Jobs - add job with name: parse_self_repo
2015-03-19T20:20:00.916Z 9752 TID-owfr4v32w WARN: undefined method `jid=' for #<ParseRepoJob:0x007fc81160b0b8>

Is there a easy way to fix that?

the job was added to the queue but the script was not executed

in the console I can find the cron job:

pry(main)> job = Sidekiq::Cron::Job.find('update movie status - every 1 day')
=> #<Sidekiq::Cron::Job:0x007fa1c5346b60
 @args=[],
 @cron="25 11 */1 * *",
 @klass="LaterWorker",
 @last_enqueue_time=2014-10-29 11:26:00 +0800,
 @message="{\"retry\":true,\"queue\":\"default\",\"class\":\"LaterWorker\",\"args\":[]}",
 @name="update movie status - every 1 day",
 @status="enabled">

and in the sidekiq.log I can find about this job'log:

2014-10-29T03:26:00.786Z 7011 TID-oxepfiwp4 INFO: Cron Jobs - add job with name: update movie status - every 1 day

and my script about:

class LaterWorker
  include Sidekiq::Worker

  def perform
    Movie.each do |m|
      m.update_attributes(executed:true)        
    end
  end
end

Sidekiq::Cron::Job.create( name: 'update movie status - every 1 day', cron: '25 11 */1 * *', klass: 'LaterWorker')

anyhing wrong about that?

@args encoding leads to memory problem

I'm trying out your gem and notice there is an issue with jobs that have args. After each subsequent enque!, the @Args instance variable is encoded improperly leading to a growing string with each execution. Eventually it leads to a memory max error from Redis:

ERROR: CRON JOB: OOM command not allowed when used memory > 'maxmemory'.

Example of job before an enque!

Sidekiq::Cron::Job.all
=> [#<Sidekiq::Cron::Job:0x007fbbcffe55a0
  @args=["[\"[\\\"asap\\\"]\"]"],
  @cron="*/10 * * * *",
  @klass="Notifications::Runner",
  @last_run_time=2013-09-06 14:24:04 -0700,
  @message=
   "{\"retry\":false,\"queue\":\"default\",\"backtrace\":false,\"class\":\"Notifications::Runner\",\"args\":[\"asap\"]}",
  @name="Notifications: Real-time",
  @status="enabled">]

Example of job again after the enque!

Sidekiq::Cron::Job.all
=> [#<Sidekiq::Cron::Job:0x007fbbd2222370
  @args=["[\"[\\\"[\\\\\\\"asap\\\\\\\"]\\\"]\"]"],
  @cron="*/10 * * * *",
  @klass="Notifications::Runner",
  @last_run_time=2013-09-06 14:28:22 -0700,
  @message=
   "{\"retry\":false,\"queue\":\"default\",\"backtrace\":false,\"class\":\"Notifications::Runner\",\"args\":[\"asap\"]}",
  @name="Notifications: Real-time",
  @status="enabled">]

notice the @Args keeps growing.... not sure how to properly fix this... not familiar with the codebase yet, any ideas?

New Feature: pagination

I would like pagination, similar in behavior to the Scheduled view. I know of another gem, sidekiq-failures, that does this (as an example).

This idea seemed like a good opportunity for me to learn, so I got to work trying to add it myself...

I referred to the Scheduled view's code, and I noticed that it relies on the name of the set (in redis) that contains these items. Specifically, this is in the page("schedule", params[:page], @count) piece of code. In that line, "schedule" is the set in redis that's storing the scheduled jobs.

I followed that down, and found that redis needs this in a number of places. One of them is in order to count the items in that set - this line, for example.

I searched in sidekiq-cron, and I found that the job.rb file is storing each individual job in its own set named in the format "cron_job:#{name}:enqueued". This makes it impossible to hook into the existing page("NAMEOFSET", params[:page], @count) code that sidekiq has for paginating jobs.

I'm wondering a couple things before I move forward any more...

  • Why are jobs each put in their own set ("cron_job:#{name}:enqueued")?
  • Do you know if it would be safe to put jobs into a single set (e.g. "sidekiq-cron")?

Thanks for all your hard work on this gem! Your README is great, too - thanks for that!

redis-namespace

now that sidekiq no longer uses this gem, can we remove this dependancy

Some strange local test failures

I pulled down the code to mess around with today and ran into some unexpected test failures.
Running the tests on master locally is giving me these failures:

1) Failure:
Cron web::work with cron job#test_0001_disable and enable cron job [/Users/adam/code/sidekiq-cron/test/unit/web_extesion_test.rb:58]:
Expected: "enabled"
  Actual: "disabled"


  2) Failure:
Cron web::work with cron job#test_0002_enqueue job [/Users/adam/code/sidekiq-cron/test/unit/web_extesion_test.rb:72]:
Queue should have 1 job.
Expected: 1
  Actual: 0


  3) Failure:
Cron web::work with cron job#test_0003_destroy job [/Users/adam/code/sidekiq-cron/test/unit/web_extesion_test.rb:86]:
Should have zero jobs.
Expected: 1
  Actual: 0

I poked at the test and found that I am getting a 403 from the post in the test:

    56: it "disable and enable cron job" do
    57:   post "/cron/#{@name}/disable"
 => 58:   require 'pry'; binding.pry
    59:   assert_equal "disabled", Sidekiq::Cron::Job.find(@name).status
    60: 
    61:   post "/cron/#{@name}/enable"
    62:   assert_equal "enabled", Sidekiq::Cron::Job.find(@name).status
    63: end

[1] pry(#<Cron web::work with cron job>)> post "/cron/#{@name}/disable"
=> #<Rack::MockResponse:0x007f88f5382310
 @block=nil,
 @body=["Forbidden"],
 @body_string=nil,
 @chunked=false,
 @errors="",
 @header=
  {"Content-Type"=>"text/plain", "X-Content-Type-Options"=>"nosniff", "Content-Length"=>"9"},
 @length=9,
 @original_headers={"Content-Type"=>"text/plain", "X-Content-Type-Options"=>"nosniff"},
 @status=403,
 @writer=
  #<Proc:0x007f88f53820b8@/Users/adam/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/rack-1.6.4/lib/rack/response.rb:30 (lambda)>>

any idea what is going on?
am I missing some setup step?

Thanks!

Different time format breaks job scheduling

We recently started using sidekiq-cron (which is awesome!) and came across an odd bug that prevented any jobs from being enqueued. Long story short, our app has a custom default time format that ended up causing conn.zadd(job_enqueued_key, time.to_f.to_s, formated_last_time(time)) to always return false, thereby causing should_enque? to always return false.

We fixed this by forking and changing the implementation of Sidekiq::Cron::Job#formated_last_time to specify the time string format.

Would there be any interest in merging in a patch that enforces a format for the time? If so, I'd be happy to clean up our code and open a PR. Here's the simple version of our patch: https://github.com/ValencePM/sidekiq-cron/commit/a75a72721cf783c1ef9fbd2a66815edd579bed27.

Daily job did not run, how to diagnose?

I have a job scheduled to run every day at 00:05 UTC which has always run successfully for the last few months. Today I noticed it didn't run, and I can't figure out why it didn't run and why it returns false for job.should_enqueue?

Here are some relevant logs:

irb(main):016:0> job
=> #<Sidekiq::Cron::Job:0x007fdc4c275d78 @name="ActiveUserWorkerJob", @cron="5 0 * * *", @klass="ActiveUserWorker", @status="enabled", @last_enqueue_time=2015-08-05 00:05:00 UTC, @args=[], @message="{\"retry\":true,\"queue\":\"default\",\"class\":\"ActiveUserWorker\",\"args\":[]}">
irb(main):017:0> Time.now.utc
=> 2015-08-06 00:46:06 UTC
irb(main):018:0> job.last_enqueue_time
=> 2015-08-05 00:05:00 UTC
irb(main):019:0> job.should_enque?(Time.now.utc)
=> false

Any ideas?

Note: I'm using v0.2.0

Cron Jobs not running

Hello,

I'm currently running in to an issue where my cron jobs in a AWS environment are not running. My local box works perfectly fine! However, in AWS, i see the job scheduled in the sidekiq-cron tab, but i don't see any trace of the jobs getting executed. Not in the logs or in the job queue, or even reflected on the admin tab (last enqueued remains unchanged). I

t just seems like no worker is actually executing anything and I don't know if this is a setup issue, an environment issue since there doesn't seem to be any trace of any attempts to run it or any errors when loading up the environment.

Any help would be greatly appreciated

This is my setup:

Gemfile

gem 'sidekiq', '2.17.7'
gem 'sidekiq-failures', '0.4.3'
gem "sidekiq-cron", "~> 0.2.0"

Gemfile.lock

    sidekiq (2.17.7)
      celluloid (>= 0.15.2)
      connection_pool (>= 1.0.0)
      json
      redis (>= 3.0.6)
      redis-namespace (>= 1.3.1)
    sidekiq-cron (0.2.0)
      rufus-scheduler (>= 2.0.24)
      sidekiq (>= 2.17.3)
      tilt (< 2.0.0)
    sidekiq-failures (0.4.3)
      sidekiq (>= 2.16.0)

I'm loading the jobs in the initializer:

  Sidekiq.configure_client do |config|
    config.redis = { :url => "redis://#{host}:#{port}/#{db}", :namespace => 'sidekiq'}
  end

  Sidekiq.configure_server do |config|
    config.redis = { :url => "redis://#{host}:#{port}/0", :namespace => 'sidekiq' }
  end

schedule_file = rails_root + "/config/sidekiq_schedule.yml"
if File.exists?(schedule_file)
  sidekiq_cron = YAML.load_file(schedule_file)
  Sidekiq::Cron::Job.load_from_hash sidekiq_cron[Rails.env]
end

Multiple jobs scheduled at the same time

Hi,

We have 2 worker servers running Sidekiq. We added sidekiq-cron and it's adding multiple exactly the same jobs at once.

Its adding 2-4 jobs at the same time.

using Sidekiq 4.0.1

Any ideas why this happens ?

bug with sidekiq 2.15.2

With sidekiq 2.15.2 I get this error when viewing the web UI.

Started GET "/sidekiq/sinatra/500.png" for 127.0.0.1 at 2013-10-18 18:00:56 +0700
NoMethodError - undefined method []' for nil:NilClass: /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:22:inblock (3 levels) in strings'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:21:in each' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:21:inblock (2 levels) in strings'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:20:in each' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:20:inblock in strings'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:19:in each' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-cron-0.1.5/lib/sidekiq/cron/web_extension.rb:19:instrings'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/lib/sidekiq/web_helpers.rb:20:in get_locale' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/lib/sidekiq/web_helpers.rb:24:int'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/web/views/dashboard.erb:4:in block in singleton class' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/web/views/dashboard.erb:-5:ininstance_eval'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/web/views/dashboard.erb:-5:in singleton class' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/web/views/dashboard.erb:-7:in__tilt_70333273343700'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/tilt-1.4.1/lib/tilt/template.rb:170:in call' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/tilt-1.4.1/lib/tilt/template.rb:170:inevaluate'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/tilt-1.4.1/lib/tilt/template.rb:103:in render' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:798:inrender'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:657:in erb' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sidekiq-2.15.2/lib/sidekiq/web.rb:173:inblock in class:Web'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:1541:in call' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:1541:inblock in compile!'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:950:in []' /Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:950:inblock (3 levels) in route!'
/Users/fred/.rvm/gems/ruby-2.0.0-p247/gems/sinatra-1.4.3/lib/sinatra/base.rb:966:in `route_eval'

I think it comes from the Web UI refactoring in this commit:
sidekiq/sidekiq@7a41404
sidekiq/sidekiq#1247

cheers.

Allow intervals for scheduler

I'm trying to convert an existing resque + resque-scheduler application to sidekiq + sidekiq-cron.

I already saw #16 however I think that allowing intervals for jobs does have an added value to this gem.

In my use case I have an admin interface where administrators can specify intervals to run jobs and allowing them to specify as intervals is much more user friendly that having them enter job intervals as cron jobs.

One can express some interval as multiple cron entries however this lead to multiple Sidekiq::Cron::Job for the same job and this is very ugly. I have a database record with job specification and a callback that convert record attributes to job instance. If one create a job that has to be mapped to multiple Sidekiq::Cron::Jobs code will become a mess.

Finally there are some intervals that cannot be converted to cron (or where its conversion is a big mess and not accurate), see for instance this example or think about "repeat every 37 minutes".

A very naive implementation would be to rely a rufus scheduler and use it for recurring jobs, something like:

# Somewhere in initialization code
Sidekiq::Cron::Job.all.select { |j| j.interval? }.each do |job|
  job_id = scheduler.every job.interval do
    job.enque! # Don't know if this is enough to enqueue the job 
    # In rails would be something like
    # job.klass.constantize.perform_async(job.arguments)
  end
  # Persist job id, used later to cancel the job if needed
  job.every_id = job.id
  job.save
end

What do you think?

Incorrect Last Enqueued Date

It seems as though the last enqueued dates are not reflecting the actual last time the job was ran, but rather the time since midnight. Even if I manually enqueue a job the date does not update. Any ideas as to what I could be doing wrong?

One per minute cron jobs not running every minute but every 10ish minutes

Hi,
Looks like for some reasons, cron jobs that I have scheduled every minutes runs weirdly. Sometimes it runs every minutes, sometimes it stops for more than 15minutes than start again by itself.

Do you guys ever noticed that kind of bug ? Any suggestion on how to diagnosed that kind of bug ?

Job did not get updated on heroku

I have written a job which runs every 1 min, deployed to heroku, it ran perfectly fine.
Then I updated that job to run in every 120 mins, when I deployed to heroku the job is still running every 1 min. (In my local env. I changed 1min->5min, it worked fine)
I am using RedisToGo addon on heroku.
The job creation script is in one of the initializers which is as follows:

#initializers/sidekiq.rb

hash = {
  'etl_job' => {
    'class' => 'EtlWorker',
    'cron'  => '*/120 * * * *'
  }
}

if Sidekiq.server?
  Sidekiq::Cron::Job.load_from_hash! hash
end

I tried restarting the worker, app and even RedisToGo server, still no change.
Am I doing something wrong?

attr_reader: for the queue

Dear all,

We have an issue that we have to re-enqueue the sidekiq-cron jobs on every deploy because there could be some new. While runtime we create dynamically new cronable jobs, they are deleted because we reload all of them (as written above). We have implemented a kind of hack that stores these dynamically created jobs on deploy and puts them back afterwards.
The problem is, that we cannot access the queue we have defined for these jobs (except, job.instance_variable_get....) would you agree to create an attribute reader for the queue?
Or doesn't it make any sense to you?

Here is an example
https://gist.github.com/tfluehmann/8807ce5d4ada60c57a39ddbbb9c131d5

Thx

Description isn't very..descritive

I just had to read through the code to actually work out what this gem did.

I originally though it added wrapped cronjobs to the system so that sidekiq jobs got executed by that.

It would be great to say "Run a scheduler thread alongside your sidekiq worker to enqueue jobs at intervals specified in cron notation" or something similar to make it more obvious.

Also - what happens if you have 10 worker processes? won't crons get executed 10 times?

Re-namespace?

I noticed this gem uses the Sidekiq module by putting its code in Sidekiq::Cron. This is a problem as it or other constants you add can collide with Sidekiq's code. Your gem's namespace should be SidekiqCron. Would you change the namespace to avoid any accidental collisions?

Prune old tasks

I've discovered unexpected behaviour, which caused some bugs at the end.

I've used to load tasks from hash on rails load with Sidekiq::Cron::Job.load_from_hash hash

But as it turns out this only adds new tasks to cron, and does not remove old ones. So we ended up with old tasks sitting in the scheduler.

Would like to suggest add new method to load task and clear old ones if they no longer exist.

bin/rails:6: warning: already initialized constant APP_PATH

Hi,

I've got this error when I add sidekiq-cron in my Gemfile and try to start a server:

bin/rails:6: warning: already initialized constant APP_PATH
/home/user/projects/commit/bin/rails:6: warning: previous definition of APP_PATH was here
Usage: rails COMMAND [ARGS]

Sidekiq 4.0.1
Ruby 2.2.2
Rails 4.2.5

Any ideas why this happens?

Load Balancer

This is more to a question than issue.
Sorry about that.

We are wondering how does this work on server that is load balanced? Will multiple task be schedule together?

Does my sidekiq.rb config look sane?

Just checking. At config/initializers/sidekiq.rb, I have got:

require 'sidekiq/web'
require 'sidekiq/cron/web'
require 'sidekiq-cron'

Sidekiq.configure_client do |config|
  config.redis = { url: ENV['REDIS_SERVER_URL'], namespace: "sidekiq_#{Rails.env}" }
end

Sidekiq.configure_server do |config|
  config.redis = { url: ENV['REDIS_SERVER_URL'], namespace: "sidekiq_#{Rails.env}" }
end

Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
  [user, password] == [ENV['AUTHORIZED_USERNAME'], ENV['AUTHORIZED_PASSWORD']]
end

# Sidekiq cron
hash = {
  'Send Slack Summary' => {
    'class' => 'SendSlackSummaryWorker',
    'cron'  => '*/30 * * * *', # Run every 30 minutes
    # 'args'  => [5]
  }
}

Sidekiq::Cron::Job.load_from_hash hash

The Readme wasn't very clear on where to place Sidekiq::Cron::Job.load_from_hash hash in a Rails environment.

Does above configuration look fine?

Deploying on AWS OpsWorks. When running bundle exec rake db:migrate --trace. I get the following error:

Redis::CannotConnectError: Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED)

For some reason, it is trying to connect to the local Redis server.

Problem does not happen locally. Just on Staging and Production.
Readme suggests checking for Sidekiq.server?. Dont know if this helps.

Any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.