lobster 0.1.0.alpha

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.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+ # gem "rails"
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lobster (0.1.0)
5
+ daemons (>= 1.1.4)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ daemons (1.1.4)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ lobster!
data/bin/lobster ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'lobster'
4
+ require 'daemons'
5
+
6
+ lobster_dir = File.expand_path(ENV['LOBSTER_DIR'] || '.')
7
+ log_dir = File.join(lobster_dir, 'log')
8
+
9
+ Dir.mkdir log_dir unless Dir.exist?(log_dir) || ARGV.first == "run"
10
+
11
+ #puts "LOBSTER_DIR set to #{lobster_dir}"
12
+
13
+ options = {
14
+ :multiple => false,
15
+ :monitor => true,
16
+ :backtrace => true,
17
+ :log_dir => File.join(lobster_dir, 'log'),
18
+ :log_output => true
19
+ }
20
+ options[:dir_mode] = :system unless ARGV.first == "run"
21
+ options[:log_dir] = File.join(lobster_dir, 'log')
22
+
23
+ Daemons.run_proc('lobster', options) do
24
+ Lobster::Service.start(lobster_dir)
25
+ end
@@ -0,0 +1,52 @@
1
+ module Lobster
2
+ class Job
3
+ attr_accessor :next_run
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ Lobster.logger.info "Job #{name} created."
8
+ @pid = nil
9
+ end
10
+
11
+ def reload(options)
12
+ options[:delay] ||= 10
13
+
14
+ if options[:command] != @command
15
+ Lobster.logger.info "Job command updated for #{@name}" if @command
16
+ @command = options.delete(:command)
17
+ end
18
+
19
+ if options[:delay] != @delay
20
+ Lobster.logger.info "Job delay updated for #{@name}" if @delay
21
+ @delay = options.delete(:delay)
22
+ @next_run = nil unless running?
23
+ end
24
+
25
+ @name ||= "<unnamed_job_#{command.hash.abs}>"
26
+ @next_run ||= Time.now + rand(@delay*60)
27
+ end
28
+
29
+ def running?
30
+ return false if @pid.nil?
31
+ if Process.wait @pid, Process::WNOHANG
32
+ Lobster.logger.error "Job #{@name} Failed with status #{$?}" unless $?.success?
33
+ @pid = nil
34
+ @next_run = Time.now + @delay*60
35
+ false
36
+ else
37
+ true
38
+ end
39
+ end
40
+
41
+ def run(out,err,dir)
42
+ Lobster.logger.info "starting job #{@name} from directory #{dir}"
43
+ begin
44
+ @pid = spawn(@command, :out=>out, :err=>err, :chdir=>dir)
45
+ Process.detach @pid
46
+ rescue Exception => e
47
+ Lobster.logger.error "#{e}: error when starting job #{@name}"
48
+ @next_run = Time.now + 10
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,55 @@
1
+ module Lobster
2
+ class JobList
3
+ attr_accessor :jobs
4
+
5
+ def initialize(file)
6
+ @file = file
7
+ #@options = {}
8
+ @current_options = nil
9
+ @jobs = {}
10
+ end
11
+
12
+ def reload
13
+ @new_jobs = {}
14
+ #@new_options = {}
15
+
16
+ instance_eval(File.read(@file),@file)
17
+
18
+ # purely for logging
19
+ @jobs.each do |name, job|
20
+ Lobster.logger.info "Job #{name} deleted." unless @new_jobs[name]
21
+ end
22
+ #@options.each do |key, value|
23
+ # Lobster.logger.info "#{key} unset." unless @new_options[key]
24
+ #end
25
+
26
+ @jobs = @new_jobs
27
+ #@options = @new_options
28
+ end
29
+
30
+ def job(name)
31
+ @current_options = {}
32
+ yield
33
+ @new_jobs[name] ||= @jobs[name] || Job.new(name)
34
+ @new_jobs[name].reload(@current_options)
35
+ @current_options = nil
36
+ end
37
+
38
+ def cmd(command)
39
+ @current_options[:command] = command
40
+ end
41
+
42
+ def delay(delay)
43
+ @current_options[:delay] = delay
44
+ end
45
+
46
+ # def set(option, value)
47
+ # Lobster.logger.info "set #{option}=#{value}" if value != @options[option]
48
+ # @new_options[option] = value
49
+ # end
50
+ #
51
+ # def get(option)
52
+ # @options[option]
53
+ # end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ require 'logger'
2
+
3
+ module Lobster
4
+ class Service
5
+ def self.start(dir)
6
+ Lobster.logger = Logger.new(STDOUT)
7
+ new(dir).run
8
+ end
9
+
10
+ def initialize(dir)
11
+ @job_list = nil
12
+ @directory = dir || '.'
13
+ @file = File.join(@directory, 'config', 'schedule.rb')
14
+ @poll_delay = 60
15
+
16
+ rout, @wout = IO.pipe
17
+ rerr, @werr = IO.pipe
18
+
19
+ Thread.new do
20
+ while (line = rout.gets)
21
+ Lobster.logger.info "out: #{line}"
22
+ end
23
+ end
24
+
25
+ Thread.new do
26
+ while (line = rerr.gets)
27
+ Lobster.logger.error "err: #{line}"
28
+ end
29
+ end
30
+
31
+ Signal.trap "INT" do
32
+ Lobster.logger.info "All jobs are getting killed."
33
+ exit 0
34
+ end
35
+ end
36
+
37
+ def run
38
+ Lobster.logger.info "Lobster started."
39
+ Lobster.logger.info "Schedule file: #{@file}"
40
+ Lobster.logger.info "Poll delay: #{@poll_delay}"
41
+
42
+ loop do
43
+ now = Time.now
44
+
45
+ reload_config
46
+
47
+ @job_list.jobs.each_value do |job|
48
+ if not job.running? and now >= job.next_run
49
+ job.run(@wout, @werr, @directory)
50
+ end
51
+ end
52
+ sleep @poll_delay
53
+ end
54
+ end
55
+
56
+ def reload_config
57
+ @job_list ||= JobList.new(@file)
58
+ begin
59
+ @job_list.reload
60
+ rescue Exception => e
61
+ Lobster.logger.error "#{e}: error while reading config file in #{@file}, not updating"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ module Lobster
2
+ VERSION = '0.1.0.alpha'
3
+ end
data/lib/lobster.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Lobster
2
+ autoload :JobList, 'lobster/job_list'
3
+ autoload :Job, 'lobster/job'
4
+ autoload :Service, 'lobster/service'
5
+
6
+ class << self
7
+ attr_accessor :logger
8
+ end
9
+ end
data/lobster.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lobster/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "lobster"
7
+ s.version = Lobster::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Maxime Brugidou"]
10
+ s.email = ["m.brugidou@criteo.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Simple loop job runner service.}
13
+ s.description = %q{}
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- test/{functional,unit}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency "daemons", ">= 1.1.4"
20
+
21
+ #s.add_development_dependency "shoulda", ">= 2.1.1"
22
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lobster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.alpha
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Maxime Brugidou
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: daemons
16
+ requirement: &76767520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *76767520
25
+ description: ''
26
+ email:
27
+ - m.brugidou@criteo.com
28
+ executables:
29
+ - lobster
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - Gemfile
34
+ - Gemfile.lock
35
+ - bin/lobster
36
+ - lib/lobster.rb
37
+ - lib/lobster/job.rb
38
+ - lib/lobster/job_list.rb
39
+ - lib/lobster/service.rb
40
+ - lib/lobster/version.rb
41
+ - lobster.gemspec
42
+ homepage: ''
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>'
58
+ - !ruby/object:Gem::Version
59
+ version: 1.3.1
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 1.8.11
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Simple loop job runner service.
66
+ test_files: []