qpush 0.1.2 → 0.1.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.byebug_history +74 -0
  3. data/bin/qpush-server +0 -1
  4. data/bin/qpush-web +7 -1
  5. data/jobs/fail_job.rb +11 -0
  6. data/jobs/test_job.rb +2 -0
  7. data/lib/qpush/config.rb +0 -20
  8. data/lib/qpush/job.rb +11 -7
  9. data/lib/qpush/jobs/queue_delayed.rb +17 -0
  10. data/lib/qpush/redis.rb +36 -0
  11. data/lib/qpush/server.rb +20 -2
  12. data/lib/qpush/server/apis.rb +46 -0
  13. data/lib/qpush/server/apis/delay.rb +37 -0
  14. data/lib/qpush/server/apis/execute.rb +32 -0
  15. data/lib/qpush/server/apis/fail.rb +39 -0
  16. data/lib/qpush/server/apis/history.rb +36 -0
  17. data/lib/qpush/server/apis/morgue.rb +24 -0
  18. data/lib/qpush/server/apis/perform.rb +24 -0
  19. data/lib/qpush/server/apis/queue.rb +24 -0
  20. data/lib/qpush/server/apis/setup.rb +27 -0
  21. data/lib/qpush/server/apis/success.rb +39 -0
  22. data/lib/qpush/server/delay.rb +5 -5
  23. data/lib/qpush/server/errors.rb +1 -16
  24. data/lib/qpush/server/heartbeat.rb +28 -0
  25. data/lib/qpush/server/jobs.rb +10 -55
  26. data/lib/qpush/server/launcher.rb +5 -5
  27. data/lib/qpush/server/loader.rb +38 -0
  28. data/lib/qpush/server/perform.rb +2 -2
  29. data/lib/qpush/server/queue.rb +2 -2
  30. data/lib/qpush/server/worker.rb +1 -0
  31. data/lib/qpush/version.rb +1 -1
  32. data/lib/qpush/web.rb +10 -1
  33. data/lib/qpush/web/apis/crons.rb +34 -0
  34. data/lib/qpush/web/apis/heart.rb +12 -0
  35. data/lib/qpush/web/apis/history.rb +28 -0
  36. data/lib/qpush/web/apis/jobs.rb +26 -0
  37. data/lib/qpush/web/apis/morgue.rb +30 -0
  38. data/lib/qpush/web/apis/queue_delayed.rb +29 -0
  39. data/lib/qpush/web/apis/queued.rb +0 -0
  40. data/lib/qpush/web/apis/retries.rb +40 -0
  41. data/lib/qpush/web/apis/stats.rb +58 -0
  42. data/lib/qpush/web/get.rb +32 -34
  43. data/lib/qpush/web/post.rb +8 -0
  44. data/lib/qpush/web/server.rb +34 -5
  45. data/qpush.gemspec +1 -0
  46. metadata +40 -3
  47. data/lib/qpush/server/execute.rb +0 -100
@@ -14,7 +14,7 @@ module QPush
14
14
  def start
15
15
  until @done
16
16
  job = retrieve_job
17
- job.api.setup if job
17
+ job.setup if job
18
18
  end
19
19
  end
20
20
 
@@ -29,7 +29,7 @@ module QPush
29
29
  # Performs a 'blocking pop' on our redis job list.
30
30
  #
31
31
  def retrieve_job
32
- json = QPush.redis.with { |c| c.brpop(QPush.config.queue_namespace) }
32
+ json = QPush.redis.with { |c| c.brpop(QPush.keys.queue) }
33
33
  Job.new(JSON.parse(json.last))
34
34
  rescue => e
35
35
  raise ServerError, e.message
@@ -56,6 +56,7 @@ module QPush
56
56
  @perform_threads.times { @workers << Perform.new }
57
57
  @queue_threads.times { @workers << Queue.new }
58
58
  @delay_threads.times { @workers << Delay.new }
59
+ @workers << Heartbeat.new
59
60
  end
60
61
 
