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! | ... | ... |