質問

My code like this:

class MessagesController < ApplicationController
@@m = Mutex.new
def index
 @@m.synchronize do
   Message.transaction do
     m = Message.find_by_msg_id(params[:msg_id])
     if m.nil?
       mess = Message.new(:msg_id => params[:msg_id], ......)
       mess.save!
       ......
     end
   end
 end
end
end

Now the question is messages in the database still have the same msg_id. Please help me...

役に立ちましたか?

解決

It all depends on how you run your server - rails runs as a single threaded app with most servers. There are servers (like passenger) which run the server as multi process, which means that concurrency is achieved by running more than one service. On greater scale - instances might be running on a cluster (different machines).

In all those cases, creating a Mutex will not achieve what you are looking for. The scope of the Mutex you created is within the same process.

To make sure you don't have the same msg_id in the db, you must make the validation in the db (like using a unique column, use stored procedures, etc.)

他のヒント

What Uri Agassi said,

for most cases a simple unique validator in rails will do and a unique constraint will just give you more headaches if applied by default since they can cause regressions on the database level,

however, for the rest 1% of cases only way to handle this reliably is with a unique constraint in the database. Basically:

  1. put a unique constraint on the msg_id column
  2. try to insert two of same msg_id through console, see what kind of exception occurs, note the exception class and the exception message, figure out how to distinguish msg_id unique constraint errors from other unique constraint errors
  3. and then make a rescue block for it that does an update or something in those lines

Step 3 on Oracle for example means you need to rescue the appropriate exception class and then check if the exception message matches the name of the unique constraint of the column in question, for example e.message =~ /I_MSG_ID_UNIQUE_CONSTRAINT/

The exact code will depend on the database in question, but its pretty much this workflow

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top