61
62
  # Information about the start process
@@ -1,4 +1,4 @@
1
1
  module QPush
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.4'
3
3
  CODENAME = 'Sun Soaked Salamander'
4
4
  end
@@ -1,7 +1,16 @@
1
1
  # Base
2
2
  require 'qpush/base'
3
3
 
4
- # Web
4
+ # Web Base
5
5
  require 'sinatra/base'
6
6
  require 'qpush/web/get'
7
7
  require 'qpush/web/server'
8
+
9
+ # Web Apis
10
+ require 'qpush/web/apis/crons'
11
+ require 'qpush/web/apis/heart'
12
+ require 'qpush/web/apis/history'
13
+ require 'qpush/web/apis/jobs'
14
+ require 'qpush/web/apis/morgue'
15
+ require 'qpush/web/apis/retries'
16
+ require 'qpush/web/apis/stats'
@@ -0,0 +1,34 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Crons
5
+ def initialize(start, count)
6
+ @jobs = nil
7
+ @start = start ? start.to_i : 0
8
+ @count = count ? count.to_i : 10
9
+ end
10
+
11
+ def call
12
+ retrieve_delays
13
+ filter_crons
14
+ end
15
+
16
+ private
17
+
18
+ def retrieve_delays
19
+ @jobs = QPush.redis.with do |conn|
20
+ conn.zrange(QPush.keys.delay, 0, -1, with_scores: true)
21
+ end
22
+ end
23
+
24
+ def filter_crons
25
+ @jobs.map! do |job|
26
+ hash = JSON.parse(job.first).merge(perform_at: job.last)
27
+ hash['cron'].empty? ? next : hash
28
+ end
29
+ @jobs.compact[@start, @count]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,12 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Heart
5
+ def call
6
+ heart = QPush.redis.with { |c| c.get(QPush.keys.heart) }
7
+ { status: !heart.nil?, namespace: QPush.config.namespace }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class History
5
+ def initialize
6
+ @jobs = nil
7
+ end
8
+
9
+ def call
10
+ retrieve_jobs
11
+ update_jobs
12
+ end
13
+
14
+ private
15
+
16
+ def retrieve_jobs
17
+ @jobs = QPush.redis.with do |conn|
18
+ conn.lrange(QPush.keys.history, 0, 10)
19
+ end
20
+ end
21
+
22
+ def update_jobs
23
+ @jobs.map! { |i| JSON.parse(i) }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Jobs
5
+ def initialize
6
+ @jobs = nil
7
+ end
8
+
9
+ def call
10
+ retrieve_jobs
11
+ update_jobs
12
+ end
13
+
14
+ private
15
+
16
+ def retrieve_jobs
17
+ QPush.redis.with { |c| @jobs = c.smembers("#{QPush.keys.jobs}") }
18
+ end
19
+
20
+ def update_jobs
21
+ @jobs.map! { |job| { klass: job } }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Morgue
5
+ def initialize(start, count)
6
+ @morgue = nil
7
+ @start = start
8
+ @count = count
9
+ end
10
+
11
+ def call
12
+ retrieve_morgue
13
+ update_morgue
14
+ end
15
+
16
+ private
17
+
18
+ def retrieve_morgue
19
+ @morgue = QPush.redis.with do |conn|
20
+ conn.lrange(QPush.keys.morgue, @start, @start + @count)
21
+ end
22
+ end
23
+
24
+ def update_morgue
25
+ @morgue.map! { |i| JSON.parse(i) }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class QueueDelayed
5
+ def initialize(id, score)
6
+ @id = id
7
+ @score = score
8
+ end
9
+
10
+ def call
11
+ QPush.redis.with do |conn|
12
+ @conn = conn
13
+ watch_delay { retrieve_delay }
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def retrieve_delay
20
+ delays = @conn.zrangebyscore(QPush.keys.delay, @score, @score)
21
+ delays.each
22
+
23
+ # Performs a watch on our delay list
24
+ #
25
+ def watch_delay
26
+ @conn.watch(QPush.keys.delay) do
27
+ yield if block_given?
28
+ end
29
+ end
File without changes
@@ -0,0 +1,40 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Retries
5
+ def initialize(start, count)
6
+ @start = start ? start.to_i : 0
7
+ @count = count ? count.to_i : 10
8
+ @jobs = nil
9
+ end
10
+
11
+ def call
12
+ retrieve_jobs
13
+ update_jobs
14
+ trim_jobs
15
+ end
16
+
17
+ private
18
+
19
+ def retrieve_jobs
20
+ @jobs = QPush.redis.with do |conn|
21
+ conn.zrange(QPush.keys.delay, 0, -1, with_scores: true)
22
+ end
23
+ end
24
+
25
+ def update_jobs
26
+ @jobs.map! do |job|
27
+ hash = JSON.parse(job.first, symbolize_names: true).merge(perform_at: job.last)
28
+ next unless hash[:failed]
29
+ hash
30
+ end
31
+ end
32
+
33
+ def trim_jobs
34
+ @jobs.compact!
35
+ @jobs[@start, @count]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,58 @@
1
+ module QPush
2
+ module Web
3
+ module Apis
4
+ class Stats
5
+ DEFAULTS = {
6
+ 'queued' => 0,
7
+ 'success' => 0,
8
+ 'failed' => 0,
9
+ 'performed' => 0,
10
+ 'dead' => 0,
11
+ 'retries' => 0,
12
+ 'delayed' => 0,
13
+ 'current_queue' => 0,
14
+ 'percent_success' => 100.00
15
+ }.freeze
16
+
17
+ def initialize
18
+ @stats = nil
19
+ end
20
+
21
+ def call
22
+ retrieve_stats
23
+ apply_defaults
24
+ calculate_stats
25
+ @stats
26
+ end
27
+
28
+ private
29
+
30
+ def retrieve_stats
31
+ @stats = QPush.redis.with do |conn|
32
+ conn.hgetall(QPush.keys.stats)
33
+ end
34
+ end
35
+
36
+ def apply_defaults
37
+ @stats.each { |k, v| @stats[k] = v.to_i }
38
+ @stats = DEFAULTS.merge(@stats)
39
+ end
40
+
41
+ def calculate_stats
42
+ @stats['percent_success'] = calculate_success
43
+ @stats['current_queue'] = calculate_current
44
+ end
45
+
46
+ def calculate_success
47
+ (100.00 - ((@stats['failed'].to_f / @stats['performed'].to_f) * 100.00)).round(2)
48
+ end
49
+
50
+ def calculate_current
51
+ QPush.redis.with do |c|
52
+ QPush.keys.perform_lists.collect { |list| c.llen(list) }.reduce(:+)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,57 +1,55 @@
1
+ require 'byebug'
2
+
1
3
  module QPush
