iron_worker 2.1.0

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/README.markdown ADDED
@@ -0,0 +1,72 @@
1
+ Getting Started
2
+ ===============
3
+
4
+ [Sign up for a IronWorker account][1], it's free to try!
5
+
6
+ [1]: http://www.iron.io/
7
+
8
+ Install IronWorker Gem
9
+ ------------------------
10
+
11
+ gem install iron_worker
12
+
13
+ Configure IronWorker
14
+ ----------------------
15
+
16
+ You really just need your token, which you can get [here][2]
17
+ [2]: http://hud.iron.io/tokens
18
+
19
+ IronWorker.configure do |config|
20
+ config.token = TOKEN
21
+ config.project_id = MY_PROJECT_ID
22
+ end
23
+
24
+ Write a Worker
25
+ --------------
26
+
27
+ Here's an example worker that sends an email:
28
+
29
+ require 'iron_worker'
30
+
31
+ class HelloWorker < IronWorker::Base
32
+
33
+ attr_accessor :name
34
+
35
+ # This is the method that will be run
36
+ def run
37
+ puts "Hello #{name}!"
38
+ end
39
+ end
40
+
41
+ Test It Locally
42
+ ---------------
43
+
44
+ Let's say someone does something in your app and you want to send an email about it.
45
+
46
+ worker = HelloWorker.new
47
+ worker.name = "Travis"
48
+ worker.run_local
49
+
50
+ Once you've got it working locally, the next step is to run it on the IronWorker cloud.
51
+
52
+ Queue up your Worker on the IronWorker Cloud
53
+ ----------------------------------------------
54
+
55
+ Let's say someone does something in your app and you want to send an email about it.
56
+
57
+ worker = HelloWorker.new
58
+ worker.name = "Travis"
59
+ worker.queue
60
+
61
+ This will send it off to the IronWorker cloud.
62
+
63
+ Full Documentation
64
+ -----------------
65
+
66
+ Now that you've got your first worker running, be sure to [check out the full documentation](http://docs.iron.io).
67
+ IronWorker can do so much more!
68
+
69
+ Discussion Group
70
+ ----------------------
71
+
72
+ Join the discussion group at: https://groups.google.com/forum/#!forum/ironworker-users
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 2
3
+ :minor: 1
4
+ :patch: 0
5
+ :build:
@@ -0,0 +1,13 @@
1
+ class IronWorkerGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path("../templates", __FILE__)
3
+
4
+ desc "Creates a new skeleton worker - NAME is camelized"
5
+ def create_worker_file
6
+ # file_name needs to be classified
7
+ @camel = file_name.camelize
8
+ if not File.directory? "#{Rails.root}/app/workers"
9
+ Dir.mkdir "#{Rails.root}/app/workers"
10
+ end
11
+ template "template_worker.erb", "app/workers/#{file_name}.rb"
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'iron_worker/utils'
2
+ require_relative 'iron_worker/service'
3
+ require_relative 'iron_worker/base'
4
+ require_relative 'iron_worker/config'
5
+ require_relative 'iron_worker/used_in_worker'
6
+
7
+
8
+ module IronWorker
9
+ @@logger = Logger.new(STDOUT)
10
+ @@logger.level = Logger::INFO
11
+
12
+
13
+ class << self
14
+ attr_accessor :config,
15
+ :service
16
+
17
+ def configure()
18
+ yield(config)
19
+ if config && config.token
20
+ IronWorker.service ||= Service.new(config.token, :config=>config)
21
+ else
22
+ @@logger.warn "No token specified in configure, be sure to set it!"
23
+ end
24
+ end
25
+
26
+ def config
27
+ @config ||= Config.new
28
+ end
29
+
30
+ def logger
31
+ @@logger
32
+ end
33
+
34
+ def api_version
35
+ 2
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ if defined?(Rails)
42
+ # puts 'Rails=' + Rails.inspect
43
+ # puts 'vers=' + Rails::VERSION::MAJOR.inspect
44
+ if Rails::VERSION::MAJOR == 2
45
+ require_relative 'iron_worker/rails2_init.rb'
46
+ else
47
+ require_relative 'iron_worker/railtie'
48
+ end
49
+ end
@@ -0,0 +1,242 @@
1
+ require 'rest_client'
2
+ require_relative 'uber_client'
3
+
4
+ module IronWorker
5
+
6
+ class RequestError < StandardError
7
+ def initialize(msg, options={})
8
+ super(msg)
9
+ @options = options
10
+ end
11
+
12
+ def status
13
+ @options[:status]
14
+ end
15
+ end
16
+
17
+ module Api
18
+
19
+ module Signatures
20
+
21
+
22
+ def self.generate_timestamp(gmtime)
23
+ return gmtime.strftime("%Y-%m-%dT%H:%M:%SZ")
24
+ end
25
+
26
+
27
+ def self.generate_signature(operation, timestamp, secret_key)
28
+ my_sha_hmac = Digest::HMAC.digest(operation + timestamp, secret_key, Digest::SHA1)
29
+ my_b64_hmac_digest = Base64.encode64(my_sha_hmac).strip
30
+ return my_b64_hmac_digest
31
+ end
32
+
33
+
34
+ def self.hash_to_s(hash)
35
+ str = ""
36
+ hash.sort.each { |a| str+= "#{a[0]}#{a[1]}" }
37
+ #removing all characters that could differ after parsing with rails
38
+ return str.delete "\"\/:{}[]\' T"
39
+ end
40
+ end
41
+
42
+ # Subclass must define:
43
+ # host: endpoint url for service
44
+ class Client
45
+
46
+ attr_accessor :scheme, :host, :port, :token, :version, :config
47
+
48
+ def initialize(host, token, options={})
49
+ @config = options[:config]
50
+ @scheme = options[:scheme] || @config.scheme || "https"
51
+ @host = options[:host] || @config.host || host
52
+ @port = options[:port] || @config.port || 443
53
+ @token = options[:token] || @config.token || token
54
+ @version = options[:version]
55
+ #@logger = options[:logger]
56
+
57
+ @base_url = "#{@scheme}://#{@host}:#{@port}/#{@version}"
58
+
59
+ @uber_client = Uber::Client.new
60
+
61
+ end
62
+
63
+
64
+ def base_url
65
+ @base_url
66
+ end
67
+
68
+ def url(command_path)
69
+ # @logger.debug "url: " + url.to_s
70
+ "/#{command_path}"
71
+ end
72
+
73
+ def url_full(command_path)
74
+ url = "#{base_url}/#{command_path}"
75
+ # @logger.debug "url: " + url.to_s
76
+ url
77
+ end
78
+
79
+
80
+ def common_req_hash
81
+ {
82
+ :headers=>{"Content-Type" => 'application/json',
83
+ "Authorization"=>"OAuth #{@token}",
84
+ "User-Agent"=>"IronWorker Ruby Client"}
85
+ }
86
+ end
87
+
88
+ def process_ex(ex)
89
+ logger.error "EX #{ex.class.name}: #{ex.message}"
90
+ body = ex.http_body
91
+ logger.debug 'EX http_code: ' + ex.http_code.to_s
92
+ logger.debug 'EX BODY=' + body.to_s
93
+ decoded_ex = JSON.parse(body)
94
+ exception = Exception.new(ex.message + ": " + decoded_ex["msg"])
95
+ exception.set_backtrace(decoded_ex["backtrace"].split(",")) if decoded_ex["backtrace"]
96
+ raise exception
97
+ end
98
+
99
+
100
+ def check_response(response, options={})
101
+ # response.code # http status code
102
+ #response.time # time in seconds the request took
103
+ #response.headers # the http headers
104
+ #response.headers_hash # http headers put into a hash
105
+ #response.body # the response body
106
+ status = response.code
107
+ body = response.body
108
+ # todo: check content-type == application/json before parsing
109
+ logger.debug "response code=" + status.to_s
110
+ logger.debug "response body=" + body.inspect
111
+ res = nil
112
+ unless options[:parse] == false
113
+ res = JSON.parse(body)
114
+ end
115
+ if status < 400
116
+
117
+ else
118
+ raise IronWorker::RequestError.new((res ? "#{status}: #{res["msg"]}" : "#{status} Error! parse=false so no msg"), :status=>status)
119
+ end
120
+ res || body
121
+ end
122
+
123
+ def get(method, params={}, options={})
124
+ full_url = url_full(method)
125
+ #all_params = add_params(method, params)
126
+ #url_plus_params = append_params(full_url, all_params)
127
+ logger.debug 'get url=' + full_url
128
+ req_hash = common_req_hash
129
+ req_hash[:params] = params
130
+ response = @uber_client.get(full_url, req_hash) # could let typhoeus add params, using :params=>x
131
+ #response = @http_sess.request(:get, url_plus_params,
132
+ # {},
133
+ # {})
134
+ check_response(response, options)
135
+ body = response.body
136
+ parse_response(body, options)
137
+
138
+ end
139
+
140
+ def post_file(method, file, params={}, options={})
141
+ begin
142
+ data = add_params(method, params).to_json
143
+ url = url_full(method)
144
+ logger.debug "post_file url = " + url
145
+ logger.debug "data = " + data
146
+ logger.debug "params = " + params.inspect
147
+ logger.debug "options = " + options.inspect
148
+ # todo: replace with uber_client
149
+ parse_response(RestClient.post(append_params(url, add_params(method, params)), {:data => data, :file => file}, :content_type => 'application/json'), options)
150
+ rescue RestClient::Exception => ex
151
+ process_ex(ex)
152
+ end
153
+ end
154
+
155
+ def post(method, params={}, options={})
156
+ logger.debug "params = " + params.inspect
157
+ logger.debug "options = " + options.inspect
158
+ logger.debug "params.payload = " + params[:payload].inspect
159
+ logger.debug "token = "+ token.inspect
160
+ begin
161
+ url = url_full(method)
162
+ logger.debug 'post url=' + url
163
+ json = add_params(method, params).to_json
164
+ logger.debug 'body=' + json
165
+ req_hash = common_req_hash
166
+ req_hash[:body] = json
167
+ response = @uber_client.post(url, req_hash)
168
+ #response = @http_sess.post(url, json, {"Content-Type" => 'application/json'})
169
+ check_response(response)
170
+ logger.debug 'response: ' + response.inspect
171
+ body = response.body
172
+ parse_response(body, options)
173
+ rescue IronWorker::RequestError => ex
174
+ # let it throw, came from check_response
175
+ raise ex
176
+ rescue RestClient::Exception => ex
177
+ logger.warn("Exception in post! #{ex.message}")
178
+ logger.warn(ex.backtrace.join("\n"))
179
+ process_ex(ex)
180
+ end
181
+ end
182
+
183
+
184
+ def put(method, body, options={})
185
+ begin
186
+ # todo: replace with uber_client
187
+ parse_response RestClient.put(url_full(method), add_params(method, body).to_json, headers), options
188
+ rescue RestClient::Exception => ex
189
+ process_ex(ex)
190
+ end
191
+ end
192
+
193
+ def delete(method, params={}, options={})
194
+ begin
195
+ # todo: replace with uber_client
196
+ parse_response RestClient.delete(append_params(url_full(method), add_params(method, params))), options
197
+ rescue RestClient::Exception => ex
198
+ process_ex(ex)
199
+ end
200
+ end
201
+
202
+ def add_params(command_path, hash)
203
+ extra_params = {'oauth' => token}
204
+ hash.merge!(extra_params)
205
+ end
206
+
207
+ def append_params(host, params)
208
+ host += "?"
209
+ i = 0
210
+ params.each_pair do |k, v|
211
+ #puts "k=#{k} v=#{v}"
212
+ host += "&" if i > 0
213
+ host += k + "=" + (v.is_a?(String) ? CGI.escape(v) : v.to_s)
214
+ i +=1
215
+ end
216
+ return host
217
+ end
218
+
219
+ def headers
220
+ user_agent = "IronWorker Ruby Client"
221
+ headers = {'User-Agent' => user_agent}
222
+ end
223
+
224
+ def parse_response(response, options={})
225
+ #puts 'PARSE RESPONSE: ' + response.to_s
226
+ unless options[:parse] == false
227
+ begin
228
+ return JSON.parse(response.to_s)
229
+ rescue => ex
230
+ puts 'parse_response: response that caused error = ' + response.to_s
231
+ raise ex
232
+ end
233
+ else
234
+ response
235
+ end
236
+ end
237
+
238
+ end
239
+
240
+ end
241
+
242
+ end
@@ -0,0 +1,432 @@
1
+ require 'digest/md5'
2
+ require 'base64'
3
+
4
+ module IronWorker
5
+
6
+ class Base
7
+
8
+ attr_accessor :task_set_id, :task_id, :schedule_id
9
+ attr_reader :response
10
+
11
+ class << self
12
+ attr_accessor :subclass, :caller_file
13
+ @merged = {}
14
+ @merged_workers = {}
15
+ @merged_gems = {}
16
+ @merged_mailers = {}
17
+ @merged_folders = {}
18
+ @unmerged = {}
19
+ @unmerged_gems = {}
20
+
21
+ def reset!
22
+ @merged = {}
23
+ @merged_workers = {}
24
+ @merged_gems = {}
25
+ @merged_mailers = {}
26
+ @merged_folders = {}
27
+ @unmerged = {}
28
+ @unmerged_gems = {}
29
+ end
30
+
31
+ def inherited(subclass)
32
+ subclass.reset!
33
+
34
+ caller_file = caller[0][0...(caller[0].index(":in"))]
35
+ caller_file = caller_file[0...(caller_file.rindex(":"))]
36
+ subclass.instance_variable_set(:@caller_file, caller_file)
37
+
38
+ super
39
+ end
40
+
41
+ # merges the specified gem.
42
+ def merge_gem(gem_name, options={})
43
+ gem_info = IronWorker::MergeHelper.create_gem_info(gem_name, options)
44
+ @merged_gems[gem_name.to_s] = gem_info
45
+ reqs = gem_info[:require].is_a?(Array) ? gem_info[:require] : [gem_info[:require]]
46
+ reqs.each do |r|
47
+ r2 = "#{gem_info[:path]}/lib/#{r}"
48
+ begin
49
+ IronWorker.logger.debug 'requiring ' + r2
50
+ require r2
51
+ rescue LoadError=>ex
52
+ IronWorker.logger.error "Error requiring gem #{r}: #{ex.message}"
53
+ raise "Gem #{gem_name} was found, but we could not load the file '#{r2}'. You may need to use :require=>x.........."
54
+ end
55
+ end
56
+ end
57
+
58
+
59
+ def unmerge_gem(gem_name)
60
+ #gem_info = {:name=>gem_name}
61
+ #@unmerged_gems[gem_name.to_s] = gem_info
62
+ gs = gem_name.to_s
63
+ gem_info = {:name=>gs}
64
+ @unmerged_gems[gs] = gem_info
65
+ @merged_gems.delete(gs)
66
+ end
67
+
68
+ #merge action_mailer mailers
69
+ def merge_mailer(mailer, params={})
70
+ f2 = IronWorker::MergeHelper.check_for_file(mailer, @caller_file)
71
+ basename = File.basename(mailer, f2[:extname])
72
+ path_to_templates = params[:path_to_templates] || File.join(Rails.root, "app/views/#{basename}")
73
+ @merged_mailers[basename] = {:name=>basename, :path_to_templates=>path_to_templates, :filename => f2[:path]}.merge!(params)
74
+ end
75
+
76
+ def merge_folder(path)
77
+ files = []
78
+ #puts "caller_file=" + caller_file
79
+ if path[0, 1] == '/'
80
+ abs_dir = path
81
+ else # relative
82
+ abs_dir = File.join(File.dirname(caller_file), path)
83
+ end
84
+ #puts 'abs_dir=' + abs_dir
85
+ raise "Folder not found for merge_folder #{path}!" unless File.directory?(abs_dir)
86
+ rbfiles = File.join(abs_dir, "*.rb")
87
+ Dir[rbfiles].each do |f|
88
+ #f2 = check_for_file(f)
89
+ #puts "f2=#{f2}"
90
+ merge(f)
91
+ #files << f
92
+ #@merged[f]
93
+ end
94
+ #@merged_folders[path] = files unless files.empty?
95
+ #IronWorker.logger.info "Merged folders! #{@merged_folders.inspect}"
96
+ end
97
+
98
+ # merges the specified file.
99
+ #
100
+ # Example: merge 'models/my_model'
101
+ def merge(f)
102
+ f2 = IronWorker::MergeHelper.check_for_file(f, @caller_file)
103
+ fbase = f2[:basename]
104
+ ret = f2
105
+ @merged[fbase] = ret
106
+ ret
107
+ end
108
+
109
+ # Opposite of merge, this will omit the files you specify from being merged in. Useful in Rails apps
110
+ # where a lot of things are auto-merged by default like your models.
111
+ def unmerge(f)
112
+ f2 = IronWorker::MergeHelper.check_for_file(f, @caller_file)
113
+ fbase = f2[:basename]
114
+ @unmerged[fbase] = f2
115
+ @merged.delete(fbase)
116
+ end
117
+
118
+
119
+ # Use this to merge in other workers. These are treated differently the normal merged files because
120
+ # they will be uploaded separately and treated as distinctly separate workers.
121
+ #
122
+ # file: This is the path to the file, just like merge.
123
+ # class_name: eg: 'MyWorker'.
124
+ def merge_worker(file, class_name)
125
+ # puts 'merge_worker in ' + self.name
126
+ ret = merge(file)
127
+ ret[:class_name] = class_name
128
+ #[File.expand_path(file), class_name]
129
+ @merged_workers[file] = ret
130
+ ret
131
+ end
132
+ end
133
+
134
+
135
+ def log(str)
136
+ puts str.to_s
137
+ end
138
+
139
+ def user_dir
140
+ "./"
141
+ end
142
+
143
+ def set_progress(hash)
144
+ puts 'set_progress: ' + hash.inspect
145
+ end
146
+
147
+ def who_am_i?
148
+ return self.class.name
149
+ end
150
+
151
+ def uploaded?
152
+ self.class.instance_variable_defined?(:@uploaded) && self.class.instance_variable_get(:@uploaded)
153
+ end
154
+
155
+ # Call this if you want to run locally and get some extra features from this gem like global attributes.
156
+ def run_local
157
+ # puts 'run_local'
158
+ set_auto_attributes
159
+ init_database
160
+ init_mailer
161
+ begin
162
+ run
163
+ rescue => ex
164
+ if self.respond_to?(:rescue_all)
165
+ rescue_all(ex)
166
+ else
167
+ raise ex
168
+ end
169
+ end
170
+ end
171
+
172
+ def init_mailer
173
+ if IronWorker.config.mailer
174
+ require 'action_mailer'
175
+ ActionMailer::Base.raise_delivery_errors = true
176
+ ActionMailer::Base.smtp_settings = (IronWorker.config.mailer)
177
+ end
178
+ end
179
+
180
+ def init_database
181
+ if IronWorker.config.database
182
+ require 'active_record'
183
+ if !ActiveRecord::Base.connected?
184
+ ActiveRecord::Base.establish_connection(IronWorker.config.database)
185
+ end
186
+ end
187
+ end
188
+
189
+ def set_auto_attributes
190
+ set_global_attributes
191
+ end
192
+
193
+ def set_global_attributes
194
+ return unless IronWorker.config
195
+ ga = IronWorker.config.global_attributes
196
+ if ga && ga.size > 0
197
+ ga.each_pair do |k, v|
198
+ # puts "k=#{k} v=#{v}"
199
+ if self.respond_to?(k)
200
+ self.send("#{k}=", v)
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ def enqueue(options={})
207
+ queue(options)
208
+ end
209
+
210
+ # Call this to queue up your job to IronWorker cloud.
211
+ # options:
212
+ # :priority => 0, 1 or 2. Default is 0.
213
+ # :recursive => true/false. Default is false. If you queue up a worker that is the same class as the currently
214
+ # running worker, it will be rejected unless you set this explicitly so we know you meant to do it.
215
+ def queue(options={})
216
+ # puts 'in queue'
217
+ set_auto_attributes
218
+ upload_if_needed(options)
219
+
220
+ response = IronWorker.service.queue(self.class.name, sw_get_data, options)
221
+ IronWorker.service.logger.debug 'queue response=' + response.inspect
222
+ @response = response
223
+ @task_id = response["tasks"][0]["id"]
224
+ response
225
+ end
226
+
227
+ # Receive the status of your worker.
228
+ def status
229
+ check_service
230
+ if task_id
231
+ task_status
232
+ elsif schedule_id
233
+ schedule_status
234
+ else
235
+ raise "Queue or schedule before check status."
236
+ end
237
+ end
238
+
239
+ def task_status
240
+ IronWorker.service.status(task_id)
241
+ end
242
+
243
+ def is_local?
244
+ !is_remote?
245
+ end
246
+
247
+ def is_remote?
248
+ false
249
+ end
250
+
251
+ # will return after job has completed or errored out.
252
+ # Returns status.
253
+ # todo: add a :timeout option
254
+ def wait_until_complete
255
+ check_service
256
+ IronWorker.service.wait_until_complete(self.task_id)
257
+ end
258
+
259
+ def upload
260
+ upload_if_needed
261
+ end
262
+
263
+ #
264
+ # schedule: hash of scheduling options that can include:
265
+ # Required:
266
+ # - start_at: Time of first run - DateTime or Time object.
267
+ # Optional:
268
+ # - run_every: Time in seconds between runs. If ommitted, task will only run once.
269
+ # - delay_type: Fixed Rate or Fixed Delay. Default is fixed_delay.
270
+ # - end_at: Scheduled task will stop running after this date (optional, if ommitted, runs forever or until cancelled)
271
+ # - run_times: Task will run exactly :run_times. For instance if :run_times is 5, then the task will run 5 times.
272
+ # - name: Provide a name for the schedule, defaults to class name. Use this if you want more than one schedule per worker class.
273
+ #
274
+ def schedule(schedule)
275
+ set_global_attributes
276
+ upload_if_needed(schedule)
277
+
278
+ response = IronWorker.service.schedule(self.class.name, sw_get_data, schedule)
279
+ IronWorker.service.logger.debug 'schedule response=' + response.inspect
280
+ @schedule_id = response["schedules"][0]["id"]
281
+ response
282
+ end
283
+
284
+ def schedule_status
285
+ IronWorker.service.schedule_status(schedule_id)
286
+ end
287
+
288
+ # Retrieves the log for this worker from the IronWorker service.
289
+ def get_log(options={})
290
+ IronWorker.service.get_log(task_id, options)
291
+ end
292
+
293
+ # Callbacks for developer
294
+ def before_upload
295
+
296
+ end
297
+
298
+ def after_upload
299
+
300
+ end
301
+
302
+ def before_run
303
+
304
+ end
305
+
306
+ def after_run
307
+
308
+ end
309
+
310
+ private
311
+
312
+ def gems_to_merge(merged_gems)
313
+ list_of_gems = {}
314
+ if merged_gems && merged_gems.size > 0
315
+ installed_gems = IronWorker.config.get_server_gems
316
+ merged_gems.each_pair do |k, gem|
317
+ gem.merge!({:merge=>(!installed_gems.find { |g| g["name"]==gem[:name] && g["version"]==gem[:version] })})
318
+ list_of_gems[gem[:name]] = gem # don't' need this if (list_of_gems.select { |k,g| g[:name]==gem[:name] }).empty?
319
+ end
320
+ IronWorker.logger.debug "#{list_of_gems.inspect}"
321
+ end
322
+ list_of_gems
323
+ end
324
+
325
+ def check_service
326
+ raise "IronWorker configuration not set." unless IronWorker.service
327
+ end
328
+
329
+ def self.extract_superclasses_merges(worker, merged)
330
+ subclass = worker.class
331
+ rfile = subclass.instance_variable_get(:@caller_file) # Base.caller_file # File.expand_path(Base.subclass)
332
+ # puts 'subclass file=' + rfile.inspect
333
+ # puts 'subclass.name=' + subclass.name
334
+ superclass = subclass
335
+ # Also get merged from subclasses up to IronWorker::Base
336
+ while (superclass = superclass.superclass)
337
+ #puts 'superclass=' + superclass.name
338
+ break if superclass.name == IronWorker::Base.name
339
+ super_merged = superclass.instance_variable_get(:@merged)
340
+ #puts 'merging caller file: ' + superclass.instance_variable_get(:@caller_file).inspect
341
+ caller_to_add = superclass.instance_variable_get(:@caller_file)
342
+ fb = File.basename(caller_to_add)
343
+ r = {:name=>fb, :path=>caller_to_add}
344
+ super_merged[fb] = r
345
+ merged.merge!(super_merged)
346
+ #puts 'merged with superclass=' + merged.inspect
347
+ end
348
+ return merged, rfile, subclass
349
+ end
350
+
351
+ def self.extract_merged_workers(worker)
352
+ merged_workers = worker.class.instance_variable_get(:@merged_workers)
353
+ IronWorker.logger.debug "Looking for merged_workers in #{worker.class.name}: #{merged_workers.inspect}"
354
+ ret = {}
355
+ if merged_workers && merged_workers.size > 0
356
+ merged_workers.each_pair do |k, mw|
357
+ IronWorker.logger.debug "merged worker found in #{worker.class.name}: #{mw.inspect}"
358
+ ret[mw[:name]] = mw
359
+ end
360
+ end
361
+ ret
362
+ end
363
+
364
+ def upload_if_needed(options={})
365
+ check_service
366
+ IronWorker.service.check_config
367
+
368
+ before_upload
369
+
370
+ merged = self.class.instance_variable_get(:@merged)
371
+
372
+ # do merged_workers first because we need to get their subclasses and what not too
373
+ merged_workers = self.class.instance_variable_get(:@merged_workers)
374
+ if merged_workers && merged_workers.size > 0
375
+ IronWorker.logger.debug 'now uploading merged workers ' + merged_workers.inspect
376
+ merged_workers.each_pair do |mw, v|
377
+ IronWorker.logger.debug 'Instantiating and uploading ' + v.inspect
378
+ mw_instantiated = Kernel.const_get(v[:class_name]).new
379
+ mw_instantiated.upload
380
+
381
+ merged, rfile, subclass = IronWorker::Base.extract_superclasses_merges(mw_instantiated, merged)
382
+ merged.merge!(IronWorker::Base.extract_merged_workers(mw_instantiated))
383
+
384
+ end
385
+ end
386
+
387
+ if !uploaded?
388
+ unmerged = self.class.instance_variable_get(:@unmerged)
389
+ merged_gems = self.class.instance_variable_get(:@merged_gems)
390
+ merged_mailers = self.class.instance_variable_get(:@merged_mailers)
391
+ merged_folders = self.class.instance_variable_get(:@merged_folders)
392
+ merged, rfile, subclass = IronWorker::Base.extract_superclasses_merges(self, merged)
393
+ merged_mailers = merged_mailers.merge(IronWorker.config.mailers) if IronWorker.config.mailers
394
+ unless merged_gems.size == 0
395
+ merged_gems = gems_to_merge(merged_gems)
396
+ end
397
+
398
+ options_for_upload = {:merge=>merged, :unmerge=>unmerged, :merged_gems=>merged_gems, :merged_mailers=>merged_mailers, :merged_folders=>merged_folders}
399
+ options_for_upload.merge!(options)
400
+ IronWorker.service.upload(rfile, subclass.name, options_for_upload)
401
+ self.class.instance_variable_set(:@uploaded, true)
402
+ else
403
+ IronWorker.logger.debug 'Already uploaded for ' + self.class.name
404
+ end
405
+
406
+ after_upload
407
+ end
408
+
409
+ def sw_get_data
410
+ data = {}
411
+
412
+ payload = {}
413
+ # todo: should put these down a layer, eg: payload[:attributes]
414
+ self.instance_variables.each do |iv|
415
+ payload[iv] = instance_variable_get(iv)
416
+ end
417
+ data['class_name'] = self.class.name
418
+ data[:attr_encoded] = Base64.encode64(payload.to_json)
419
+ data[:file_name] = File.basename(self.class.instance_variable_get(:@caller_file))
420
+ if defined?(Rails)
421
+ data[:rails] = {}
422
+ data[:rails]['env'] = Rails.env
423
+ data[:rails]['version'] = Rails.version
424
+ end
425
+ config_data = IronWorker.config.get_atts_to_send
426
+ data[:sw_config] = config_data
427
+ return data
428
+ end
429
+
430
+
431
+ end
432
+ end