Mutex for Rails Processes
Asked Answered
P

4

5

When deploying Rails via Passenger or Mongrel you have multiple instances of the application running. What is the best practice or pattern to establish a mutex on shared resources such as a writing to a local file or to a remote file. I want to ensure two processes are not writing to the same resource at the same time.

Phosphide answered 22/9, 2009 at 16:52 Comment(0)
L
16

If you just need to prevent multiple writers from working with a file simultaneously, you can use the File#flock method to request an exclusive write lock from each process:

fh = File.new("/some/file/path")
begin
  fh.flock(File::LOCK_EX)
  # ... write to the file here, or perform some other critical operation
ensure
  fh.flock(File::LOCK_UN)
end

Note: putting the unlock call in an ensure block is important to prevent deadlock if an uncaught exception is thrown after you've locked the file.

Landmass answered 22/9, 2009 at 18:23 Comment(2)
How do we check if file is locked? I want to use file as a global lock, #flock seems fine with me but another process needs to check if it is available, how do I resolve that?Latini
@HarisKrajina, a file is locked if flock(File::LOCK_EX|File::LOCK_NB) returns false. For docs, see ri File.flock.Hassiehassin
P
2

As far as I know, the only way to do this in an environment like this is to use a file-based semaphore - touch a lockfile, do your work, remove the lockfile. Make the process fail if there's a lock on the file.

You could also have a service that writes to the file that is threaded, and make the apps talk to the service to modify the file rather than letting them modify the file directly.

Putrefy answered 22/9, 2009 at 18:4 Comment(0)
D
2

You could use a background job scheduler to do the actual work, for example delayed_job (http://github.com/tobi/delayed_job).

Dufy answered 22/9, 2009 at 18:13 Comment(0)
B
0

If your Rails instances are connected to PostgreSQL, you could use a PostgreSQL Advisory Lock (syntax) (i.e. a lock with an application-defined meaning) as your mutex. You could also just have a locked table record as your flag but:

While a flag stored in a table could be used for the same purpose, advisory locks are faster, avoid table bloat, and are automatically cleaned up by the server at the end of the session.

Other DBs may have similar functionalities.

Barocchio answered 4/5, 2023 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.