Principia Programmatica

cvm Ars Compilandi & Ars Interpretandi

Multithreading en Ruby

Hace unos dias, necesité la posibilidad de ejecutar varias peticiones a los servicios web de Amazon en paralelo, debido a que hacerlo secuencialmente hubiese consumido demasiado tiempo, y los usuarios últimos, que esperan los resultados tras hacer una petición web, se hubiesen impacientado. Así que resolví averiguar si Ruby me permitiría hacer las diferentes peticiones en paralelo sin complicarme mucho la vida -tengo los temas de concurrencia y regiones críticas algo oxidados. Para mi sorpresa, resultó mucho más fácil de lo que me esperaba:

def AmazonHelper.find_isbn(isbn) reqs=[] ['us', 'uk', 'de', 'fr', 'ca' ,'jp'].each do |loc| reqs.push Thread.new { Request.new(DEVTOKEN, ASSOCIATESID,loc).asin_search(isbn) } end response = reqs.collect { |req| req.value rescue nil } response.compact![0].products[0] end

Como se puede ver, itero sobre una lista de locales y para cada una de ellas creo un nuevo Thread, que guardo en un array (en realidad, lo que guardo es el resultado, como veremos enseguida). El constructor del thread recibe un bloque de código, que es lo que debe ejecutar el mismo thread. El resultado de la ejecución de este código, siguiendo las convenciones de Ruby, es lo que se devuelve al código llamante, por lo que acaba en el array reqs, una vez hayan finalizado todos los threads. A continuación, para cada resultado de ejecución -para cada thread finalizado- le pedimos su valor, que viene a ser el resultado de la petición al web service de Amazon. Puede ser que la petición haya fallado, en cuyo caso obtendremos nil. Entonces, compactamos el array, para eliminar estos nils, y obtenemos como resultado un array con todas aquellas respuestas válidas.

Pages

Categories

Tags