2009-06-30 11 views
6

Sto cercando un gemma rubino (o un plugin per rails) che riassuma i dettagli di memcached nello stesso modo in cui ActiveRecord astrae i dettagli di SQL. Sono NON alla ricerca di qualcosa che aiuti a memorizzare nella cache i modelli di ActiveRecord in memcached. Sono sicuro che ci sono circa 4215 gemme che aiuteranno a risolvere questo problema.C'è un wrapper tipo ORM per memcached

Idealmente quello che vorrei è quello di essere in grado di fare qualcosa di simile:

class Apple < MemcachedModel 
# whatever else here 
end 

e quindi in grado di fare cose come:

my_apple = Apple.find('some memcached key') 

che guardare in alto la rappresentazione JSON di questa classe è memorizzata e deserializzata. Mi piacerebbe anche forse in grado di fare cose come:

my_apple.color = "red" 

# persist changes back to memcached 
my_apple.save 

# load any changes from memcached into local model 
my_apple.update 

Sembra che qualcuno deve aver graffiato questo prurito ormai e creato qualcosa in questo senso, ma ogni volta che Google per una tale gioiello Ho appena mantenere alzare cosa che aiuta a memorizzare i modelli AR usando memcached.

risposta

11

Potete dare un'occhiata al mio gioiello moneta, che è una cosa di ORM'ish per tutti i tipi di negozi di valore-chiave. Potete vederlo a: http://github.com/wycats/moneta/tree/master

L'idea alla base di moneta è che tutti i KVS devono comportarsi esattamente come un sottoinsieme di normali hash di Ruby.Sosteniamo:

#[] 
#[]= 
#delete 
#fetch 
#key? 
#store 
#update_key 
#clear 

I store e update_key metodi di prendere una possibilità ulteriore di hash che è possibile utilizzare questa convenzione:

cache = Moneta::Memcache.new(:server => "localhost:11211", :namespace => "me") 
cache.store("name", "wycats", :expires_in => 2) 
cache.update_key("name", :expires_in => 10) 

Sosteniamo un gran numero di KVSs:

  • BerkeleyDB
  • CouchDB
  • DataMapper (Che significa qualsiasi negozio supportato da DM)
  • file
  • LMC
  • Memcache
  • in-process memoria
  • MongoDB
  • Redis
  • Tokyo Cabinet
  • Tokyo Tyrant
  • S3
  • SDBM
  • file utilizzando XAttrs

Ogni negozio supporta scadenza, sia in modo nativo (come in memcached) oppure utilizzando un modulo standard che emula memcache stile di scadenza. L'API è sempre identica e vi è una specifica condivisa su cui vengono eseguiti tutti gli adattatori per garantire la conformità.

È anche abbastanza semplice aggiungere il proprio adattatore, motivo per cui esistono così tanti.

+0

Questa è una libreria davvero interessante. Grazie per aver postato qui! –

+0

Fresco. grazie Yehuda, controllerò questo. Ho cercato una scusa per giocare con tutti questi nuovi negozi di hash persistenti che stanno spuntando. –

3

Non conosco alcun adattatore Ruby ActiveRecord per Memcached. Una libreria simile sarebbe probabilmente difficile da creare perché Memcached non agisce come un database relazionale.

Il risultato è che la libreria non sarebbe in grado di implementare circa l'80% delle funzionalità supportate da ActiveRecord, quindi qual è il vantaggio di tale implementazione? Hai già tutto ciò che ti serve in Rails per lavorare con memcache con un pattern "CRUD".

Rails.cache.read('key') 
Rails.cache.write('key', 'value') 
Rails.cache.delete('key') 
Rails.cache.increment('key', 5) 
Rails.cache.fetch('key') { 'value' } 

Se si sente più a suo agio, è possibile creare un wrapper e procura questi metodi con corrispondente nuovo/creare/aggiornare/save/distruggere metodi. Tuttavia, non sarebbe mai possibile andare oltre un sistema CRUD di base solo perché Memcached non è destinato a essere un database relazionale.

2

È abbastanza facile da implementare.

require 'ostruct' 
require 'active_support/cache' 

class StoredStruct < OpenStruct 
    attr_writer :store 
    def self.store 
    @store || superclass.store 
    end 

    def self.expand_key(key) 
    'StoredStruct_' + (superclass == OpenStruct ? '' : "#{self}_") + key.to_s 
    end 

    def self.get_unique_id 
    key = expand_key('unique_id') 
    store.write(key, 0, :unless_exist => true) 
    store.increment(key) 
    end 

    def self.save(instance) 
    id = instance.id || get_unique_id 
    store.write(expand_key(id), instance) 
    id 
    end 

    def self.find(id) 
    store.read(expand_key(id)) 
    end 

    attr_reader :id 

    def attributes 
    @table 
    end 

    def attributes=(hash) 
    @table = hash 
    end 

    def new_record? 
    self.id.nil? 
    end 

    def save 
    @id = self.class.save(self) 
    true 
    end 

    def reload 
    instance = self.class.find(self.id) 
    self.attributes = instance.attributes unless self == instance 
    self 
    end 
end 

usare in questo modo:

# connect to memcached 
StoredStruct.store = ActiveSupport::Cache::MemCacheStore.new("localhost:11211") 

class Apple < StoredStruct 
end 

fruit = Apple.new 
fruit.color = "red" 
fruit.taste = "delicious" 

fruit.id 
#=> nil 

fruit.save 
#=> true 
fruit.id 
#=> 1 

# to load any changes: 
fruit.reload 

Apple.find(1) 
#=> fruit 
+0

Nizza. Mi piace in particolare come hai implementato get_unique_id. Idealmente, sto cercando di usare una libreria esistente piuttosto che reinventare la ruota, ma se dovessi farlo da zero mi piacerebbe rubare quello che hai qui :) –

0

Si può essere alla ricerca di Nick Kallen's cache-money.

+0

Grazie Sarah, ma è esattamente quello che sono NON cercare: una libreria di memorizzazione nella cache per ActiveRecord. –

+0

Ah, vedo che ho frainteso la tua domanda. Desiderate fare a meno di ActiveRecord e memorizzare solo gli oggetti in memcached? Sono curioso di sapere che tipo di cose memorizzerai. –

+0

Sì, ho dati transitori che ottengo da un'altra API. Voglio memorizzare nella cache i dati localmente in modo che non debba fare il round-trip su questa altra API ogni volta che servizio una richiesta. Le cose che sto memorizzando nella cache sono informazioni sull'account: oggetti come un utente, un'organizzazione, ecc. –

1

Come ha scritto Simone Carletti, Memcached non è un database relazionale; non può nemmeno elencare tutte le sue chiavi. Pertanto, qualsiasi modello simile a ActiveRecord che memorizza i dati in Memcached non conterrà tutte le funzionalità di ActiveRecord. Ciononostante, penso che ci sia un certo valore nell'avere un'API coerente per tutti i tuoi modelli, quindi se ha senso che uno dei tuoi modelli memorizzi i suoi dati in Memcached, puoi usare questo modulo che ho creato a tale scopo:

http://blog.slashpoundbang.com/post/1455548868/memcachemodel-make-any-ruby-object-that-persists-in