How to Synchronize?

Hi,

I am developing a web based game in which people try to guess the
concealed word in a collaborative manner.

As you already take for granted, I use ruby on rails on the server side.

But I have a problem, I synchronize the method which arranges games and
informs the users using a Mutex. Though I didn’t tested heavily, it
seemed to work on the development server. But when I deployed the
project onto the production server, it seems that it’s not functioning
(or there may be some other problem)

On the development, I use a mongrel server, which I start on the command
line (script/server -b bla bla -p 3000)

On the production server, I use Passenger with the default settings.

First I suspected that this problem is originating because Passenger was
spawning processes and they are not sharing the mutex. But I checked the
documentation but couldn’t find a mention of it. And in this link
(http://m.onkey.org/2008/10/23/thread-safety-for-your-rails) it says
that it’s OK to use Mutexes (though not mentioning the multiprocess
passenger).

What do you think the problem is about? I am posting a code snippet
which exemplifies my usage of Mutexes.

Here is the relevant versions:

Production:

Passenger: 2.2.2
Apache: 2.2.8-1ubuntu0.9

About your application’s environment
Ruby version 1.8.6 (x86_64-linux)
RubyGems version 1.3.1
Rack version 1.0 bundled
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Edge Rails revision unknown
Application root XXXX
Environment development
Database adapter mysql

Development:

About your application’s environment
Ruby version 1.8.7 (i486-linux)
RubyGems version 1.3.1
Rack version 1.0 bundled
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Edge Rails revision unknown
Application root XXXX
Environment development
Database adapter mysql
Database schema version 20090701025248

Here is the code:

def GameControl

@@semaphore = Mutex.new

def GameControl.start_game(user, singlegame = false)

@@semaphore.synchronize {

do the stuff here which I want to be processed by only one at a

time.

}

end

end

Hi,

I don’t really know whether it’s appropriate to re-post a message. But I
think I asked my question in a proper way, and would like to re-post to
eliminate the chance of missing the right people for this question.

Here is the original message:


Onur G. wrote:

Hi,

I am developing a web based game in which people try to guess the
concealed word in a collaborative manner.

As you already take for granted, I use ruby on rails on the server side.

But I have a problem, I synchronize the method which arranges games and
informs the users using a Mutex. Though I didn’t tested heavily, it
seemed to work on the development server. But when I deployed the
project onto the production server, it seems that it’s not functioning
(or there may be some other problem)

On the development, I use a mongrel server, which I start on the command
line (script/server -b bla bla -p 3000)

On the production server, I use Passenger with the default settings.

First I suspected that this problem is originating because Passenger was
spawning processes and they are not sharing the mutex. But I checked the
documentation but couldn’t find a mention of it. And in this link
(http://m.onkey.org/2008/10/23/thread-safety-for-your-rails) it says
that it’s OK to use Mutexes (though not mentioning the multiprocess
passenger).

What do you think the problem is about? I am posting a code snippet
which exemplifies my usage of Mutexes.

Here is the relevant versions:

Production:

Passenger: 2.2.2
Apache: 2.2.8-1ubuntu0.9

About your application’s environment
Ruby version 1.8.6 (x86_64-linux)
RubyGems version 1.3.1
Rack version 1.0 bundled
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Edge Rails revision unknown
Application root XXXX
Environment development
Database adapter mysql

Development:

About your application’s environment
Ruby version 1.8.7 (i486-linux)
RubyGems version 1.3.1
Rack version 1.0 bundled
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Edge Rails revision unknown
Application root XXXX
Environment development
Database adapter mysql
Database schema version 20090701025248

Here is the code:

def GameControl

@@semaphore = Mutex.new

def GameControl.start_game(user, singlegame = false)

@@semaphore.synchronize {

do the stuff here which I want to be processed by only one at a

time.

}

end

end

Frederick C. wrote:

On Jul 2, 11:10�am, Onur G. [email protected]
wrote:

First I suspected that this problem is originating because Passenger was
spawning processes and they are not sharing the mutex. But I checked the
documentation but couldn’t find a mention of it. And in this link
(http://m.onkey.org/2008/10/23/thread-safety-for-your-rails) it says
that it’s OK to use Mutexes (though not mentioning the multiprocess
passenger).

Mutexes aren’t for cross process synchronisation (unlike a mutex in
windows which can be shared across processes).

Fred

OK. Then it means Mutex’es don’t work in a multi-process Passenger
setup.

But then how can I synchronize this method’s usage? I am very new to web
development so I just heard about database locking.

Simply, how should I use the
ActiveRecord::Transactions::ClassMethods#transaction and
ActiveRecord::Base#lock!?

Would it be OK to create a model and its corresponding table for just
locking? i.e. Lock model and locks table.

Then use them like this:

Lock.transaction do

lock = Lock.find(1)
lock.lock!

do my stuff which should be done by only one process at a time.

end

Thanks,
Onur

On Jul 5, 12:04 pm, Onur G. [email protected]
wrote:

Would it be OK to create a model and its corresponding table for just
locking? i.e. Lock model and locks table.

That or rails’ optimistic locking might be useful. I would usually shy
away from creating a Lock model, it just seems a bit artificial. I
would probably stick a locked_by_foo column on the appropriate model
and use that to tell whether a particular object is being updated (and
use optimistic locking in conjunction with that)

Fred

On Jul 2, 11:10 am, Onur G. [email protected]
wrote:

First I suspected that this problem is originating because Passenger was
spawning processes and they are not sharing the mutex. But I checked the
documentation but couldn’t find a mention of it. And in this link
(http://m.onkey.org/2008/10/23/thread-safety-for-your-rails) it says
that it’s OK to use Mutexes (though not mentioning the multiprocess
passenger).

Mutexes aren’t for cross process synchronisation (unlike a mutex in
windows which can be shared across processes).

Fred

Would it be OK to create a model and its corresponding table for just
locking? i.e. Lock model and locks table.

That would be pointless. If you wrap your DB operations in a
transaction, you will automatically get the appropriate locks – and the
DB will keep track of them, so you don’t have to.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Yes, I got your point.

But I think that the situation is not that clear. I don’t know a single
model to have a transaction open and be safe after.

So you might be right if I had a design which kept that in mind right
from the beginning. But -at least as a workaround- I need something like
that.

A moment ago, I found this:

This is pretty much the functionality I require.

I think I will use this.

Didn’t anybody require anything like this?

Thanks
Onur

Frederick C. wrote:

On Jul 5, 12:04�pm, Onur G. [email protected]
wrote:

Would it be OK to create a model and its corresponding table for just
locking? i.e. Lock model and locks table.

That or rails’ optimistic locking might be useful. I would usually shy
away from creating a Lock model, it just seems a bit artificial. I
would probably stick a locked_by_foo column on the appropriate model
and use that to tell whether a particular object is being updated (and
use optimistic locking in conjunction with that)

Fred

Thanks for your response,

But as I told in my post replying Marnen, I just don’t know which
objects to lock (or because there are several of them).

So I will use the Lock model approach for now.

Thanks for all your answers, Best
Onur

Onur G. wrote:
[…]

But I think that the situation is not that clear. I don’t know a single
model to have a transaction open and be safe after.

That sentence is unclear, but I think you’re saying that the transaction
doesn’t fit neatly into any one model. Right?

If so, then don’t worry: it doesn’t have to. Transactions affect the
whole DB connection, not just one table. If you need to create a
separate class to house a multitable transaction, you can do that, but
there’s no need to make that class inherit from ActiveRecord or give it
a DB table.

So you might be right if I had a design which kept that in mind right
from the beginning.

If your code is telling you that it needs to be refactored, then
refactor it instead of kludging around it!

But -at least as a workaround- I need something like
that.

Take the time to do it right if possible rather than relying on
workarounds.

A moment ago, I found this:

Kurtis Seebaldt: Synchronizing using Active Record

This is pretty much the functionality I require.

I think I will use this.

I’ll look at that. But if that comes from November 2007 as the URL
implies, it is liable to be out of date: I believe the current Rails
version at that time was 1.2.6.

Didn’t anybody require anything like this?

Thanks
Onur

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Onur G. wrote:
[…]

But then how can I synchronize this method’s usage? I am very new to web
development so I just heard about database locking.

Simply, how should I use the
ActiveRecord::Transactions::ClassMethods#transaction and
ActiveRecord::Base#lock!?

Would it be OK to create a model and its corresponding table for just
locking? i.e. Lock model and locks table.

That would be pointless. If you wrap your DB operations in a
transaction, you will automatically get the appropriate locks – and the
DB will keep track of them, so you don’t have to.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]