2015-09-29 21 views
5

Ho un API REST (costruito a Nancy, in esecuzione su ASP.NET) che può restituire un oggetto JSON come questo:Cos'è un algoritmo efficace ed economico per generare ETags?

{ 
    id: "1", 
    name: "Fred", 
    reviews: [ 
    { 
     id: "10", 
     content: "I love Stack Overflow" 
    } 
    ] 
} 

Nota come questo oggetto non è un'entità diretta, invece si tratta di una rappresentazione.

Di solito, vorrei usare un ultimo modificato/timestamp dell'entità nel DB come ETag, quindi quando viene aggiornato, l'ETag viene aggiornato. Semplice.

Ma in questo caso, cosa succede se l'utente non cambia, ma il contenuto della prima revisione cambia? Usando la suddetta logica ETag, non cambierebbe. Qui abbiamo un caso in cui la rappresentazione include più entità e sto cercando di trovare un modo per identificarlo in modo univoco.

Quindi ho bisogno di identificare in qualche modo quella rappresentazione (che è un semplice C# POCO, memorizzato in una cache Redis).

Qui sono i miei pensieri iniziali:

  • Object.GetHashCode(). Non funzionerà, perché il riferimento alla memoria sarà sempre diverso.
  • La memoria scorre l'oggetto, SHA1 lo ha cancellato. Costoso da fare ogni volta.
  • Prima di aggiungere/aggiornare la cache, creare un GUID da utilizzare per ETag e memorizzarlo anche nella cache. Quindi, quando la cache viene scaricata (che sarebbe, nell'esempio precedente), viene generato un nuovo GUID e l'ETag viene aggiornato. Il problema con questo approccio è che lego il mio meccanismo ETag alla mia implementazione di caching (quindi non strettamente accoppiato).

Qualcuno può pensare a un modo economico/efficace per farlo, idealmente a livello globale? (ad esempio Object o oggetto di base, anziché la logica di generazione ETag specifica per ogni entità/risorsa).

Grazie mille!

risposta

1

Penso che l'approccio di hashing non sia poi così male. Esistono algoritmi hash estremamente efficienti come MurmurHash3 (versione a 128 bit) e xxHash (versione a 64 bit) che prenderei in considerazione. Questo è un modo efficace per farlo gobally, ma sfortunatamente non è il più economico. È possibile trovare le implementazioni C# here e here.

Hai detto che ogni entità nel database ha un timestamp modificato. Se il modello è composto da più entità, il modello ETag potrebbe essere derivato dai timestamp delle entità. Il modello ETag sarebbe la concatenazione dei timestamp delle entità. Questo approccio è più efficiente ma non puoi farlo in modo gobbo, avresti bisogno di scrivere un codice specifico per ogni modello.