Die Amazon-Api durchgängig nur 1-mal pro Sekunde anzusprechen führt natürlich dazu, dass die Anwendung nun deutlich länger braucht. Denn vorher wurden Anfragen so schnell losgeschickt wie möglich, und diese Bursts tolerierte Amazon – nur eben nicht immer und nicht zuverlässig. Daher brauchte es einen Weg, weniger Anfragen zu benutzen und so wieder akzeptable Geschwindigkeiten hinzukriegen.
Naheliegende Lösung war, Amazons Apiantworten für eine Weile zu cachen. Statt über SQLite zu funktionieren sollte dieser Cache jedoch im Speicher liegen. Genau das tut LruRedux, ist thread-safe und hat dazu einige nette Funktionen, beispielsweise ebenfalls eine Time-To-Live-Variante.
require 'lru_redux'
class Amazon
def initialize()
begin
@@cache
rescue
@@cache = LruRedux::TTL::ThreadSafeCache.new(200, 86400) # 24h
…
end
end
def getOffer(hardware)
return @@cache.getset(hardware.type) do
…
self.search(hardware.type)
end
end
end
Die getset-Methode ist besonders hilfreich. Der übergebene Block wird nur ausgeführt, wenn die id (hardware.type
hier) nicht bereits im Cache ist. Ansonsten wird der Block einmal ausgeführt, sein Ergebnis direkt gecached und zusätzlich noch returned. Ansonsten kann der Cache einfach wie ein Hash benutzt werden – allerdings wie ein Hash, der hier nur 200 Einträge fasst und sie nach 24 Stunden wieder vergisst.
LruRedux ist damit genau das, was ich hier brauchte: Ein pfeilschneller und einfach zu benutzender Cache, den ich als Klassenvariable setzen kann. Wie throttle-queue scheint er hervorragend zu funktionieren.
Ruby habe ich damals angefangen, weil ich Sinatra mochte. Inzwischen mag ich auch die Sprache selbst, aber es ist immer noch das Ökosystem drumherum, das besonders toll ist. Ich hätte sowohl cache als auch queue selbst bauen können, aber es wäre so viel mehr Arbeit und das Endergebnis schlechter gewesen. Ein spezifisches Problem durch kleine hilfreiche Gems zu erschlagen ist immer wieder eine schöne Erfahrung.