Commit a7431d97424fcbc61b0f4a47bcb055ad6bd5b522
1 parent
92dd57ad
Exists in
master
and in
1 other branch
generate 1000 prompts at once
only generate prompts if cache is less than 90% full
Showing
3 changed files
with
34 additions
and
48 deletions
Show diff stats
app/models/question.rb
@@ -80,26 +80,29 @@ class Question < ActiveRecord::Base | @@ -80,26 +80,29 @@ class Question < ActiveRecord::Base | ||
80 | end | 80 | end |
81 | 81 | ||
82 | # adapted from ruby cookbook(2006): section 5-11 | 82 | # adapted from ruby cookbook(2006): section 5-11 |
83 | - def catchup_choose_prompt | 83 | + def catchup_choose_prompt(num=1000) |
84 | weighted = catchup_prompts_weights | 84 | weighted = catchup_prompts_weights |
85 | # Rand returns a number from 0 - 1, so weighted needs to be normalized | 85 | # Rand returns a number from 0 - 1, so weighted needs to be normalized |
86 | - prompt = nil | ||
87 | - | ||
88 | - until prompt && prompt.active? | ||
89 | - target = rand | ||
90 | - left_choice_id = right_choice_id = nil | ||
91 | - | ||
92 | - weighted.each do |item, weight| | ||
93 | - if target <= weight | ||
94 | - left_choice_id, right_choice_id = item.split(", ") | ||
95 | - break | 86 | + generated_prompts = [] |
87 | + | ||
88 | + num.times do | ||
89 | + prompt = nil | ||
90 | + until prompt && prompt.active? | ||
91 | + target = rand | ||
92 | + left_choice_id = right_choice_id = nil | ||
93 | + | ||
94 | + weighted.each do |item, weight| | ||
95 | + if target <= weight | ||
96 | + left_choice_id, right_choice_id = item.split(", ") | ||
97 | + break | ||
98 | + end | ||
99 | + target -= weight | ||
96 | end | 100 | end |
97 | - target -= weight | 101 | + prompt = prompts.find_or_create_by_left_choice_id_and_right_choice_id(left_choice_id, right_choice_id, :include => [{ :left_choice => :item }, { :right_choice => :item }]) |
98 | end | 102 | end |
99 | - prompt = prompts.find_or_create_by_left_choice_id_and_right_choice_id(left_choice_id, right_choice_id, :include => [{ :left_choice => :item }, { :right_choice => :item }]) | 103 | + generated_prompts.push prompt |
100 | end | 104 | end |
101 | - # check if prompt has two active choices here, maybe we can set this on the prompt level too? | ||
102 | - prompt | 105 | + generated_prompts |
103 | end | 106 | end |
104 | 107 | ||
105 | 108 | ||
@@ -472,9 +475,18 @@ class Question < ActiveRecord::Base | @@ -472,9 +475,18 @@ class Question < ActiveRecord::Base | ||
472 | end | 475 | end |
473 | 476 | ||
474 | def add_prompt_to_queue | 477 | def add_prompt_to_queue |
475 | - prompt = self.catchup_choose_prompt | ||
476 | - $redis.rpush(self.pq_key, prompt.id) | ||
477 | - prompt | 478 | + num_prompts = 1000 |
479 | + # if less than 90% full, regenerate prompts | ||
480 | + if $redis.llen(self.pq_key) < num_prompts * 0.9 | ||
481 | + prompts = self.catchup_choose_prompt(num_prompts) | ||
482 | + # clear list | ||
483 | + $redis.ltrim(self.pq_key, 0, 0) | ||
484 | + $redis.lpop(self.pq_key) | ||
485 | + prompts.each do |prompt| | ||
486 | + $redis.rpush(self.pq_key, prompt.id) | ||
487 | + end | ||
488 | + return prompts | ||
489 | + end | ||
478 | end | 490 | end |
479 | 491 | ||
480 | def pop_prompt_queue | 492 | def pop_prompt_queue |
lib/tasks/test_api.rake
@@ -39,7 +39,7 @@ namespace :test_api do | @@ -39,7 +39,7 @@ namespace :test_api do | ||
39 | 1000.times do |n| | 39 | 1000.times do |n| |
40 | puts "#{n} votes completed" if n % 100 == 0 | 40 | puts "#{n} votes completed" if n % 100 == 0 |
41 | question = Question.find(214) # test question change as needed | 41 | question = Question.find(214) # test question change as needed |
42 | - @prompt = question.catchup_choose_prompt | 42 | + @prompt = question.catchup_choose_prompt(1).first |
43 | @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) | 43 | @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) |
44 | 44 | ||
45 | direction = (rand(2) == 0) ? "left" : "right" | 45 | direction = (rand(2) == 0) ? "left" : "right" |
spec/models/question_spec.rb
@@ -55,7 +55,7 @@ describe Question do | @@ -55,7 +55,7 @@ describe Question do | ||
55 | end | 55 | end |
56 | 56 | ||
57 | it "should choose an active prompt using catchup algorithm" do | 57 | it "should choose an active prompt using catchup algorithm" do |
58 | - prompt = @question.catchup_choose_prompt | 58 | + prompt = @question.catchup_choose_prompt(1).first |
59 | prompt.active?.should == true | 59 | prompt.active?.should == true |
60 | end | 60 | end |
61 | 61 | ||
@@ -242,7 +242,7 @@ describe Question do | @@ -242,7 +242,7 @@ describe Question do | ||
242 | # Sanity check | 242 | # Sanity check |
243 | @catchup_q.choices.size.should == 100 | 243 | @catchup_q.choices.size.should == 100 |
244 | 244 | ||
245 | - prompt = @catchup_q.catchup_choose_prompt | 245 | + prompt = @catchup_q.catchup_choose_prompt(1).first |
246 | prompt.active?.should == true | 246 | prompt.active?.should == true |
247 | end | 247 | end |
248 | 248 | ||
@@ -282,36 +282,10 @@ describe Question do | @@ -282,36 +282,10 @@ describe Question do | ||
282 | prompt.should_not == nil | 282 | prompt.should_not == nil |
283 | prompt.active?.should == true | 283 | prompt.active?.should == true |
284 | end | 284 | end |
285 | - it "should return prompts from the queue in FIFO order" do | ||
286 | - @catchup_q.clear_prompt_queue | ||
287 | - @catchup_q.pop_prompt_queue.should == nil | ||
288 | - | ||
289 | - prompt1 = @catchup_q.add_prompt_to_queue | ||
290 | - prompt2 = @catchup_q.add_prompt_to_queue | ||
291 | - prompt3 = @catchup_q.add_prompt_to_queue | ||
292 | - | ||
293 | - prompt_1 = @catchup_q.pop_prompt_queue | ||
294 | - prompt_2 = @catchup_q.pop_prompt_queue | ||
295 | - prompt_3 = @catchup_q.pop_prompt_queue | ||
296 | - | ||
297 | - | ||
298 | - prompt_1.should == prompt1 | ||
299 | - prompt_2.should == prompt2 | ||
300 | - prompt_3.should == prompt3 | ||
301 | - | ||
302 | - # there is a small probability that the catchup algorithm | ||
303 | - # choose two prompts that are indeed equal | ||
304 | - prompt_1.should_not == prompt_2 | ||
305 | - prompt_1.should_not == prompt_3 | ||
306 | - prompt_2.should_not == prompt_3 | ||
307 | - | ||
308 | - | ||
309 | - @catchup_q.pop_prompt_queue.should == nil | ||
310 | - end | ||
311 | it "should not return prompts from queue that are deactivated" do | 285 | it "should not return prompts from queue that are deactivated" do |
312 | @catchup_q.clear_prompt_queue | 286 | @catchup_q.clear_prompt_queue |
313 | @catchup_q.pop_prompt_queue.should == nil | 287 | @catchup_q.pop_prompt_queue.should == nil |
314 | - prompt1 = @catchup_q.add_prompt_to_queue | 288 | + prompt1 = @catchup_q.add_prompt_to_queue.first |
315 | 289 | ||
316 | prompt = Prompt.find(prompt1) | 290 | prompt = Prompt.find(prompt1) |
317 | prompt.left_choice.deactivate! | 291 | prompt.left_choice.deactivate! |