desmond 0.5.4
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/bin/desmond +28 -0
- data/lib/desmond.rb +185 -0
- data/lib/desmond/capistrano.rb +42 -0
- data/lib/desmond/rake.rb +84 -0
- metadata +226 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cc12e128251786d7865236f627e20573ad622606
|
4
|
+
data.tar.gz: b65335f02f5d8332fab20b96cf93f0574444525e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c45fc27e36157d1c9ab3b26a143276f78fcae7e20611aa40da0cc43bf186faf8a9d1b20a63a2bdeba28b583c06fcb48c07be0140b576526dc49b969b32c409b
|
7
|
+
data.tar.gz: b8a68ef6e23f7b3294e1a8b7a20649a1d2d5f81008b69e39e0efcc371a99e029baf5de664a36b894a77b7940d646f64422ca1b5ce84377f3411bcfe8da4d309c
|
data/bin/desmond
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'daemons'
|
5
|
+
require_relative '../lib/desmond'
|
6
|
+
|
7
|
+
#
|
8
|
+
# script to run the desmond workers in background processes
|
9
|
+
# easily manageable using start/stop/restart commands
|
10
|
+
#
|
11
|
+
|
12
|
+
# set_daemon really early, so it true as early as possible
|
13
|
+
DesmondConfig.send :set_daemon
|
14
|
+
current_dir = Dir.pwd
|
15
|
+
options = { backtrace: true, log_dir: File.join(current_dir, 'log/') }
|
16
|
+
options = options.merge(dir_mode: :normal, dir: ARGV[1]) if ARGV.size > 1
|
17
|
+
Daemons.run_proc("desmond_for_#{DesmondConfig.app_id}", options) do
|
18
|
+
begin
|
19
|
+
Dir.chdir(current_dir)
|
20
|
+
Rake.application.init
|
21
|
+
Rake.application.load_rakefile
|
22
|
+
Rake::Task['desmond:run'].invoke
|
23
|
+
rescue Exception => e
|
24
|
+
DesmondConfig.logger.error "Fatal error in desmond process: #{e.message}"
|
25
|
+
DesmondConfig.logger.error e.backtrace.join("\n\t")
|
26
|
+
raise
|
27
|
+
end
|
28
|
+
end
|
data/lib/desmond.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'que'
|
2
|
+
require 'active_record'
|
3
|
+
require 'yaml'
|
4
|
+
require 'aws-sdk'
|
5
|
+
require 'active_support/hash_with_indifferent_access'
|
6
|
+
|
7
|
+
require_relative 'desmond/monkey_patches'
|
8
|
+
require_relative 'desmond/utils/pg_util'
|
9
|
+
require_relative 'desmond/utils/s3_util'
|
10
|
+
require_relative 'desmond/utils/log_censor'
|
11
|
+
|
12
|
+
require_relative 'desmond/execution_error'
|
13
|
+
|
14
|
+
require_relative 'desmond/streams/base'
|
15
|
+
require_relative 'desmond/streams/csv'
|
16
|
+
require_relative 'desmond/streams/database'
|
17
|
+
require_relative 'desmond/streams/s3'
|
18
|
+
|
19
|
+
require_relative 'desmond/job_run_finders'
|
20
|
+
require_relative 'desmond/jobs/base'
|
21
|
+
require_relative 'desmond/jobs/base_no_job_id'
|
22
|
+
require_relative 'desmond/jobs/pg_export'
|
23
|
+
require_relative 'desmond/jobs/export'
|
24
|
+
require_relative 'desmond/jobs/import'
|
25
|
+
require_relative 'desmond/jobs/unload'
|
26
|
+
require_relative 'desmond/jobs/sequential'
|
27
|
+
|
28
|
+
require_relative 'desmond/models/job_run'
|
29
|
+
|
30
|
+
##
|
31
|
+
# manages the gem's configuration
|
32
|
+
#
|
33
|
+
class DesmondConfig
|
34
|
+
@is_daemon = false
|
35
|
+
@logger = Logger.new(STDOUT)
|
36
|
+
@exception_notifier = []
|
37
|
+
class << self
|
38
|
+
attr_accessor :logger
|
39
|
+
attr_reader :is_daemon
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# determins the environment we are running in:
|
44
|
+
# - development
|
45
|
+
# - staging
|
46
|
+
# - production
|
47
|
+
#
|
48
|
+
def self.environment
|
49
|
+
(ENV['RACK_ENV'] || 'development').to_sym
|
50
|
+
end
|
51
|
+
##
|
52
|
+
# set where the desmond configuration file is located
|
53
|
+
# and reload the configration
|
54
|
+
#
|
55
|
+
def self.config_file=(file)
|
56
|
+
@config = load_config_file(file)
|
57
|
+
end
|
58
|
+
##
|
59
|
+
# retrieve the desmond configuration
|
60
|
+
#
|
61
|
+
def self.config
|
62
|
+
self.config_file = 'config/desmond.yml' if @config.nil?
|
63
|
+
@config
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# retrieves the app_id from the config, defaults to 'desmond'
|
68
|
+
#
|
69
|
+
def self.app_id
|
70
|
+
config['app_id'] || 'desmond'
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# adds the given argument to the list of block to be called when
|
75
|
+
# an uncaught exception occurs during job execution
|
76
|
+
#
|
77
|
+
# blocks will be called with the arguments (exception, job_class, job_run)
|
78
|
+
#
|
79
|
+
def self.add_exception_notifier(&block)
|
80
|
+
@exception_notifier << block
|
81
|
+
end
|
82
|
+
def self.clear_exception_notifier
|
83
|
+
@exception_notifier = []
|
84
|
+
end
|
85
|
+
def self.register_with_exception_notifier(options={})
|
86
|
+
options.each do |notifier_name, options|
|
87
|
+
ExceptionNotifier.register_exception_notifier(notifier_name, options)
|
88
|
+
end
|
89
|
+
DesmondConfig.add_exception_notifier do |exception, job_class, job_run|
|
90
|
+
ExceptionNotifier.notify_exception(exception, :data => { :class => job_class, run: job_run })
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# change 'app_id' to +value+
|
96
|
+
# only use this in the 'test' environment otherwise the change
|
97
|
+
# will not be shared with the worker processes, use the desmond.yml
|
98
|
+
# configuration file instead
|
99
|
+
#
|
100
|
+
def self.app_id=(value)
|
101
|
+
fail 'Do not use this DesmondConfig.app_id= outside of "test"' if self.environment != :test
|
102
|
+
config['app_id'] = value
|
103
|
+
end
|
104
|
+
##
|
105
|
+
# retrieve the location of the ActiveRecord database configuration file.
|
106
|
+
# should really only be used when developing desmond, otherwise the using app
|
107
|
+
# should establish the ActiveRecord connections
|
108
|
+
#
|
109
|
+
def self.database
|
110
|
+
load_config_file(config['database'] || 'config/database.yml')
|
111
|
+
end
|
112
|
+
##
|
113
|
+
# determines whether the tasks are allowed to use the configured
|
114
|
+
# connection instead of using the users credentials
|
115
|
+
#
|
116
|
+
def self.system_connection_allowed?
|
117
|
+
config['system_connection_allowed'] || false
|
118
|
+
end
|
119
|
+
##
|
120
|
+
# change 'system_connection_allowed' to +value+
|
121
|
+
# only use this in the 'test' environment otherwise the change
|
122
|
+
# will not be shared with the worker processes, use the desmond.yml
|
123
|
+
# configuration file instead
|
124
|
+
#
|
125
|
+
def self.system_connection_allowed=(value)
|
126
|
+
fail 'Do not use this DesmondConfig.system_connection_allowed= outside of "test"' if self.environment != :test
|
127
|
+
config['system_connection_allowed'] = value
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.load_config_file(file)
|
131
|
+
return {} unless File.exist?(file)
|
132
|
+
ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(file))
|
133
|
+
end
|
134
|
+
private_class_method :load_config_file
|
135
|
+
|
136
|
+
def self.set_daemon
|
137
|
+
@is_daemon = true
|
138
|
+
end
|
139
|
+
private_class_method :set_daemon
|
140
|
+
|
141
|
+
def self.exception_notification(exception, job_class, job_run)
|
142
|
+
@exception_notifier.each do |thing|
|
143
|
+
thing.call(exception, job_class, job_run) rescue nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
private_class_method :exception_notification
|
147
|
+
end
|
148
|
+
|
149
|
+
# configure ActiveRecord, but the app using us should really do this,
|
150
|
+
# mostly included for development purposes on desmond itself
|
151
|
+
if ActiveRecord::Base.configurations.empty?
|
152
|
+
ActiveRecord::Base.configurations = DesmondConfig.database
|
153
|
+
ActiveRecord::Base.establish_connection DesmondConfig.environment
|
154
|
+
end
|
155
|
+
|
156
|
+
# configure que
|
157
|
+
Que.connection = ActiveRecord
|
158
|
+
ActiveRecord::Base.schema_format = :sql # otherwise the que_jobs table gets missed
|
159
|
+
Que.mode = :sync if DesmondConfig.environment == :test
|
160
|
+
Que.mode = :off if DesmondConfig.environment != :test
|
161
|
+
|
162
|
+
# configure log censoring, so that password and AWS secret keys don't end up in the logs
|
163
|
+
CENSORED_KEYS = %w(password secret_access_key)
|
164
|
+
Que.log_formatter = proc do |data|
|
165
|
+
tmp = ActiveSupport::HashWithIndifferentAccess.new(data)
|
166
|
+
if tmp.include?(:job) && !tmp[:job].nil?
|
167
|
+
tmp[:job][:args] = tmp[:job][:args].map do |arg|
|
168
|
+
censor_hash_keys(arg, CENSORED_KEYS) if arg.is_a?(Hash)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
tmp.to_json
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# overwriting the get logger method of Que, to always return
|
176
|
+
# Desmond's configured logger. Que tends to overwrite the logger
|
177
|
+
# in background situations, which we'll ignore by this.
|
178
|
+
#
|
179
|
+
module Que
|
180
|
+
class << self
|
181
|
+
def logger
|
182
|
+
DesmondConfig.logger
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
namespace :desmond do
|
2
|
+
def pid_dir
|
3
|
+
fetch(:pid_dir, "#{fetch(:release_path)}/tmp/pids")
|
4
|
+
end
|
5
|
+
|
6
|
+
def cmd(cmd)
|
7
|
+
"cd #{current_path};#{env} #{workers} #{que_command} #{cmd} #{pid_dir}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Stop the desmond process'
|
11
|
+
task :stop do
|
12
|
+
on roles(:app) do
|
13
|
+
within release_path do
|
14
|
+
with rack_env: fetch(:rack_env), que_worker_count: fetch(:que_num_workers, 1) do
|
15
|
+
execute :bundle, :exec, :desmond, 'stop', pid_dir
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Start the desmond process'
|
22
|
+
task :start do
|
23
|
+
on roles(:app) do
|
24
|
+
within release_path do
|
25
|
+
with rack_env: fetch(:rack_env), que_worker_count: fetch(:que_num_workers, 1) do
|
26
|
+
execute :bundle, :exec, :desmond, 'start', pid_dir
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Restart the desmond process'
|
33
|
+
task :restart do
|
34
|
+
on roles(:app) do
|
35
|
+
within release_path do
|
36
|
+
with rack_env: fetch(:rack_env), que_worker_count: fetch(:que_num_workers, 1) do
|
37
|
+
execute :bundle, :exec, :desmond, 'restart', pid_dir
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/desmond/rake.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative '../desmond'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
#
|
5
|
+
# returns migration files in the given directory +dirname+
|
6
|
+
#
|
7
|
+
def migrations(dirname)
|
8
|
+
Dir.foreach(dirname).select do |entry|
|
9
|
+
!entry.start_with?('.')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# returns the next migration number to use from the given directory +dirname+
|
15
|
+
#
|
16
|
+
def next_migration_number(dirname)
|
17
|
+
current_migration_number_str = migrations(dirname).map do |file|
|
18
|
+
File.basename(file).split('_').first
|
19
|
+
end.max || '0000'
|
20
|
+
current_migration_number = current_migration_number_str.to_i
|
21
|
+
|
22
|
+
num_digits = current_migration_number_str.size
|
23
|
+
if num_digits > 5
|
24
|
+
# timestamp format
|
25
|
+
[Time.now.utc.strftime('%Y%m%d%H%M%S'), format('%.14d', current_migration_number + 1)].max
|
26
|
+
else
|
27
|
+
# counter format
|
28
|
+
format("%.#{num_digits}d", current_migration_number + 1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# copy migration +source_file+ to migrations folder +dest_folder+
|
34
|
+
# if it doesn't exist ther yet
|
35
|
+
#
|
36
|
+
def copy_migration(source_file, dest_folder)
|
37
|
+
# check if migration already exists
|
38
|
+
migration_exists = migrations(dest_folder).map do |file|
|
39
|
+
File.basename(file).split('_')[1..-1].join('_').eql?(File.basename(source_file))
|
40
|
+
end.any?
|
41
|
+
return if migration_exists
|
42
|
+
|
43
|
+
# copy migration file
|
44
|
+
migration_number = next_migration_number(dest_folder)
|
45
|
+
base_migration_name = File.basename source_file
|
46
|
+
migration_name = "#{migration_number}_#{base_migration_name}"
|
47
|
+
dest_file = File.join dest_folder, migration_name
|
48
|
+
FileUtils.cp(source_file, dest_file)
|
49
|
+
end
|
50
|
+
|
51
|
+
# hook into db:migrate to create our migrations and migrate Que
|
52
|
+
namespace :db do
|
53
|
+
task :migrate => :desmond_migrate
|
54
|
+
|
55
|
+
task :desmond_migrate do
|
56
|
+
Rake::Task['desmond:migrate'].invoke
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
namespace :desmond do
|
61
|
+
desc 'Setup database for desmond manually'
|
62
|
+
task :migrate do
|
63
|
+
Que.migrate! version: 3
|
64
|
+
|
65
|
+
migration = File.join File.dirname(__FILE__), 'migrations', 'add_desmond_job_runs.rb'
|
66
|
+
copy_migration(migration, 'db/migrate')
|
67
|
+
end
|
68
|
+
|
69
|
+
desc 'Start daemon for desmond'
|
70
|
+
task :run do
|
71
|
+
require 'que/rake_tasks' # so that que's tasks don't get directly included in using apps
|
72
|
+
ActiveRecord::Base.logger = DesmondConfig.logger
|
73
|
+
DesmondConfig.send :set_daemon
|
74
|
+
Rake::Task['que:work'].invoke
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Clear job runs and queues'
|
78
|
+
task :clear do
|
79
|
+
require 'que/rake_tasks' # so that que's tasks don't get directly included in using apps
|
80
|
+
ActiveRecord::Base.logger = DesmondConfig.logger
|
81
|
+
Rake::Task['que:clear'].invoke
|
82
|
+
ActiveRecord::Base.connection.execute('TRUNCATE desmond_job_runs')
|
83
|
+
end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: desmond
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tobias Thiel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '6'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.2'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '6'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.2'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '6'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4.2'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '6'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: pg
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.17'
|
60
|
+
- - "<"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.17'
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '2.0'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: que
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0.9'
|
80
|
+
type: :runtime
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - "~>"
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0.9'
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: daemons
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "~>"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.2'
|
94
|
+
type: :runtime
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - "~>"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '1.2'
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: aws-sdk
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '2.0'
|
108
|
+
- - "<"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.0'
|
111
|
+
type: :runtime
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.0'
|
118
|
+
- - "<"
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '4.0'
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
name: rake
|
123
|
+
requirement: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - "~>"
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '12.0'
|
128
|
+
type: :runtime
|
129
|
+
prerelease: false
|
130
|
+
version_requirements: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - "~>"
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '12.0'
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: rspec
|
137
|
+
requirement: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
type: :development
|
143
|
+
prerelease: false
|
144
|
+
version_requirements: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: simplecov
|
151
|
+
requirement: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
type: :development
|
157
|
+
prerelease: false
|
158
|
+
version_requirements: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
- !ruby/object:Gem::Dependency
|
164
|
+
name: rubocop
|
165
|
+
requirement: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
type: :development
|
171
|
+
prerelease: false
|
172
|
+
version_requirements: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
- !ruby/object:Gem::Dependency
|
178
|
+
name: sinatra-activerecord
|
179
|
+
requirement: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
type: :development
|
185
|
+
prerelease: false
|
186
|
+
version_requirements: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
description: Background tasks & Exporting and importing data out of Amazon AWS RedShift
|
192
|
+
email: tobi@605.tv
|
193
|
+
executables:
|
194
|
+
- desmond
|
195
|
+
extensions: []
|
196
|
+
extra_rdoc_files: []
|
197
|
+
files:
|
198
|
+
- bin/desmond
|
199
|
+
- lib/desmond.rb
|
200
|
+
- lib/desmond/capistrano.rb
|
201
|
+
- lib/desmond/rake.rb
|
202
|
+
homepage: http://605.tv
|
203
|
+
licenses:
|
204
|
+
- MIT
|
205
|
+
metadata: {}
|
206
|
+
post_install_message:
|
207
|
+
rdoc_options: []
|
208
|
+
require_paths:
|
209
|
+
- lib
|
210
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
requirements: []
|
221
|
+
rubyforge_project:
|
222
|
+
rubygems_version: 2.6.12
|
223
|
+
signing_key:
|
224
|
+
specification_version: 4
|
225
|
+
summary: Background tasks & CSV Export/Import
|
226
|
+
test_files: []
|