2013-07-15 2 views
8

Ich verwende eine Kombination von Dragonfly und rack/cache auf Heroku gehostet.Wie können Dateien über 1 MB mit Rack/Cache auf Heroku zwischengespeichert werden?

Ich verwende Dragonfly für hochgeladene Assets. Thumbnails werden on-the-fly verarbeitet und im Rack/Cache für die schnelle Lieferung aus Memcached (über die Memcachier addon) gespeichert.

Reguläre statische Assets werden auch über Rack/Cache in memcached zwischengespeichert.

Mein Problem ist, dass alle hochgeladenen Dateien über 1 MB einen Fehler von 500 in meiner Anwendung verursachen.

2013-07-15T10:38:27.040992+00:00 app[web.1]: DalliError: Value too large, memcached can only store 1048576 bytes per key [key: d49c36d5db74ef45e957cf169a0b27b83b9e84de, size: 1502314] 
2013-07-15T10:38:27.052255+00:00 app[web.1]: cache: [GET /media/BAhbBlsHOgZmSSIdNTA3Njk3ZWFiODBmNDEwMDEzMDAzNjA4BjoGRVQ/WTW_A5Flyer_HealthcareMedicalObsGynae_WEB.pdf] miss, store 
2013-07-15T10:38:27.060583+00:00 app[web.1]: !! Unexpected error while processing request: undefined method `each' for nil:NilClass 

Memcache hat eine Grenze von 1MB, so kann ich verstehen, warum wurde mein Asset nicht im Cache gespeichert, aber ich würde lieber es nicht brechen dienen Vermögen.

Ich bin nicht einmal sicher, woher dieser Fehler kommt. Vermutlich von einem der anderen Rack Middleware?

Das Erhöhen der maximalen Dateigröße scheint keine Auswirkungen zu haben.

config.cache_store = :dalli_store, ENV["MEMCACHIER_SERVERS"].split(","), {¬ 
    :username  => ENV["MEMCACHIER_USERNAME"],¬ 
    :password  => ENV["MEMCACHIER_PASSWORD"],¬ 
    :value_max_bytes => 5242880 # 5MB¬ 
} 

Langzeit, ich weiß, dass weg von Heroku diese Art des Vermögens bewegt, ist ein vernünftiger Schritt, aber das wird nicht eine schnelle Aufgabe.

Was kann ich tun, um diese Assets auf Heroku in der Zwischenzeit fehlerfrei zu beliefern?

Antwort

7

hatte ich das gleiche Problem wie @jordelver und verwaltet rund memcachier die Grenzen zu erhalten, indem Affe Dragonfly::Response Patchen:

module Dragonfly 
    class Response 
    private 
    def cache_headers 
     if job.size > 1048576 
     { 
      "Cache-Control" => "no-cache, no-store", 
      "Pragma" => "no-cache" 
     } 
     else 
     { 
      "Cache-Control" => "public, max-age=31536000", # (1 year) 
      "ETag" => %("#{job.signature}") 
     } 
     end 
    end 
    end 
end 

Wesentlichen, wenn die Größe über 1.048.576 Bytes ist, senden No-Cache-Header.

+0

diese Lösung funktionierte erfolgreich für mich. Vielen Dank! – Francois

+1

FYI es gibt eine API zum Ändern der Header ohne Affe-Patching - siehe http://markevans.github.io/dragonfly/configuration/ ("response_header" Bit) –

9

Also im Gegensatz zu @ Jordelver Frage, finde ich, dass die Einstellung :value_max_bytes Option von Dalli funktioniert. Ich richte Rack :: Cache auf eine etwas andere Weise ein, die vielleicht den Unterschied macht. Diese

ist, was mein production.rb enthält Rack konfigurieren :: Cache:

client = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"], 
          :username => ENV["MEMCACHIER_USERNAME"], 
          :password => ENV["MEMCACHIER_PASSWORD"], 
          :value_max_bytes => 10485760) 
config.action_dispatch.rack_cache = { 
    :metastore => client, 
    :entitystore => client 
} 
config.static_cache_control = "public, max-age=2592000" 

Mit dem oben werden einige Fehler in die Protokolle für Werte über 1 MB gedruckt werden, aber sie werden keine 5xx-Fehler verursachen für den Client, nur ein Cache-Miss.

P.S Ich arbeite für MemCachier :) also sind wir daran interessiert, dies zu klären. Bitte lassen Sie mich wissen, wenn es funktioniert.

+0

Einstellung eines höheren Wertes Wert_max_bytes hat in meinem Fall nicht funktioniert. – Francois

+0

Dies half mir in die richtige Richtung auf ein etwas anderes Problem, so danke David :) – robotmay

+0

Um es auf diese Weise zu tun, müssen Sie Rack-Cache-Juwel installieren. Normalerweise schaltet man dalli in 'environments/development.rb' ein, indem man' config.cache_store =: dalli_store' hinzufügt.Können Sie hier den Wert_max_bytes angeben? Danke –

0

Mein application.js war zu groß für rack-cache so habe ich:

# in config/environments/development.rb 
config.action_dispatch.rack_cache = { 
    metastore: 'file:/var/cache/rack/meta', 
    entitystore: 'file:tmp/cache/rack/body' 
} 

Und es funktioniert!

Speichert Metadaten in Memcache, aber tatsächliche Datei im Dateisystem und nicht im Speicher.

+1

Dies ist keine gute Idee, wenn Sie auf Heroku als laufen Dynos teilen sich den Metastore, aber nicht das Dateisystem. Dies bedeutet, dass Ihre Datei manchmal im Cache gespeichert wird, aber nicht im Dateisystem vorhanden ist und nicht gefunden wird. – jordelver

+0

Empfehlen Sie die Speicherung von Dateien in Memcache? – Dorian

+0

Und BTW, das ist für 'development.rb' – Dorian

Verwandte Themen