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.
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.
flock(File::LOCK_EX|File::LOCK_NB)
returns false
. For docs, see ri File.flock
. –
Hassiehassin 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.
You could use a background job scheduler to do the actual work, for example delayed_job (http://github.com/tobi/delayed_job).
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.
© 2022 - 2024 — McMap. All rights reserved.