pomelo-citrus-scheduler 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +20 -0
- data/Rakefile +0 -0
- data/citrus-scheduler.gemspec +27 -0
- data/lib/citrus-scheduler.rb +8 -0
- data/lib/citrus-scheduler/cron_trigger.rb +19 -0
- data/lib/citrus-scheduler/cron_trigger_decoder.rb +14 -0
- data/lib/citrus-scheduler/job.rb +66 -0
- data/lib/citrus-scheduler/schedule.rb +114 -0
- data/lib/citrus-scheduler/simple_trigger.rb +38 -0
- data/lib/citrus-scheduler/version.rb +7 -0
- data/test/test_schedule.rb +28 -0
- metadata +85 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 602975c89705979ad0a6b2477c38134e4c0ed8f2
         | 
| 4 | 
            +
              data.tar.gz: 481027405914536c19e7300e5d93b2824a75397b
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 9e6929058f53f2b85b78370423e02668b718e23bc13606f141165ac2c02f56072c8abc77fae589562c76f3f89618eb33a4d1be9d3a6241d0de7c2411c035f2e9
         | 
| 7 | 
            +
              data.tar.gz: e1c5c5ab749fa8a56a5218fb147027f52619231c6288444e0ec4a4f84ca40853e9c8cc58072f38918bf5fdbcf072fa94e140e45bfe1a92912eadbb96c0d44270
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            ## Welcome to pomelo-citrus-scheduler
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            pomelo-citrus-scheduler is a simple clone of pomelo-scheduler written in Ruby using EventMachine.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Motivation
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Since NodeJS is influenced by Ruby EventMachine and Python's Twisted model, Ruby should also be able to have its own game server framework like pomelo.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Ruby is a very expressive and eloquent programming language. I was an RoR programmer before and I really like Ruby, When developing this project, I have used many skills like meta-programming and they give me the real pleasures.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Recently, I would focus on my daily work, so I open source this project and hope to have more people participate in this project.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ## Todo
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            This gem is the very first gem I have done in my whole work, it needs to be improved but it already has the ablity to provide the basic infrastructure to other gems, other gems exist in my own repository.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ## Links
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * [EventMachine](https://github.com/eventmachine/eventmachine)
         | 
| 20 | 
            +
            * [pomelo-scheduler](https://github.com/NetEase/pomelo-scheduler)
         | 
    
        data/Rakefile
    ADDED
    
    | 
            File without changes
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            $:.push File.expand_path('../lib', __FILE__)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'citrus-scheduler/version'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Gem::Specification.new do |spec|
         | 
| 10 | 
            +
              spec.name        = 'pomelo-citrus-scheduler'
         | 
| 11 | 
            +
              spec.version     = CitrusScheduler::VERSION
         | 
| 12 | 
            +
              spec.platform    = Gem::Platform::RUBY
         | 
| 13 | 
            +
              spec.authors     = ['MinixLi']
         | 
| 14 | 
            +
              spec.email       = 'MinixLi1986@gmail.com'
         | 
| 15 | 
            +
              spec.description = %q{pomelo-citrus-scheduler is a simple clone of pomelo-scheduler, it is a schedule tool and provide a schedule module which is highly efficient and can support large number job schedule}
         | 
| 16 | 
            +
              spec.summary     = %q{pomelo-scheduler clone written in Ruby using EventMachine}
         | 
| 17 | 
            +
              spec.homepage    = 'https://github.com/minixli/pomelo-citrus-scheduler'
         | 
| 18 | 
            +
              spec.license     = 'MIT'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              spec.files         = `git ls-files`.split($/)
         | 
| 21 | 
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 22 | 
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 23 | 
            +
              spec.require_paths = ['lib']
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              spec.add_dependency('algorithms', '~> 0')
         | 
| 26 | 
            +
              spec.add_dependency('eventmachine', '~> 0')
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'citrus-scheduler/cron_trigger_decoder'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module CitrusScheduler
         | 
| 8 | 
            +
              # CronTrigger
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              #
         | 
| 11 | 
            +
              class CronTrigger
         | 
| 12 | 
            +
                # Create a new cron trigger
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # @param [String] args
         | 
| 15 | 
            +
                # @param [Object] job
         | 
| 16 | 
            +
                def initialize args='', job
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module CitrusScheduler
         | 
| 6 | 
            +
              # CronTrigger
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              #
         | 
| 9 | 
            +
              class CronTriggerDecoder
         | 
| 10 | 
            +
                # Create a new cron trigger decoder
         | 
| 11 | 
            +
                def initialize
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,66 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'citrus-scheduler/cron_trigger'
         | 
| 6 | 
            +
            require 'citrus-scheduler/simple_trigger'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module CitrusScheduler
         | 
| 9 | 
            +
              # Job
         | 
| 10 | 
            +
              #
         | 
| 11 | 
            +
              #
         | 
| 12 | 
            +
              class Job
         | 
| 13 | 
            +
                @job_id = 1
         | 
| 14 | 
            +
                @job_count = 0
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                class << self
         | 
| 17 | 
            +
                  attr_accessor :job_id, :job_count
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                attr_reader :job_id, :run_time
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # Create a new job
         | 
| 23 | 
            +
                #
         | 
| 24 | 
            +
                # @param [#call]        job_cb
         | 
| 25 | 
            +
                # @param [Hash]         job_cb_args
         | 
| 26 | 
            +
                # @param [Hash, String] trigger_args
         | 
| 27 | 
            +
                def initialize job_cb, job_cb_args={}, trigger_args={}
         | 
| 28 | 
            +
                  @job_cb = job_cb
         | 
| 29 | 
            +
                  @job_cb_args = job_cb_args
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  if trigger_args.instance_of? Hash
         | 
| 32 | 
            +
                    @type = :simple_job
         | 
| 33 | 
            +
                    @trigger = SimpleTrigger.new trigger_args, self
         | 
| 34 | 
            +
                  elsif trigger_args.instance_of? String
         | 
| 35 | 
            +
                    @type = :cron_job
         | 
| 36 | 
            +
                    @trigger = CronTrigger.new trigger_args, self
         | 
| 37 | 
            +
                  else
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  @job_id = Job.job_id
         | 
| 41 | 
            +
                  Job.job_id += 1
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  @run_time = 0
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                # Run the job
         | 
| 47 | 
            +
                def run
         | 
| 48 | 
            +
                  begin
         | 
| 49 | 
            +
                    Job.job_count += 1
         | 
| 50 | 
            +
                    @run_time += 1
         | 
| 51 | 
            +
                    @job_cb.call @job_cb_args
         | 
| 52 | 
            +
                  rescue => err
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Get the current execution time
         | 
| 57 | 
            +
                def execute_time
         | 
| 58 | 
            +
                  @trigger.execute_time
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                # Get the next execution time
         | 
| 62 | 
            +
                def next_execute_time
         | 
| 63 | 
            +
                  @trigger.next_execute_time
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
            end
         | 
| @@ -0,0 +1,114 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'algorithms'
         | 
| 6 | 
            +
            require 'citrus-scheduler/job'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module CitrusScheduler
         | 
| 9 | 
            +
              @jobs_map = {}
         | 
| 10 | 
            +
              @jobs_queue = Containers::PriorityQueue.new
         | 
| 11 | 
            +
              @timer = nil
         | 
| 12 | 
            +
              @accuracy = 0.01
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # Schedule a new job
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              # @param [#call] job_cb
         | 
| 17 | 
            +
              # @param [Hash]  job_cb_args
         | 
| 18 | 
            +
              # @param [Hash]  trigger_args
         | 
| 19 | 
            +
              def self.schedule_job job_cb, job_cb_args={}, trigger_args={}
         | 
| 20 | 
            +
                job = Job.new job_cb, job_cb_args, trigger_args
         | 
| 21 | 
            +
                job_id = job.job_id
         | 
| 22 | 
            +
                execute_time = job.execute_time
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                @jobs_map[job_id] = job
         | 
| 25 | 
            +
                element = {
         | 
| 26 | 
            +
                  :job_id => job_id,
         | 
| 27 | 
            +
                  :execute_time => execute_time
         | 
| 28 | 
            +
                }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                cur_job = @jobs_queue.next
         | 
| 31 | 
            +
                unless cur_job && execute_time >= cur_job[:execute_time]
         | 
| 32 | 
            +
                  @jobs_queue.push element, -execute_time
         | 
| 33 | 
            +
                  set_timer job
         | 
| 34 | 
            +
                  return job_id
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                @jobs_queue.push element, -execute_time
         | 
| 38 | 
            +
                return job_id
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              # Cancel a job
         | 
| 42 | 
            +
              #
         | 
| 43 | 
            +
              # @param [Integer] job_id
         | 
| 44 | 
            +
              def self.cancel_job job_id
         | 
| 45 | 
            +
                cur_job = @jobs_queue.next
         | 
| 46 | 
            +
                if cur_job && job_id == cur_job[:job_id]
         | 
| 47 | 
            +
                  @jobs_queue.pop
         | 
| 48 | 
            +
                  @jobs_map.delete job_id
         | 
| 49 | 
            +
                  @timer.cancel
         | 
| 50 | 
            +
                  execute_job
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
                @jobs_map.delete job_id
         | 
| 53 | 
            +
                true
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              # Clear last timeout and schedule the next job, it will automatically
         | 
| 57 | 
            +
              # run the job that need to run now
         | 
| 58 | 
            +
              #
         | 
| 59 | 
            +
              # @param [Object] job
         | 
| 60 | 
            +
              def self.set_timer job
         | 
| 61 | 
            +
                @timer.cancel if @timer
         | 
| 62 | 
            +
                @timer = EM::Timer.new(job.execute_time - Time.now.to_f) {
         | 
| 63 | 
            +
                  execute_job
         | 
| 64 | 
            +
                }
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              # Execute job
         | 
| 68 | 
            +
              def self.execute_job
         | 
| 69 | 
            +
                job = peek_next_job
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                while job && (job.execute_time - Time.now.to_f) < @accuracy
         | 
| 72 | 
            +
                  job.run
         | 
| 73 | 
            +
                  @jobs_queue.pop
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  next_time = job.next_execute_time
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  if next_time
         | 
| 78 | 
            +
                    element = {
         | 
| 79 | 
            +
                      :job_id => job.job_id,
         | 
| 80 | 
            +
                      :execute_time => next_time
         | 
| 81 | 
            +
                    }
         | 
| 82 | 
            +
                    @jobs_queue.push element, -next_time
         | 
| 83 | 
            +
                  else
         | 
| 84 | 
            +
                    @jobs_map.delete job.job_id
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                  job = peek_next_job
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                return unless job
         | 
| 90 | 
            +
                set_timer job
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              # Peek next job
         | 
| 94 | 
            +
              def self.peek_next_job
         | 
| 95 | 
            +
                return nil if @jobs_queue.size <= 0
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                job = nil
         | 
| 98 | 
            +
                loop do
         | 
| 99 | 
            +
                  job = @jobs_map[@jobs_queue.next[:job_id]]
         | 
| 100 | 
            +
                  @jobs_queue.pop unless job
         | 
| 101 | 
            +
                  break if job || @jobs_queue.size <= 0
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
                job
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
              # Get next job
         | 
| 107 | 
            +
              def self.get_next_job
         | 
| 108 | 
            +
                job = nil
         | 
| 109 | 
            +
                while !job && @jobs_queue.size > 0
         | 
| 110 | 
            +
                  job = @jobs_map[@jobs_queue.pop[:job_id]]
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
                job
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 15 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module CitrusScheduler
         | 
| 6 | 
            +
              # SimpleTrigger
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              #
         | 
| 9 | 
            +
              class SimpleTrigger
         | 
| 10 | 
            +
                # Create a new simple trigger
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                # @param [Hash] args Options
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # @option args [Integer] start_time
         | 
| 15 | 
            +
                # @option args [Integer] interval
         | 
| 16 | 
            +
                # @option args [Integer] count
         | 
| 17 | 
            +
                # @option args [Object]  job
         | 
| 18 | 
            +
                def initialize args={}, job
         | 
| 19 | 
            +
                  @next_time = args[:start_time] || Time.now.to_f
         | 
| 20 | 
            +
                  @interval = args[:interval] || -1
         | 
| 21 | 
            +
                  @count = args[:count] || -1
         | 
| 22 | 
            +
                  @job = job
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # Get the current execution time
         | 
| 26 | 
            +
                def execute_time
         | 
| 27 | 
            +
                  @next_time
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # Get the next execution time
         | 
| 31 | 
            +
                def next_execute_time
         | 
| 32 | 
            +
                  if (@count > 0 && @count <= @job.run_time) || @interval <= 0
         | 
| 33 | 
            +
                    return nil
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                  @next_time += @interval
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            # Author:: MinixLi (gmail: MinixLi1986)
         | 
| 2 | 
            +
            # Homepage:: http://citrus.inspawn.com
         | 
| 3 | 
            +
            # Date:: 16 July 2014
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require File.expand_path('../../lib/citrus-scheduler', __FILE__)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            def simple_job_cb args={}
         | 
| 8 | 
            +
              puts "simple job #{args[:id]} with interval: #{args[:interval]} executed at #{Time.now}"
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            def test_simple_job_schedule count
         | 
| 12 | 
            +
              count.times do |count|
         | 
| 13 | 
            +
                start_time = Time.now.to_f + rand * 10
         | 
| 14 | 
            +
                interval = rand * 60 + 0.1
         | 
| 15 | 
            +
                args = [
         | 
| 16 | 
            +
                  method(:simple_job_cb),
         | 
| 17 | 
            +
                  { :id => count, :interval => interval },
         | 
| 18 | 
            +
                  { :start_time => start_time, :interval => interval }
         | 
| 19 | 
            +
                ]
         | 
| 20 | 
            +
                CitrusScheduler.schedule_job *args
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            def test
         | 
| 25 | 
            +
              test_simple_job_schedule 5
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            EM.run { test }
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,85 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: pomelo-citrus-scheduler
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - MinixLi
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2014-09-26 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: algorithms
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: eventmachine
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0'
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0'
         | 
| 41 | 
            +
            description: pomelo-citrus-scheduler is a simple clone of pomelo-scheduler, it is
         | 
| 42 | 
            +
              a schedule tool and provide a schedule module which is highly efficient and can
         | 
| 43 | 
            +
              support large number job schedule
         | 
| 44 | 
            +
            email: MinixLi1986@gmail.com
         | 
| 45 | 
            +
            executables: []
         | 
| 46 | 
            +
            extensions: []
         | 
| 47 | 
            +
            extra_rdoc_files: []
         | 
| 48 | 
            +
            files:
         | 
| 49 | 
            +
            - README.md
         | 
| 50 | 
            +
            - Rakefile
         | 
| 51 | 
            +
            - citrus-scheduler.gemspec
         | 
| 52 | 
            +
            - lib/citrus-scheduler.rb
         | 
| 53 | 
            +
            - lib/citrus-scheduler/cron_trigger.rb
         | 
| 54 | 
            +
            - lib/citrus-scheduler/cron_trigger_decoder.rb
         | 
| 55 | 
            +
            - lib/citrus-scheduler/job.rb
         | 
| 56 | 
            +
            - lib/citrus-scheduler/schedule.rb
         | 
| 57 | 
            +
            - lib/citrus-scheduler/simple_trigger.rb
         | 
| 58 | 
            +
            - lib/citrus-scheduler/version.rb
         | 
| 59 | 
            +
            - test/test_schedule.rb
         | 
| 60 | 
            +
            homepage: https://github.com/minixli/pomelo-citrus-scheduler
         | 
| 61 | 
            +
            licenses:
         | 
| 62 | 
            +
            - MIT
         | 
| 63 | 
            +
            metadata: {}
         | 
| 64 | 
            +
            post_install_message: 
         | 
| 65 | 
            +
            rdoc_options: []
         | 
| 66 | 
            +
            require_paths:
         | 
| 67 | 
            +
            - lib
         | 
| 68 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 69 | 
            +
              requirements:
         | 
| 70 | 
            +
              - - ">="
         | 
| 71 | 
            +
                - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                  version: '0'
         | 
| 73 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 74 | 
            +
              requirements:
         | 
| 75 | 
            +
              - - ">="
         | 
| 76 | 
            +
                - !ruby/object:Gem::Version
         | 
| 77 | 
            +
                  version: '0'
         | 
| 78 | 
            +
            requirements: []
         | 
| 79 | 
            +
            rubyforge_project: 
         | 
| 80 | 
            +
            rubygems_version: 2.2.2
         | 
| 81 | 
            +
            signing_key: 
         | 
| 82 | 
            +
            specification_version: 4
         | 
| 83 | 
            +
            summary: pomelo-scheduler clone written in Ruby using EventMachine
         | 
| 84 | 
            +
            test_files:
         | 
| 85 | 
            +
            - test/test_schedule.rb
         |