Leer y escribir archivos atómicamente.

Me gustaría leer y escribir un archivo de forma atómica en Ruby entre varios procesos de Ruby independientes (no hilos).

  • Encontré atomic_write de ActiveSupport. Esto se escribe en un archivo temporal, luego se mueve sobre el original y establece todos los permisos. Sin embargo, esto no impide que el archivo se lea mientras se está escribiendo.
  • No he encontrado ningún atomic_read . (¿Las lecturas de archivos ya son atómicas?)

¿Debo implementar mi propio archivo de ‘locking’ separado que compruebo antes de leer y escribir? ¿O hay un mecanismo mejor ya presente en el sistema de archivos para marcar un archivo como ‘ocupado’ que podría verificar antes de cualquier lectura / escritura?


La motivación es tonta, pero se incluye aquí porque vas a preguntar al respecto.

Tengo una aplicación web que utiliza Sinatra y que Thin me sirve, que (por sus propias razones) utiliza un archivo JSON como “base de datos”. Cada solicitud al servidor lee la última versión del archivo, realiza los cambios necesarios y escribe los cambios en el archivo.

Esto estaría bien si solo tuviera una única instancia del servidor en ejecución. Sin embargo, estaba pensando en tener varias copias de Thin ejecutándose detrás de un proxy inverso de Apache. Estos son procesos discretos de Ruby, y por lo tanto se ejecutan verdaderamente en paralelo.

Tras una reflexión más profunda, me doy cuenta de que realmente quiero hacer que el acto de lectura-proceso-escritura sea atómico. En ese punto, me doy cuenta de que esto básicamente me obliga a procesar solo una solicitud a la vez, y por lo tanto no hay razón para tener varias instancias en ejecución. Pero la curiosidad sobre las lecturas atómicas, y la prevención de lecturas durante la escritura, permanece. De ahí la pregunta.

Quieres usar File#flock en modo exclusivo. Aquí hay una pequeña demostración. Ejecutar esto en dos ventanas de terminal diferentes.

 filename = 'test.txt' File.open(filename, File::RDWR) do |file| file.flock(File::LOCK_EX) puts "content: #{file.read}" puts 'doing some heavy-lifting now' sleep(10) end 

Eche un vistazo a transaction métodos de transaction y open_and_lock_file en “pstore.rb” (Ruby stdlib).

YAML::Store funciona bien para mí. Entonces, cuando necesito leer / escribir de forma atómica, lo (ab) lo uso para almacenar datos como un Hash .

    Intereting Posts