2
4
  module Web
3
5
  class Get
4
- STATS = [:delayed,
5
- :queued,
6
- :performed,
7
- :retries,
8
- :success,
9
- :failed].freeze
10
-
11
6
  class << self
12
7
  def stats
13
- stats = {}
14
- namespace = QPush.config.stats_namespace
15
- QPush.redis.with do |conn|
16
- STATS.each { |s| stats[s] = conn.get("#{namespace}:#{s}") }
17
- end
18
- stats
8
+ stats = Apis::Stats.new
9
+ stats.call.to_json
19
10
  end
20
11
 
21
- def delays(s, e)
22
- jobs = Get.all_delays[s, e]
23
-
24
- jobs.map! { |job| JSON.parse(job.first).merge(perform_at: job.last) }
12
+ def heartbeat
13
+ heart = Apis::Heart.new
14
+ heart.call.to_json
25
15
  end
26
16
 
27
- def crons(s, e)
28
- jobs = Get.all_delays
17
+ def history
18
+ history = Apis::History.new
19
+ history.call.to_json
20
+ end
29
21
 
30
- jobs.map! do |job|
31
- hash = JSON.parse(job.first).merge(perform_at: job.last)
32
- hash['cron'].empty? ? next : hash
33
- end
22
+ def jobs
23
+ jobs = Apis::Jobs.new
24
+ jobs.call.to_json
25
+ end
34
26
 
