background_queue 0.2.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/.document +5 -0
- data/.rspec +1 -0
- data/.rvmrc +48 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +20 -0
- data/README.md +69 -0
- data/Rakefile +42 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/background_queue.gemspec +158 -0
- data/bin/bg_queue +26 -0
- data/lib/background_queue.rb +8 -0
- data/lib/background_queue/client.rb +96 -0
- data/lib/background_queue/client_lib/command.rb +36 -0
- data/lib/background_queue/client_lib/config.rb +109 -0
- data/lib/background_queue/client_lib/connection.rb +105 -0
- data/lib/background_queue/client_lib/job_handle.rb +19 -0
- data/lib/background_queue/command.rb +49 -0
- data/lib/background_queue/config.rb +118 -0
- data/lib/background_queue/server_lib/balanced_queue.rb +108 -0
- data/lib/background_queue/server_lib/config.rb +339 -0
- data/lib/background_queue/server_lib/event_connection.rb +133 -0
- data/lib/background_queue/server_lib/event_server.rb +35 -0
- data/lib/background_queue/server_lib/job.rb +252 -0
- data/lib/background_queue/server_lib/job_registry.rb +30 -0
- data/lib/background_queue/server_lib/lru.rb +193 -0
- data/lib/background_queue/server_lib/owner.rb +54 -0
- data/lib/background_queue/server_lib/priority_queue.rb +156 -0
- data/lib/background_queue/server_lib/queue_registry.rb +123 -0
- data/lib/background_queue/server_lib/server.rb +314 -0
- data/lib/background_queue/server_lib/sorted_workers.rb +52 -0
- data/lib/background_queue/server_lib/task.rb +79 -0
- data/lib/background_queue/server_lib/task_registry.rb +51 -0
- data/lib/background_queue/server_lib/thread_manager.rb +121 -0
- data/lib/background_queue/server_lib/worker.rb +18 -0
- data/lib/background_queue/server_lib/worker_balancer.rb +97 -0
- data/lib/background_queue/server_lib/worker_client.rb +94 -0
- data/lib/background_queue/server_lib/worker_thread.rb +70 -0
- data/lib/background_queue/utils.rb +40 -0
- data/lib/background_queue/worker/base.rb +46 -0
- data/lib/background_queue/worker/calling.rb +59 -0
- data/lib/background_queue/worker/config.rb +35 -0
- data/lib/background_queue/worker/environment.rb +70 -0
- data/lib/background_queue/worker/worker_loader.rb +94 -0
- data/lib/background_queue_server.rb +21 -0
- data/lib/background_queue_worker.rb +5 -0
- data/spec/background_queue/client_lib/command_spec.rb +75 -0
- data/spec/background_queue/client_lib/config_spec.rb +156 -0
- data/spec/background_queue/client_lib/connection_spec.rb +170 -0
- data/spec/background_queue/client_spec.rb +95 -0
- data/spec/background_queue/command_spec.rb +34 -0
- data/spec/background_queue/config_spec.rb +134 -0
- data/spec/background_queue/server_lib/balanced_queue_spec.rb +122 -0
- data/spec/background_queue/server_lib/config_spec.rb +443 -0
- data/spec/background_queue/server_lib/event_connection_spec.rb +190 -0
- data/spec/background_queue/server_lib/event_server_spec.rb +48 -0
- data/spec/background_queue/server_lib/integration/full_test_spec.rb +247 -0
- data/spec/background_queue/server_lib/integration/queue_integration_spec.rb +98 -0
- data/spec/background_queue/server_lib/integration/serialize_spec.rb +127 -0
- data/spec/background_queue/server_lib/job_registry_spec.rb +65 -0
- data/spec/background_queue/server_lib/job_spec.rb +525 -0
- data/spec/background_queue/server_lib/owner_spec.rb +33 -0
- data/spec/background_queue/server_lib/priority_queue_spec.rb +182 -0
- data/spec/background_queue/server_lib/server_spec.rb +353 -0
- data/spec/background_queue/server_lib/sorted_workers_spec.rb +122 -0
- data/spec/background_queue/server_lib/task_registry_spec.rb +69 -0
- data/spec/background_queue/server_lib/task_spec.rb +20 -0
- data/spec/background_queue/server_lib/thread_manager_spec.rb +106 -0
- data/spec/background_queue/server_lib/worker_balancer_spec.rb +127 -0
- data/spec/background_queue/server_lib/worker_client_spec.rb +196 -0
- data/spec/background_queue/server_lib/worker_thread_spec.rb +125 -0
- data/spec/background_queue/utils_spec.rb +27 -0
- data/spec/background_queue/worker/base_spec.rb +35 -0
- data/spec/background_queue/worker/calling_spec.rb +103 -0
- data/spec/background_queue/worker/environment_spec.rb +67 -0
- data/spec/background_queue/worker/worker_loader_spec.rb +103 -0
- data/spec/background_queue_spec.rb +7 -0
- data/spec/resources/config-client.yml +7 -0
- data/spec/resources/config-serialize.yml +12 -0
- data/spec/resources/config.yml +12 -0
- data/spec/resources/example_worker.rb +4 -0
- data/spec/resources/example_worker_with_error.rb +4 -0
- data/spec/resources/test_worker.rb +8 -0
- data/spec/shared/queue_registry_shared.rb +216 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/default_task.rb +9 -0
- data/spec/support/private.rb +23 -0
- data/spec/support/simple_server.rb +28 -0
- data/spec/support/simple_task.rb +58 -0
- data/spec/support/test_worker_server.rb +205 -0
- metadata +254 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
#we want a list of workers where the first in the list is the next worker to use.
|
2
|
+
#the next worker to use is the worker with the least number of running connections
|
3
|
+
|
4
|
+
class BackgroundQueue::ServerLib::SortedWorkers
|
5
|
+
|
6
|
+
attr_reader :worker_list
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@worker_list = []
|
10
|
+
end
|
11
|
+
|
12
|
+
#add the worker back in the correct position
|
13
|
+
def add_worker(worker)
|
14
|
+
idx = 0
|
15
|
+
while idx < @worker_list.length && @worker_list[idx].connections < worker.connections
|
16
|
+
idx += 1
|
17
|
+
end
|
18
|
+
if idx == 0
|
19
|
+
@worker_list.unshift(worker)
|
20
|
+
else
|
21
|
+
@worker_list.insert(idx, worker)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_worker(worker)
|
26
|
+
@worker_list.delete(worker)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def adjust_worker(worker)
|
31
|
+
idx = @worker_list.index(worker)
|
32
|
+
raise "Worker not found (#{worker.inspect} not in #{@worker_list.inspect})" if idx.nil?
|
33
|
+
swap_idx = idx - 1
|
34
|
+
while swap_idx >= 0 && @worker_list[swap_idx].connections > worker.connections
|
35
|
+
swap_idx -= 1
|
36
|
+
end
|
37
|
+
swap_idx += 1
|
38
|
+
if swap_idx == idx #we didnt move forward, try backwards
|
39
|
+
swap_idx = idx + 1
|
40
|
+
while swap_idx < @worker_list.length && @worker_list[swap_idx].connections < worker.connections
|
41
|
+
swap_idx += 1
|
42
|
+
end
|
43
|
+
swap_idx -= 1
|
44
|
+
end
|
45
|
+
if swap_idx != idx
|
46
|
+
tmp = @worker_list[swap_idx]
|
47
|
+
@worker_list[swap_idx] = @worker_list[idx]
|
48
|
+
@worker_list[idx] = tmp
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module BackgroundQueue::ServerLib
|
2
|
+
class Task
|
3
|
+
|
4
|
+
attr_accessor :id
|
5
|
+
attr_accessor :priority
|
6
|
+
|
7
|
+
attr_accessor :owner_id
|
8
|
+
attr_accessor :job_id
|
9
|
+
|
10
|
+
attr_accessor :worker
|
11
|
+
|
12
|
+
attr_accessor :running
|
13
|
+
|
14
|
+
attr_accessor :options
|
15
|
+
|
16
|
+
def initialize(owner_id, job_id, id, priority, worker, params, options)
|
17
|
+
@owner_id = owner_id
|
18
|
+
@job_id = job_id
|
19
|
+
@id = id
|
20
|
+
@priority = priority
|
21
|
+
@worker = worker
|
22
|
+
@running = false
|
23
|
+
@options = options
|
24
|
+
@params = params
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_json(dummy=true)
|
28
|
+
to_json_object(false).to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json_object(full)
|
32
|
+
jo = {:owner_id=>@owner_id, :job_id=>@job_id, :id=>@id, :priority=>@priority, :worker=>@worker, :params=>@params }
|
33
|
+
if full
|
34
|
+
jo[:options] = @options
|
35
|
+
end
|
36
|
+
jo
|
37
|
+
end
|
38
|
+
|
39
|
+
def running?
|
40
|
+
@running
|
41
|
+
end
|
42
|
+
|
43
|
+
def domain
|
44
|
+
@options[:domain]
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_job(job)
|
48
|
+
@job = job
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_excluded_from_count?
|
52
|
+
@options[:exclude] == true
|
53
|
+
end
|
54
|
+
|
55
|
+
def synchronous?
|
56
|
+
@options[:synchronous] == true
|
57
|
+
end
|
58
|
+
|
59
|
+
def weighted?
|
60
|
+
@options[:weight] && @options[:weight] > 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def weighted_percent
|
64
|
+
@options[:weight]
|
65
|
+
end
|
66
|
+
|
67
|
+
def initial_progress_caption
|
68
|
+
@options[:initial_progress_caption]
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_worker_status(status)
|
72
|
+
raise "Task without job set" if @job.nil?
|
73
|
+
status[:task_id] = self.id
|
74
|
+
status[:exclude] = self.is_excluded_from_count?
|
75
|
+
status[:weight] = self.weighted_percent if self.weighted?
|
76
|
+
@job.set_worker_status(status)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module BackgroundQueue::ServerLib
|
2
|
+
|
3
|
+
#keep track if tasks already queued and running so if the same task comes in, we know to remove it.
|
4
|
+
class TaskRegistry
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@waiting_tasks = {}
|
8
|
+
@tasks = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(task)
|
12
|
+
existing_task = @tasks[task.id]
|
13
|
+
if existing_task.nil?
|
14
|
+
@tasks[task.id] = task
|
15
|
+
[:new, nil]
|
16
|
+
elsif existing_task.running?
|
17
|
+
register_waiting_task(task)
|
18
|
+
[:waiting, nil]
|
19
|
+
else
|
20
|
+
@tasks[task.id] = task
|
21
|
+
[:existing, existing_task]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def de_register(task_id)
|
26
|
+
@tasks.delete(task_id)
|
27
|
+
waiting = get_waiting_task(task_id)
|
28
|
+
if waiting
|
29
|
+
@tasks[task_id] = waiting
|
30
|
+
end
|
31
|
+
waiting
|
32
|
+
end
|
33
|
+
|
34
|
+
def register_waiting_task(task)
|
35
|
+
@waiting_tasks[task.id] = task
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_waiting_task(task_id)
|
39
|
+
@waiting_tasks.delete(task_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def waiting_tasks
|
43
|
+
@waiting_tasks
|
44
|
+
end
|
45
|
+
|
46
|
+
def tasks
|
47
|
+
@tasks
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
#make sure threads are schedules and the max number of threads is controlled
|
2
|
+
class BackgroundQueue::ServerLib::ThreadManager
|
3
|
+
|
4
|
+
attr_accessor :max_threads
|
5
|
+
attr_reader :running_threads
|
6
|
+
|
7
|
+
def initialize(server, max_threads)
|
8
|
+
@server = server
|
9
|
+
@max_threads = max_threads
|
10
|
+
@running_threads = 0
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@condvar = ConditionVariable.new
|
13
|
+
@threads = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def protect_access(&block)
|
17
|
+
@mutex.synchronize {
|
18
|
+
block.call
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def control_access(&block)
|
23
|
+
@mutex.synchronize {
|
24
|
+
if @running_threads >= @max_threads && @server.running?
|
25
|
+
@running_threads -= 1
|
26
|
+
@condvar.wait(@mutex)
|
27
|
+
@running_threads += 1
|
28
|
+
end
|
29
|
+
block.call
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
#signal any waiting threads
|
34
|
+
#this should only be called from with a protect_access/control_access block
|
35
|
+
#will do nothing if there are already too many threads running
|
36
|
+
def signal_access
|
37
|
+
@condvar.signal unless @running_threads >= @max_threads
|
38
|
+
end
|
39
|
+
|
40
|
+
#wait for the condition
|
41
|
+
#must be called from within protect_access/control_access block
|
42
|
+
def wait_on_access
|
43
|
+
if @server.running?
|
44
|
+
@running_threads -= 1
|
45
|
+
#puts "waiting"
|
46
|
+
@condvar.wait(@mutex)
|
47
|
+
#puts "woken"
|
48
|
+
@running_threads += 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def change_concurrency(max_threads)
|
53
|
+
@mutex.synchronize {
|
54
|
+
if max_threads > @max_threads
|
55
|
+
for i in @max_threads...max_threads
|
56
|
+
@condvar.signal
|
57
|
+
end
|
58
|
+
end
|
59
|
+
@max_threads = max_threads
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def start(clazz)
|
65
|
+
@mutex.synchronize {
|
66
|
+
for i in 0...@max_threads
|
67
|
+
runner = clazz.new(@server)
|
68
|
+
@running_threads += 1
|
69
|
+
#puts "started thread, running=#{@running_threads}"
|
70
|
+
@threads << Thread.new(runner) { |runner|
|
71
|
+
begin
|
72
|
+
runner.run
|
73
|
+
rescue Exception=>e
|
74
|
+
@server.logger.error("Error in thread: #{e.message}")
|
75
|
+
@server.logger.debug(e.backtrace.join("\n"))
|
76
|
+
end
|
77
|
+
@mutex.synchronize {
|
78
|
+
@running_threads -= 1
|
79
|
+
#puts "finished thread, running=#{@running_threads}"
|
80
|
+
}
|
81
|
+
}
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def wait(timeout_limit = 100)
|
87
|
+
#for thread in @threads
|
88
|
+
@mutex.synchronize {
|
89
|
+
@condvar.broadcast
|
90
|
+
}
|
91
|
+
#end
|
92
|
+
#while @running_threads > 0
|
93
|
+
# @mutex.synchronize {
|
94
|
+
# @condvar.signal
|
95
|
+
# }
|
96
|
+
# sleep(0.01)
|
97
|
+
#end
|
98
|
+
begin
|
99
|
+
Timeout::timeout(timeout_limit) {
|
100
|
+
for thread in @threads
|
101
|
+
thread.join
|
102
|
+
end
|
103
|
+
}
|
104
|
+
rescue Timeout::Error => te
|
105
|
+
for thread in @threads
|
106
|
+
begin
|
107
|
+
if thread.alive?
|
108
|
+
thread.raise BackgroundQueue::ServerLib::ThreadManager::ForcedStop.new("Timeout when forcing threads to stop")
|
109
|
+
end
|
110
|
+
rescue Exception=>e
|
111
|
+
#ignore
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#Error raised when unable to load configuration
|
118
|
+
class ForcedStop < Exception
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#this is a worker which keeps track of how many connections are getting used by the worker.
|
2
|
+
class BackgroundQueue::ServerLib::Worker
|
3
|
+
|
4
|
+
attr_accessor :uri
|
5
|
+
attr_accessor :connections
|
6
|
+
attr_accessor :offline
|
7
|
+
|
8
|
+
def initialize(uri)
|
9
|
+
@uri = uri
|
10
|
+
@connections = 0
|
11
|
+
@offline = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def offline?
|
15
|
+
@offline
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module BackgroundQueue::ServerLib
|
2
|
+
#make sure each worker gets its fair share of tasks
|
3
|
+
#track the number of active connections to use as the balancing metric
|
4
|
+
class WorkerBalancer
|
5
|
+
|
6
|
+
attr_reader :available_workers
|
7
|
+
attr_reader :offline_workers
|
8
|
+
|
9
|
+
def initialize(server)
|
10
|
+
@server = server
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@offline_workers = []
|
13
|
+
@available_workers = SortedWorkers.new
|
14
|
+
for worker_config in server.config.workers.reverse
|
15
|
+
worker = Worker.new(worker_config.uri)
|
16
|
+
@available_workers.add_worker(worker)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#poll the workers that are marked as offline, and mark them online if the polling succeeded
|
21
|
+
def check_offline
|
22
|
+
|
23
|
+
workers_to_check = @mutex.synchronize { @offline_workers.clone }
|
24
|
+
|
25
|
+
for worker in workers_to_check
|
26
|
+
client = BackgroundQueue::ServerLib::WorkerClient.new(@server)
|
27
|
+
if client.send_request(worker, build_poll_task, @server.config.secret)
|
28
|
+
register_online(worker)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#get the worker with the least number of connections using it
|
34
|
+
def get_next_worker
|
35
|
+
@mutex.synchronize {
|
36
|
+
worker = @available_workers.worker_list.first
|
37
|
+
unless worker.nil?
|
38
|
+
register_start(worker)
|
39
|
+
end
|
40
|
+
worker
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def finish_using_worker(worker, online)
|
45
|
+
@mutex.synchronize {
|
46
|
+
if online
|
47
|
+
register_finish(worker)
|
48
|
+
else
|
49
|
+
register_offline(worker)
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def register_start(worker)
|
57
|
+
worker.connections += 1
|
58
|
+
@available_workers.adjust_worker(worker)
|
59
|
+
end
|
60
|
+
|
61
|
+
def register_finish(worker)
|
62
|
+
worker.connections -= 1
|
63
|
+
@available_workers.adjust_worker(worker)
|
64
|
+
end
|
65
|
+
|
66
|
+
def register_offline(worker)
|
67
|
+
worker.connections -= 1
|
68
|
+
unless worker.offline?
|
69
|
+
worker.offline = true
|
70
|
+
@available_workers.remove_worker(worker)
|
71
|
+
@offline_workers << worker
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def register_online(worker)
|
76
|
+
if worker.offline?
|
77
|
+
worker.offline = false
|
78
|
+
@offline_workers.delete(worker)
|
79
|
+
@available_workers.add_worker(worker)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_poll_task
|
84
|
+
if @poll_task.nil?
|
85
|
+
@poll_task = BackgroundQueue::ServerLib::Task.new(:owner_id, :job_id, :id, 1, :poll_worker, {}, @server.config.system_task_options)
|
86
|
+
@poll_task.set_job(BackgroundQueue::ServerLib::NullJob.new)
|
87
|
+
end
|
88
|
+
@poll_task
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class NullJob
|
93
|
+
def set_worker_status(status)
|
94
|
+
#do nothing
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module BackgroundQueue::ServerLib
|
5
|
+
#The client to a worker.
|
6
|
+
#Use http to connect to the worker, send the command, and process the streamed response of json encoded status updates.
|
7
|
+
class WorkerClient
|
8
|
+
def initialize(server)
|
9
|
+
@server = server
|
10
|
+
end
|
11
|
+
|
12
|
+
#send a request to the specified worker, passing the task and authenticating using the secret
|
13
|
+
def send_request(worker, task, secret)
|
14
|
+
@current_task = task
|
15
|
+
req = build_request(worker.uri, task, secret)
|
16
|
+
begin
|
17
|
+
Net::HTTP.start(worker.uri.host, worker.uri.port) do |server|
|
18
|
+
server.request(req) do |response|
|
19
|
+
read_response(worker, response, task)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
true
|
23
|
+
rescue Exception=>e
|
24
|
+
@server.logger.error("Error sending request #{task.id} to worker: #{e.message}")
|
25
|
+
@server.logger.debug(e.backtrace.join("\n"))
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def build_request(uri, task, secret)
|
33
|
+
req = Net::HTTP::Post.new(uri.path)
|
34
|
+
req.set_form_data({:task=>task.to_json, :auth=>secret, :server_port=>@server.config.address.port})
|
35
|
+
req["host"] = task.domain
|
36
|
+
req
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
def read_response(worker, http_response, task)
|
42
|
+
if http_response.code == "200"
|
43
|
+
http_response.read_body do |chunk|
|
44
|
+
process_chunk(chunk, task)
|
45
|
+
end
|
46
|
+
#the last chunk did not end in a newline... process it
|
47
|
+
unless @prev_chunk.nil?
|
48
|
+
process_line(@prev_chunk.strip, task)
|
49
|
+
@prev_chunk = nil
|
50
|
+
end
|
51
|
+
else
|
52
|
+
raise "Invalid response code (#{http_response.code}) when calling #{worker.uri.to_s}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def process_chunk(chunk, task)
|
57
|
+
#puts "process_chunk: #{chunk}"
|
58
|
+
chunk.each_line do |line|
|
59
|
+
unless @prev_chunk.nil?
|
60
|
+
line = @prev_chunk + line
|
61
|
+
@prev_chunk = nil
|
62
|
+
end
|
63
|
+
if line[-1,1] == "\n" #it ends in a newline so its a complete line
|
64
|
+
process_line(line.strip, task)
|
65
|
+
else
|
66
|
+
@prev_chunk = line
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_line(line, task)
|
72
|
+
hash_data = nil
|
73
|
+
begin
|
74
|
+
hash_data = JSON.load(line)
|
75
|
+
if hash_data.kind_of?(Hash)
|
76
|
+
set_worker_status(hash_data, task)
|
77
|
+
else
|
78
|
+
raise "Invalid Status Line (wrong datatype: #{hash_data.class.name}"
|
79
|
+
end
|
80
|
+
true
|
81
|
+
rescue Exception=>e
|
82
|
+
@server.logger.error("Error processing status line of task #{task.id}: #{e.message}")
|
83
|
+
@server.logger.debug(e.backtrace.join("\n"))
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def set_worker_status(status, task)
|
89
|
+
status_map = BackgroundQueue::Utils::AnyKeyHash.new(status)
|
90
|
+
task.set_worker_status(status_map)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|