khronos 0.0.0 → 0.0.1.pre1
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/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +18 -7
- data/Rakefile +36 -0
- data/bin/khronos +2 -1
- data/config.ru +9 -1
- data/config/environment.yml +27 -5
- data/{lib/khronos/storage/adapter/mongo/.schedule_log.rb.un~ → db/test.db} +0 -0
- data/khronos.gemspec +10 -7
- data/lib/khronos.rb +4 -7
- data/lib/khronos/config.rb +0 -2
- data/lib/khronos/logger.rb +16 -0
- data/lib/khronos/scheduler.rb +17 -3
- data/lib/khronos/server.rb +4 -31
- data/lib/khronos/server/controller.rb +31 -0
- data/lib/khronos/server/runner.rb +50 -0
- data/lib/khronos/server/scheduler.rb +110 -0
- data/lib/khronos/storage.rb +34 -13
- data/lib/khronos/storage/adapter.rb +44 -0
- data/lib/khronos/storage/adapter/activerecord.rb +39 -0
- data/lib/khronos/storage/adapter/activerecord/migrations/schedule.rb +29 -0
- data/lib/khronos/storage/adapter/activerecord/migrations/schedule_log.rb +23 -0
- data/lib/khronos/storage/adapter/activerecord/schedule.rb +24 -0
- data/lib/khronos/storage/adapter/activerecord/schedule_log.rb +14 -0
- data/lib/khronos/storage/adapter/mongoid.rb +37 -0
- data/lib/khronos/storage/adapter/{mongo → mongoid}/schedule.rb +6 -4
- data/lib/khronos/storage/adapter/{mongo → mongoid}/schedule_log.rb +3 -4
- data/lib/khronos/tasks/db.rake +25 -0
- data/lib/khronos/version.rb +1 -1
- data/server.rb +29 -0
- data/spec/functional/adapters_spec.rb +61 -0
- data/spec/functional/controller_spec.rb +11 -0
- data/spec/functional/scheduler_spec.rb +30 -0
- data/spec/integration/runner_server_spec.rb +26 -0
- data/spec/integration/scheduler_server_spec.rb +70 -0
- data/spec/spec_helper.rb +17 -1
- data/spec/support/factories.rb +12 -0
- data/spec/support/mocks.rb +23 -0
- data/{lib/khronos/storage/adapter/postgres/.schedule.rb.un~ → spec/tmp/scheduler.db} +0 -0
- data/{lib/khronos/.version.rb.swp → spec/tmp/sqlite3.db} +0 -0
- metadata +92 -55
- data/config/.config.yml.un~ +0 -0
- data/config/.environment.yml.un~ +0 -0
- data/config/.redis.yml.un~ +0 -0
- data/config/.storage.yml.un~ +0 -0
- data/lib/.khronos.rb.un~ +0 -0
- data/lib/.scheduler.rb.un~ +0 -0
- data/lib/khronos/.config.rb.un~ +0 -0
- data/lib/khronos/.controller.rb.un~ +0 -0
- data/lib/khronos/.runner.rb.un~ +0 -0
- data/lib/khronos/.schedule.rb.un~ +0 -0
- data/lib/khronos/.scheduler.rb.un~ +0 -0
- data/lib/khronos/.server.rb.un~ +0 -0
- data/lib/khronos/.storage.rb.un~ +0 -0
- data/lib/khronos/.task.rb.un~ +0 -0
- data/lib/khronos/.version.rb.un~ +0 -0
- data/lib/khronos/controller.rb +0 -26
- data/lib/khronos/runner.rb +0 -11
- data/lib/khronos/storage/adapter/.client.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/.memcached.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/.mongo.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/.mongodb.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/.postgres.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/.redis.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/mongo.rb +0 -13
- data/lib/khronos/storage/adapter/mongo/.mongo.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/mongo/.schedule.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/postgres.rb +0 -15
- data/lib/khronos/storage/adapter/postgres/.schedule_log.rb.un~ +0 -0
- data/lib/khronos/storage/adapter/postgres/schedule.rb +0 -13
- data/lib/khronos/storage/adapter/postgres/schedule_log.rb +0 -13
- data/lib/khronos/storage/db/migrate/.schedule.rb.un~ +0 -0
- data/lib/khronos/storage/db/migrate/.schedule_log.rb.un~ +0 -0
- data/lib/khronos/storage/db/migrate/schedule.rb +0 -15
- data/lib/khronos/storage/db/migrate/schedule_log.rb +0 -16
- data/spec/.spec_helper.rb.un~ +0 -0
- data/spec/functional/.client_spec.rb.un~ +0 -0
- data/spec/functional/client_spec.rb +0 -24
- data/spec/integration/.server_spec.rb.un~ +0 -0
- data/spec/integration/server_spec.rb +0 -31
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
deploy
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -2,17 +2,28 @@ source :rubygems
|
|
2
2
|
gemspec
|
3
3
|
|
4
4
|
group :test do
|
5
|
-
|
6
|
-
gem 'activesupport', "~> 3.2.8"
|
7
|
-
|
5
|
+
gem 'thin'
|
8
6
|
gem 'simplecov', '= 0.6.4'
|
9
7
|
|
10
|
-
|
11
|
-
gem
|
8
|
+
# Testing
|
9
|
+
gem "rspec", "~> 2.11.0"
|
10
|
+
gem 'rack-test', '~> 0.6.1'
|
12
11
|
gem "fakefs", "~> 0.4.0"
|
13
12
|
gem "delorean", "~> 2.0.0"
|
13
|
+
gem "factory_girl", "~> 4.0.0"
|
14
|
+
gem "webmock", "~> 1.8.9"
|
15
|
+
#gem "em-spec", ''
|
16
|
+
|
17
|
+
#
|
18
|
+
# Used for time functions
|
19
|
+
#
|
20
|
+
gem 'activesupport', "~> 3.2.8"
|
14
21
|
|
15
|
-
|
16
|
-
|
22
|
+
#
|
23
|
+
# Database support testing
|
24
|
+
#
|
17
25
|
gem 'mongo'
|
26
|
+
gem "mysql2", "~> 0.3.11"
|
27
|
+
gem 'sqlite3'
|
28
|
+
gem 'pg'
|
18
29
|
end
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$: << 'lib'
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
ENV['RACK_ENV'] = ENV['ENV'] || 'test'
|
6
|
+
require 'khronos'
|
7
|
+
|
8
|
+
def load_migrations!
|
9
|
+
require 'khronos/storage/adapter/activerecord/migrations/schedule'
|
10
|
+
require 'khronos/storage/adapter/activerecord/migrations/schedule_log'
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :db do
|
14
|
+
|
15
|
+
desc 'Create the database.'
|
16
|
+
task :create do
|
17
|
+
adapter = Khronos::Storage::Adapter.get(ENV['KHRONOS_STORAGE'])
|
18
|
+
if adapter.name =~ /ActiveRecord/
|
19
|
+
load_migrations!
|
20
|
+
CreateSchedule.up
|
21
|
+
CreateScheduleLog.up
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Destroy entire database.'
|
26
|
+
task :drop do
|
27
|
+
adapter = Khronos::Storage::Adapter.get(ENV['KHRONOS_STORAGE'])
|
28
|
+
if adapter.name =~ /ActiveRecord/
|
29
|
+
load_migrations!
|
30
|
+
CreateSchedule.down
|
31
|
+
CreateScheduleLog.down
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
data/bin/khronos
CHANGED
data/config.ru
CHANGED
@@ -4,4 +4,12 @@ require 'bundler/setup'
|
|
4
4
|
require 'active_support/all'
|
5
5
|
require 'khronos'
|
6
6
|
|
7
|
-
|
7
|
+
#controller = Khronos::Controller.new
|
8
|
+
#controller.start!
|
9
|
+
|
10
|
+
run Khronos::Server::Scheduler
|
11
|
+
|
12
|
+
# Note that this will block current thread.
|
13
|
+
#EventMachine.run {
|
14
|
+
#EventMachine.start_server "127.0.0.1", 8081, Khronos::Server::Runner
|
15
|
+
#}
|
data/config/environment.yml
CHANGED
@@ -1,11 +1,33 @@
|
|
1
1
|
production:
|
2
|
-
storage:
|
2
|
+
storage: mongodb://localhost:27017/khronos
|
3
3
|
interval: 5
|
4
|
+
controller:
|
5
|
+
interval: 1
|
6
|
+
runner:
|
7
|
+
host: 'localhost'
|
8
|
+
port: '7243'
|
9
|
+
scheduler:
|
10
|
+
host: 'localhost'
|
11
|
+
port: '8080'
|
4
12
|
|
5
13
|
development:
|
6
|
-
storage:
|
7
|
-
|
14
|
+
storage: mongodb://localhost:27017/khronos_development
|
15
|
+
controller:
|
16
|
+
interval: 1
|
17
|
+
runner:
|
18
|
+
host: 'localhost'
|
19
|
+
port: '7243'
|
20
|
+
scheduler:
|
21
|
+
host: 'localhost'
|
22
|
+
port: '8080'
|
8
23
|
|
9
24
|
test:
|
10
|
-
storage:
|
11
|
-
|
25
|
+
storage: sqlite3://localhost/db/test.db
|
26
|
+
controller:
|
27
|
+
interval: 1
|
28
|
+
runner:
|
29
|
+
host: 'localhost'
|
30
|
+
port: '7243'
|
31
|
+
scheduler:
|
32
|
+
host: 'localhost'
|
33
|
+
port: '8080'
|
Binary file
|
data/khronos.gemspec
CHANGED
@@ -8,17 +8,20 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Endel Dreyer"]
|
10
10
|
s.email = ["endel@ocapi.com.br"]
|
11
|
-
s.homepage = "http://github.com/ocapi/
|
11
|
+
s.homepage = "http://github.com/ocapi/khronos"
|
12
12
|
|
13
13
|
s.summary = "Ruby HTTP Job Scheduler Interface."
|
14
|
-
s.description = "
|
14
|
+
s.description = "Ruby HTTP Job Scheduler Interface. An advanced Cron replacement for the cloud."
|
15
15
|
s.licenses = ['MIT']
|
16
16
|
|
17
|
-
s.add_dependency "sinatra",
|
18
|
-
s.add_dependency
|
19
|
-
s.add_dependency
|
20
|
-
s.add_dependency
|
21
|
-
s.add_dependency
|
17
|
+
s.add_dependency "sinatra", "~> 1.3.3"
|
18
|
+
s.add_dependency "mongoid", "~> 3.0.5"
|
19
|
+
s.add_dependency "bson_ext", "~> 1.6.4"
|
20
|
+
s.add_dependency "activerecord", "~> 3.2.8"
|
21
|
+
s.add_dependency "json", "~> 1.7.5"
|
22
|
+
s.add_dependency "activesupport", "~> 3.2.8"
|
23
|
+
s.add_dependency "eventmachine", "~> 1.0.0.beta.4"
|
24
|
+
s.add_dependency "em-http-request", "~> 1.0.3"
|
22
25
|
|
23
26
|
s.files = `git ls-files`.split("\n")
|
24
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/khronos.rb
CHANGED
@@ -2,19 +2,16 @@ require 'rubygems'
|
|
2
2
|
require 'bundler'
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'json'
|
5
|
+
require 'logger'
|
5
6
|
|
6
7
|
module Khronos
|
7
8
|
autoload :Config, 'khronos/config'
|
9
|
+
autoload :Logger, 'khronos/logger'
|
10
|
+
autoload :Scheduler, 'khronos/scheduler'
|
8
11
|
|
9
12
|
autoload :Storage, 'khronos/storage'
|
10
13
|
autoload :Server, 'khronos/server'
|
11
|
-
|
12
|
-
autoload :Scheduler, 'khronos/scheduler'
|
13
|
-
autoload :Runner, 'khronos/runner'
|
14
|
-
autoload :Controller, 'khronos/controller'
|
15
14
|
end
|
16
15
|
|
16
|
+
Khronos::Logger.setup!(Logger.new(STDOUT))
|
17
17
|
Khronos::Config.instance.load!('config/environment.yml', ENV['RACK_ENV'])
|
18
|
-
|
19
|
-
controller = Khronos::Controller.new
|
20
|
-
controller.start!
|
data/lib/khronos/config.rb
CHANGED
data/lib/khronos/scheduler.rb
CHANGED
@@ -1,12 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Khronos
|
4
5
|
class Scheduler
|
5
|
-
|
6
|
+
module Methods
|
7
|
+
def run(schedule)
|
8
|
+
client = TCPSocket.new( Config.instance.runner['host'], Config.instance.runner['port'] )
|
9
|
+
client.puts( schedule.to_json )
|
6
10
|
|
7
|
-
|
11
|
+
while !(client.closed?) && (message = client.gets)
|
12
|
+
puts message.inspect
|
13
|
+
client.close
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(target_time=Time.now)
|
18
|
+
Storage::Schedule.where(['at <= ?', target_time]).where(:active => true)
|
19
|
+
end
|
8
20
|
end
|
9
21
|
|
22
|
+
include Methods
|
23
|
+
extend Methods
|
10
24
|
end
|
11
25
|
end
|
12
26
|
|
data/lib/khronos/server.rb
CHANGED
@@ -1,34 +1,7 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
|
3
1
|
module Khronos
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# @return [Hash] JSON
|
10
|
-
get '/' do
|
11
|
-
context = retrieve_context!
|
12
|
-
settings.storage.get(context).to_json
|
13
|
-
end
|
14
|
-
|
15
|
-
# Creates or updates a schedule from a context
|
16
|
-
#
|
17
|
-
# @param [String]
|
18
|
-
#
|
19
|
-
# @return [Hash] Context JSON status hash
|
20
|
-
put '/' do
|
21
|
-
context = retrieve_context!
|
22
|
-
puts params.inspect
|
23
|
-
context.to_json
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def retrieve_context!
|
29
|
-
halt 400, "Missing 'context' on query string." unless params[:context]
|
30
|
-
(params[:namespace].nil?) ? params[:context] : "#{params[:namespace]}:#{params[:context]}"
|
31
|
-
end
|
32
|
-
|
2
|
+
module Server
|
3
|
+
autoload :Runner, 'khronos/server/runner'
|
4
|
+
autoload :Scheduler, 'khronos/server/scheduler'
|
5
|
+
autoload :Controller, 'khronos/server/controller'
|
33
6
|
end
|
34
7
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Khronos
|
2
|
+
module Server
|
3
|
+
class Controller
|
4
|
+
attr_reader :storage, :scheduler
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@storage = Storage.new
|
8
|
+
@scheduler = Scheduler.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def logger=(logger)
|
12
|
+
puts "WARNING: Not implemented yet."
|
13
|
+
end
|
14
|
+
|
15
|
+
def start!
|
16
|
+
loop do
|
17
|
+
@scheduler.fetch(Time.now).each do |schedule|
|
18
|
+
schedule.update_attributes(:status => false)
|
19
|
+
schedule.save
|
20
|
+
@scheduler.run(schedule)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Sleep 'interval' seconds
|
25
|
+
#
|
26
|
+
sleep(Config.instance.controller['interval'])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'em-http'
|
4
|
+
|
5
|
+
module Khronos
|
6
|
+
module Server
|
7
|
+
|
8
|
+
class Runner < EventMachine::Connection
|
9
|
+
def post_init
|
10
|
+
puts "-- someone connected to the server!"
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive_data json
|
14
|
+
schedule = JSON.parse(json)
|
15
|
+
send_data ">>> you sent: #{schedule.inspect}"
|
16
|
+
|
17
|
+
# Close connection with client immediatelly
|
18
|
+
close_connection
|
19
|
+
|
20
|
+
if (url = schedule['task_url'])
|
21
|
+
http = EventMachine::HttpRequest.new(url).get :redirects => 5
|
22
|
+
http.callback do
|
23
|
+
puts "#{url}\n#{http.response_header.status} - #{http.response.length} bytes\n"
|
24
|
+
puts http.response
|
25
|
+
end
|
26
|
+
|
27
|
+
http.errback do
|
28
|
+
puts "#{url}\n" + http.error
|
29
|
+
end
|
30
|
+
|
31
|
+
enqueue_recurrency!(schedule)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def enqueue_recurrency!(schedule)
|
37
|
+
url = "http://#{Config.instance.scheduler['host']}"
|
38
|
+
url += ":#{Config.instance.scheduler['port']}" if Config.instance.scheduler['port']
|
39
|
+
url += "/task?id=#{schedule['id']}"
|
40
|
+
EventMachine::HttpRequest.new(url).patch :redirects => 2
|
41
|
+
end
|
42
|
+
|
43
|
+
def unbind
|
44
|
+
puts "-- someone disconnected from the echo server!"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
|
3
|
+
module Khronos
|
4
|
+
module Server
|
5
|
+
|
6
|
+
class Scheduler < Sinatra::Base
|
7
|
+
set :storage, Storage.new
|
8
|
+
|
9
|
+
# Creates a schedule
|
10
|
+
#
|
11
|
+
# @param [String] context application-level identifier
|
12
|
+
# @param [Integer] at timestamp which will run for the first time
|
13
|
+
# @param [Integer] recurrency next execution interval, in seconds
|
14
|
+
# @param [String] task_url url of the task that will run
|
15
|
+
# @param [String, JSON] callbacks callback urls (e.g. '{"success" : ... , "error" : ...}')
|
16
|
+
#
|
17
|
+
# @return [Hash] created schedule data
|
18
|
+
post '/task' do
|
19
|
+
Storage::Schedule.create(params).to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
# Retrieves scheduling tasks from a context
|
23
|
+
#
|
24
|
+
# @param [Integer] id
|
25
|
+
# @param [String] context
|
26
|
+
#
|
27
|
+
# @return [Hash] JSON
|
28
|
+
get '/task' do
|
29
|
+
schedule = (!params.empty?) ? Storage::Schedule.where(params).first : nil
|
30
|
+
if schedule.nil?
|
31
|
+
# Requested task not found
|
32
|
+
404
|
33
|
+
else
|
34
|
+
schedule.to_json
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Retrieve a list of scheduling tasks
|
39
|
+
get '/tasks' do
|
40
|
+
if Storage::Schedule.name =~ /ActiveRecord/
|
41
|
+
criteria = Storage::Schedule
|
42
|
+
params.each_pair do |field, value|
|
43
|
+
if field == 'context'
|
44
|
+
field = "#{field} LIKE ?"
|
45
|
+
else
|
46
|
+
field = "#{field} = ?"
|
47
|
+
end
|
48
|
+
criteria = criteria.where(field, value)
|
49
|
+
end
|
50
|
+
criteria.to_json
|
51
|
+
else
|
52
|
+
Storage::Schedule.where(params).to_json
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates or updates a schedule from a context
|
57
|
+
#
|
58
|
+
# @param [String]
|
59
|
+
#
|
60
|
+
# @return [Hash] Context JSON status hash
|
61
|
+
put '/task' do
|
62
|
+
schedule = Storage::Schedule.where({:id => params.delete(:id)}).first
|
63
|
+
|
64
|
+
# No schedule found for this params.
|
65
|
+
return {}.to_json unless schedule
|
66
|
+
|
67
|
+
schedule.update_attributes(params)
|
68
|
+
schedule.save
|
69
|
+
|
70
|
+
schedule.to_json
|
71
|
+
end
|
72
|
+
|
73
|
+
# Checks recurrency and reactivates a schedule if necessary
|
74
|
+
#
|
75
|
+
# @param [String] id
|
76
|
+
#
|
77
|
+
# @return [Hash] data
|
78
|
+
patch '/task' do
|
79
|
+
schedule = Storage::Schedule.where(params).first
|
80
|
+
|
81
|
+
# No schedule found for this params.
|
82
|
+
return {}.to_json unless schedule
|
83
|
+
|
84
|
+
# Is recurrency check requested
|
85
|
+
if schedule.recurrency > 0
|
86
|
+
schedule.at += schedule.recurrency
|
87
|
+
schedule.active = true
|
88
|
+
end
|
89
|
+
schedule.save
|
90
|
+
|
91
|
+
schedule.to_json
|
92
|
+
end
|
93
|
+
|
94
|
+
# Force a task to be scheduled right now
|
95
|
+
#
|
96
|
+
# @param [Integer] id
|
97
|
+
#
|
98
|
+
# @return [Hash] queued
|
99
|
+
post '/task/run' do
|
100
|
+
schedule = Storage::Schedule.where(:id => params[:id]).first
|
101
|
+
Khronos::Scheduler.run(schedule) if schedule
|
102
|
+
{:queued => !schedule.nil?}.to_json
|
103
|
+
end
|
104
|
+
|
105
|
+
# Log requests
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|