2013-07-15 9 views
8

Utilizzo una combinazione di Dragonfly e rack/cache ospitata su Heroku.Come memorizzare nella cache i file oltre 1 MB con rack/cache su Heroku?

Sto utilizzando Dragonfly per le risorse caricate. Le anteprime vengono elaborate al volo e archiviate in rack/cache per una rapida consegna da memcached (tramite lo Memcachier addon).

Le risorse statiche regolari sono anche memorizzate nella cache in memcached tramite rack/cache.

Il mio problema è che qualsiasi file caricato oltre 1 MB sta causando un errore 500 nella mia applicazione.

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 ha un limite di 1 MB, quindi posso capire perché la mia attività non è stata memorizzata nella cache, ma avrei preferito non rompere attività a servizio.

Non sono nemmeno sicuro da dove provenga questo errore. Presumibilmente da uno degli altri media rack?

L'aumento della dimensione massima del file non sembra avere alcun effetto.

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

seri, so che lo spostamento di questo tipo di attività off di Heroku è una mossa sensata, ma che non sarà un rapido lavoro.

Cosa posso fare per servire queste risorse su Heroku nel frattempo senza errori?

risposta

7

Ho avuto lo stesso problema come @jordelver e sono riusciti a ottenere i limiti di memcachier turno da scimmia patching Dragonfly::Response:

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 

In sostanza, se la dimensione è superiore a 1048576 byte, inviare un'intestazione no-cache.

+0

questa soluzione ha funzionato con successo per me. Grazie! – Francois

+1

FYI c'è un'API per cambiare le intestazioni senza patch di scimmia - vedi http://markevans.github.io/dragonfly/configuration/ (bit "response_header") –

9

Quindi contrariamente alla domanda di @ jordelver, trovo che l'impostazione dell'opzione :value_max_bytes di dalli funzioni. Sto creando Rack :: Cache in un modo leggermente diverso che forse fa la differenza.

Questo è ciò che il mio production.rb contiene configurare Rack :: 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" 

Con quanto sopra, alcuni errori verrà stampato per i registri per valori superiori a 1 MB, ma non causerà un errore 5xx per il cliente, solo una mancanza di cache.

P.S Lavoro per MemCachier :), quindi siamo interessati a provare a risolvere questo problema. Perfavore fammi sapere se funziona.

+0

l'impostazione di un valore value_max_bytes superiore non ha funzionato nel mio caso. – Francois

+0

Questo mi ha aiutato nella giusta direzione su un problema leggermente diverso, quindi grazie a David :) – robotmay

+0

Per farlo in questo modo, devi installare la gemma di rack-cache. Normalmente si attiva dalli in 'environments/development.rb' aggiungendo' config.cache_store =: dalli_store'.Puoi specificare il valore_max_byte qui? Grazie –

0

mio application.js era troppo grande per rack-cache così ho fatto:

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

e funziona!

Memorizza i metadati in memcache ma il file effettivo nel filesystem e non nella memoria.

+1

Questa non è una buona idea se stai correndo su Heroku come Dynos condividerà il metastore ma non il filesystem. Ciò significa che a volte il tuo file verrà memorizzato nella cache in base al metastore ma mancante dal file system e non verrà trovato. – jordelver

+0

Ti consiglia di memorizzare i file in Memcache? – Dorian

+0

E BTW, questo è per 'development.rb' – Dorian

Problemi correlati