1

The scenario I'm facing is as follows:

Each user can click a button and enter a queue, called "waiting room". Once there are n users in this queue, this n users should be grouped together and ejected from this queue.

The implementation I have:

I used a non-persistent model containing a ruby set to serve the purpose. user_id can be added to the set. It works fine when users enter the queue in sequence.

The possible problem:

If the website is under heavy load such as 1000 (> n) users are entering the queue at the same time, I'm afraid bad things will happen (like some users get tied to multiple groups and ejected multiple times). I don't know if Rails has some internal mechanism to prevent this or it depends on the data structure of my choice. I want something like a event queue that web browsers have. That is, events can come in at the same time but only get handled one by one. How do I ensure that?

Testing:

How do I write RSpec tests to simulate the heavy load scenario?

Joe
  • 41,484
  • 20
  • 104
  • 125
Xiaohong Deng
  • 135
  • 2
  • 12
  • 1
    Do you have a singular persistent background process that can handle this or are you depending on your database to do the grouping? If it's a database solution you're looking for you can use transactions to avoid race conditions. – tadman Jan 08 '18 at 19:07
  • Have you looked at this answer: https://stackoverflow.com/a/1815876/1249891 – Jacob Vanus Jan 08 '18 at 19:18
  • @tadman I didn't write any code to spawn a background process. The logic goes into a ActionCable `channel`. If number of in-queue users reaches n, it will call the corrsponding model to create and store a record that represent the group of users to database. Do you have any suggested examples similar to this and solutions that I can read on? – Xiaohong Deng Jan 08 '18 at 19:34
  • 1
    Avoiding race conditions usually means adding a queue and forcing them through a single process, or using a lock to prevent duplication. Either solution should work. – tadman Jan 08 '18 at 19:36
  • Possible duplicate of [Synchronized Method for concurrency in Ruby](https://stackoverflow.com/questions/14090731/synchronized-method-for-concurrency-in-ruby) – max pleaner Jan 08 '18 at 20:09
  • 1
    look at the example on the [Mutex](https://ruby-doc.org/core-2.2.0/Mutex.html#method-i-synchronize) docs – max pleaner Jan 08 '18 at 20:11
  • Thanks guys. Both tadman and @maxpleaner comments made snese to me. I'd be appreciated if someone can add some info about how to reproduce the scenario in RSpec. – Xiaohong Deng Jan 08 '18 at 20:28
  • @XiaohongDeng kinda hard to reproduce race conditions on demand, but you could try testing with a lot of runs – max pleaner Jan 08 '18 at 22:37
  • @XiaohongDeng this could help -> https://github.com/2rba/Race-Conditions-Rspec-HowTo/blob/f078c6ab27/spec/models/key_value_spec.rb. They wrote a helper to help reproduce race conditions. Also, a video of it(albeit in Russian), is here https://www.youtube.com/watch?v=eZG198z4e7I (the code is in English) – Kaka Ruto Feb 23 '21 at 21:34

0 Answers0