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 | 80 | end |
81 | 81 | |
82 | 82 | # adapted from ruby cookbook(2006): section 5-11 |
83 | - def catchup_choose_prompt | |
83 | + def catchup_choose_prompt(num=1000) | |
84 | 84 | weighted = catchup_prompts_weights |
85 | 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 | 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 | 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 | 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 | 106 | end |
104 | 107 | |
105 | 108 | |
... | ... | @@ -472,9 +475,18 @@ class Question < ActiveRecord::Base |
472 | 475 | end |
473 | 476 | |
474 | 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 | 490 | end |
479 | 491 | |
480 | 492 | def pop_prompt_queue | ... | ... |
lib/tasks/test_api.rake
... | ... | @@ -39,7 +39,7 @@ namespace :test_api do |
39 | 39 | 1000.times do |n| |
40 | 40 | puts "#{n} votes completed" if n % 100 == 0 |
41 | 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 | 43 | @appearance = current_user.record_appearance(current_user.default_visitor, @prompt) |
44 | 44 | |
45 | 45 | direction = (rand(2) == 0) ? "left" : "right" | ... | ... |
spec/models/question_spec.rb
... | ... | @@ -55,7 +55,7 @@ describe Question do |
55 | 55 | end |
56 | 56 | |
57 | 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 | 59 | prompt.active?.should == true |
60 | 60 | end |
61 | 61 | |
... | ... | @@ -242,7 +242,7 @@ describe Question do |
242 | 242 | # Sanity check |
243 | 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 | 246 | prompt.active?.should == true |
247 | 247 | end |
248 | 248 | |
... | ... | @@ -282,36 +282,10 @@ describe Question do |
282 | 282 | prompt.should_not == nil |
283 | 283 | prompt.active?.should == true |
284 | 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 | 285 | it "should not return prompts from queue that are deactivated" do |
312 | 286 | @catchup_q.clear_prompt_queue |
313 | 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 | 290 | prompt = Prompt.find(prompt1) |
317 | 291 | prompt.left_choice.deactivate! | ... | ... |