2012-09-08 23 views
6

Estoy haciendo una pequeña aplicación de sinatra. Realiza un par de llamadas a Redis, devuelve los datos y luego realiza una llamada final a Redis para guardar las "estadísticas".¿Cómo enviar una respuesta pero continuar la ejecución en Sinatra?

Hasta ahora si quiero cancelar la solicitud temprana (basado en la entrada), encontré que puedo usar halt:

# code code 
halt send_blank if is_blocked? SETTINGS, host 
# code code 

Al final quiero tener algo como esto:

response.body = JSON.generate(outgoing) 
# update user 
STATISTICS.hset('u:' + userID, 'data', JSON.generate({'ip' => request.ip, 'time' => Time.now.to_f.to_s})) 

¿Es posible enviar la respuesta y ENTONCES hacer la escritura de redis 5ms, para que el cliente no tenga que esperar? No importa dónde o cómo coloque las estadísticas finales redis call, retrasa el envío de la respuesta por algunos ms - no se puede engañar a sinatra.

Esto se puede realizar fácilmente en Nodo, pero simplemente escribiendo lo que quiero hacer y se disparará después de que se haya enviado la respuesta; Por lo que yo sé, el código aquí bloqueará la ejecución durante aproximadamente 5 ms antes de disparar una respuesta.

He intentado utilizar después de ... hacer filtros, y funcionarían bien, excepto que no se les puede pasar nada más que los datos en response.body, lo que significa que no se puede pasar al filtro nada que no sea va a salir! Es posible evitar este problema asignando variables fuera del alcance de la publicación ("/"); sin embargo, con más de 100 solicitudes por segundo, espero que pueda ver cómo el intercambio de datos a través de "globales" puede convertirse en un gran problema .

Parece algo realmente simple pero no puedo encontrar nada mejor que después ... hacer los filtros en los documentos.

¿Puedo crear un hilo o algo para que el proceso redis.hset() no sea bloqueante, funcionará? Parece que lo pirateó duro.

Gracias!

Respuesta

2

Bifurcar la escritura redis debería funcionar.

Algo como esto:

response.body = JSON.generate(outgoing) 
fork do 
    # update user 
    redis = Redis.new(:host => "your_host_name", :port => your_port_number) 
    redis.hset('u:' + userID, 'data', JSON.generate({'ip' => request.ip, 'time' => Time.now.to_f.to_s})) 
end 
+0

bifurca parece fallo en Sinatra en heroku: *** *** glibc detectado rubí: doble liberación o corrupción (Ant): 0x0000000003824b20 *** aplicación [ web.1]: ======= Backtrace: ========= aplicación [web.1]: /lib/libc.so.6(+0x775b6)[0x7fef9d8385b6] aplicación [web .1]: /lib/libc.so.6(cfree+0x73)[0x7fef9d83ee83] –

+0

¿Has probado con Thread.new, en lugar de fork? –

+0

Enhebrado nativo no está disponible en MRI, solo jRuby y Rubinius. ¿Puedo recomendar Rubinius? –

Cuestiones relacionadas