35
- jobs.compact![s, e]
27
+ def retries(s, c)
28
+ retries = Apis::Retries.new(s, c)
29
+ retries.call.to_json
30
+ end
36
31
 
37
- { total: jobs.count, jobs: jobs }
32
+ def morgue(s, c)
33
+ morgue = Apis::Morgue.new(s, c)
34
+ morgue.call.to_json
38
35
  end
39
36
 
40
- def fails(s, e)
41
- jobs = Get.all_delays
37
+ def delays(s, e)
38
+ jobs = Get.all_delays[s, e]
42
39
 
43
- jobs.map! do |job|
44
- hash = JSON.parse(job.first).merge(perform_at: job.last)
45
- hash['cron'].empty? && hash['total_fail'] > 0 ? hash : next
46
- end
47
- jobs.compact![s, e]
40
+ jobs.map! { |job| JSON.parse(job.first).merge(perform_at: job.last) }
41
+ end
48
42
 
49
- { total: jobs.count, jobs: jobs }
43
+ def crons(s, c)
44
+ crons = Apis::Crons.new(s, c)
45
+ crons.call.to_json
50
46
  end
51
47
 
48
+
49
+
52
50
  def all_delays
53
51
  QPush.redis.with do |conn|
54
- conn.zrange(QPush.config.delay_namespace, 0, -1, with_scores: true)
52
+ conn.zrange(QPush.keys.delay, 0, -1, with_scores: true)
55
53
  end
56
54
  end
57
55
  end
@@ -0,0 +1,8 @@
1
+ module QPush
2
+ module Web
3
+ class Post
4
+ class << self
5
+ def queue_delayed(id, score)
6
+ queue = Apis::QueueDelayed.new(id)
7
+ queue.call.to_json
8
+ end
@@ -1,24 +1,53 @@
1
1
  module QPush
2
2
  module Web
3
3
  class Server < Sinatra::Base
4
+ set :public_folder, Gem::Specification.find_by_name('qpush').gem_dir + '/lib/qpush/web/public'
5
+
4
6
  before do
7
+ pass if request.path_info == '/'
5
8
  content_type :json
9
+ headers 'Access-Control-Allow-Origin' => '*',
10
+ 'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST']
11
+ end
12
+
13
+ get '/' do
14
+ File.read(File.join(settings.public_folder, 'index.html'))
6
15
  end
7
16
 
8
17
  get '/stats' do
9
- Get.stats.to_json
18
+ Get.stats
19
+ end
20
+
21
+ get '/heartbeat' do
22
+ Get.heartbeat
23
+ end
24
+
25
+ get '/history' do
26
+ Get.history
27
+ end
28
+
29
+ get '/jobs' do
30
+ Get.jobs
31
+ end
32
+
33
+ post '/queue_delayed' do
34
+ Post.queue_delayed(params[:id], params[:score])
10
35
  end
11
36
 
12
37
  get '/delays' do
13
- Get.delays(params[:start].to_i, params[:end].to_i).to_json
38
+ Get.delays(params[:start].to_i, params[:count].to_i).to_json
14
39
  end
15
40
 
16
41
  get '/crons' do
17
- Get.crons(params[:start].to_i, params[:end].to_i).to_json
42
+ Get.crons(params[:start].to_i, params[:count].to_i)
43
+ end
44
+
45
+ get '/retries' do
46
+ Get.retries(params[:start], params[:count])
18
47
  end
19
48
 
20
- get '/fails' do
21
- Get.fails(params[:start].to_i, params[:end].to_i).to_json
49
+ get '/morgue' do
50
+ Get.morgue(params[:start].to_i, params[:count].to_i)
22
51
  end
23
52
  end
24
53
  end