Commit 46ba67eb2b514c47f5b3de7e4ddffaf4ab2d30d9
1 parent
09952f2a
Exists in
master
and in
7 other branches
Process ranking in an async job
Showing
5 changed files
with
100 additions
and
7 deletions
Show diff stats
lib/proposals_discussion_plugin.rb
| @@ -52,4 +52,7 @@ class ProposalsDiscussionPlugin < Noosfero::Plugin | @@ -52,4 +52,7 @@ class ProposalsDiscussionPlugin < Noosfero::Plugin | ||
| 52 | [ProposalsDiscussionPlugin::API] | 52 | [ProposalsDiscussionPlugin::API] |
| 53 | end | 53 | end |
| 54 | 54 | ||
| 55 | + # schedule ranking job in initialization process | ||
| 56 | + ProposalsDiscussionPlugin::RankingJob.new.schedule | ||
| 57 | + | ||
| 55 | end | 58 | end |
lib/proposals_discussion_plugin/api.rb
| @@ -5,13 +5,9 @@ class ProposalsDiscussionPlugin::API < Grape::API | @@ -5,13 +5,9 @@ class ProposalsDiscussionPlugin::API < Grape::API | ||
| 5 | paginate per_page: 10, max_per_page: 20 | 5 | paginate per_page: 10, max_per_page: 20 |
| 6 | get ':id/ranking' do | 6 | get ':id/ranking' do |
| 7 | article = find_article(environment.articles, params[:id]) | 7 | article = find_article(environment.articles, params[:id]) |
| 8 | - ranking = Rails.cache.fetch("#{article.cache_key}/proposals_ranking", expires_in: 30.minutes) do | ||
| 9 | - #FIXME call update_ranking in an async job | ||
| 10 | - article.update_ranking | ||
| 11 | - {:proposals => article.ranking, :updated_at => DateTime.now} | ||
| 12 | - end | ||
| 13 | - ranking[:proposals] = paginate ranking[:proposals] | ||
| 14 | - ranking | 8 | + current_page = paginate(article.ranking) |
| 9 | + #FIXME find a better way to get updated_at date | ||
| 10 | + {:proposals => current_page, :updated_at => current_page.blank? ? DateTime.now : current_page.first.updated_at} | ||
| 15 | end | 11 | end |
| 16 | 12 | ||
| 17 | post ':id/propose' do | 13 | post ':id/propose' do |
| @@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
| 1 | +class ProposalsDiscussionPlugin::RankingJob | ||
| 2 | + | ||
| 3 | + def perform | ||
| 4 | + ProposalsDiscussionPlugin::Topic.find_each do |topic| | ||
| 5 | + ProposalsDiscussionPlugin::RankingJob::TopicRankingJob.new(topic.id).schedule | ||
| 6 | + end | ||
| 7 | + schedule(30.minutes.from_now) | ||
| 8 | + end | ||
| 9 | + | ||
| 10 | + def schedule(run_at = nil) | ||
| 11 | + Delayed::Job.enqueue(self, {:run_at => run_at}) unless self.class.find_job.exists? | ||
| 12 | + end | ||
| 13 | + | ||
| 14 | + def self.find_job | ||
| 15 | + Delayed::Job.by_handler("--- !ruby/object:ProposalsDiscussionPlugin::RankingJob {}\n") | ||
| 16 | + end | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + class TopicRankingJob < Struct.new(:topic_id) | ||
| 20 | + | ||
| 21 | + def perform | ||
| 22 | + topic = ProposalsDiscussionPlugin::Topic.find_by_id(topic_id) | ||
| 23 | + topic.update_ranking if topic.present? | ||
| 24 | + end | ||
| 25 | + | ||
| 26 | + def schedule | ||
| 27 | + Delayed::Job.enqueue(self) unless find_job.exists? | ||
| 28 | + end | ||
| 29 | + | ||
| 30 | + def find_job | ||
| 31 | + Delayed::Job.by_handler("--- !ruby/struct:ProposalsDiscussionPlugin::RankingJob::TopicRankingJob\ntopic_id: #{topic_id}\n") | ||
| 32 | + end | ||
| 33 | + | ||
| 34 | + end | ||
| 35 | + | ||
| 36 | +end |
test/unit/api_test.rb
| @@ -30,10 +30,12 @@ class APITest < ActiveSupport::TestCase | @@ -30,10 +30,12 @@ class APITest < ActiveSupport::TestCase | ||
| 30 | 2.times { Vote.create!(:voteable => proposal3, :voter => nil, :vote => 1) } | 30 | 2.times { Vote.create!(:voteable => proposal3, :voter => nil, :vote => 1) } |
| 31 | 31 | ||
| 32 | proposal1.update_attribute(:hits, 5) | 32 | proposal1.update_attribute(:hits, 5) |
| 33 | + process_delayed_job_queue | ||
| 33 | 34 | ||
| 34 | get "/api/v1/proposals_discussion_plugin/#{topic.id}/ranking?#{params.to_query}" | 35 | get "/api/v1/proposals_discussion_plugin/#{topic.id}/ranking?#{params.to_query}" |
| 35 | json = JSON.parse(last_response.body) | 36 | json = JSON.parse(last_response.body) |
| 36 | assert_equal [proposal2.abstract, proposal3.abstract, proposal1.abstract], json['proposals'].map {|p| p['abstract']} | 37 | assert_equal [proposal2.abstract, proposal3.abstract, proposal1.abstract], json['proposals'].map {|p| p['abstract']} |
| 38 | + assert json['updated_at'].to_datetime <= Time.now | ||
| 37 | end | 39 | end |
| 38 | 40 | ||
| 39 | should 'suggest article children' do | 41 | should 'suggest article children' do |
| @@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
| 1 | +require_relative '../test_helper' | ||
| 2 | + | ||
| 3 | +class RankingJobTest < ActiveSupport::TestCase | ||
| 4 | + | ||
| 5 | + def setup | ||
| 6 | + @job = ProposalsDiscussionPlugin::RankingJob.new | ||
| 7 | + @topic = fast_create(ProposalsDiscussionPlugin::Topic) | ||
| 8 | + @proposal = fast_create(ProposalsDiscussionPlugin::Proposal, :parent_id => topic.id) | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + attr_accessor :job, :topic, :proposal | ||
| 12 | + | ||
| 13 | + should 'create ranking job in initialization' do | ||
| 14 | + assert job.class.find_job.exists? | ||
| 15 | + end | ||
| 16 | + | ||
| 17 | + should 'do not create duplicated ranking job' do | ||
| 18 | + job.schedule | ||
| 19 | + job.schedule | ||
| 20 | + assert_equal 1, job.class.find_job.count | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + should 'schedule topic jobs when performed' do | ||
| 24 | + job.perform | ||
| 25 | + assert ProposalsDiscussionPlugin::RankingJob::TopicRankingJob.new(topic.id).find_job.exists? | ||
| 26 | + end | ||
| 27 | + | ||
| 28 | + should 'reschedule job when performed' do | ||
| 29 | + process_delayed_job_queue | ||
| 30 | + job.perform | ||
| 31 | + new_job = job.class.find_job.first | ||
| 32 | + assert new_job.present? | ||
| 33 | + assert new_job.run_at > 20.minutes.from_now | ||
| 34 | + end | ||
| 35 | + | ||
| 36 | + should 'schedule topic job' do | ||
| 37 | + topic_job = ProposalsDiscussionPlugin::RankingJob::TopicRankingJob.new(topic.id) | ||
| 38 | + topic_job.schedule | ||
| 39 | + assert topic_job.find_job.exists? | ||
| 40 | + end | ||
| 41 | + | ||
| 42 | + should 'do not schedule duplicated topic job' do | ||
| 43 | + topic_job = ProposalsDiscussionPlugin::RankingJob::TopicRankingJob.new(topic.id) | ||
| 44 | + topic_job.schedule | ||
| 45 | + topic_job.schedule | ||
| 46 | + assert_equal 1, topic_job.find_job.count | ||
| 47 | + end | ||
| 48 | + | ||
| 49 | + should 'perform topic job' do | ||
| 50 | + job.schedule | ||
| 51 | + assert_equal 0, topic.ranking.count | ||
| 52 | + process_delayed_job_queue | ||
| 53 | + assert_equal 1, topic.ranking.count | ||
| 54 | + end | ||
| 55 | + | ||
| 56 | +end |