Riutilizza i dati già recuperati per la richiesta

7

Ho un'azione che recupera il modello utente da db per controllare l'accesso.

Allora ho un metodo che in alcuni casi richiede lo stesso modello.

function checkAccess(req, res, next) {
    var data = Data.fetch(req.params._id);
    if (data.userId === req.user._id) {
        return res.sendStatus(401);
    }
    return next();
}

Router()
    .get('/:_id',
        checkAccess,
        function (req, res, next) {
            var data = Data.fetch(req.params._id);
            update(data);
            return res.json(data);
        });

La domanda non riguarda come riutilizzare i dati esattamente in quel caso (la soluzione più semplice che ho trovato è usare res.local ).

La mia confusione riguarda il recupero degli stessi dati da db due volte, quando teoricamente può essere riutilizzato.

Non è una richiesta pesante, quindi è improbabile che il livello di cache aumenti la velocità di accesso rispetto all'accesso a db. Ma l'uso della cache può introdurre molti problemi con l'invalidazione.

Ho scoperto che l'utilizzo della cache correlata alla richiesta ( res.local ) può risolvere in particolare il problema, ma rende il mio codice più dettagliato e complesso. Controllo tutti i dati che sono stati recuperati e devo anche prendere la decisione che questi dati siano obsoleti. Inoltre, inoltro gli argomenti tramite diversi metodi per riutilizzarlo, in modo da inquinare la mia API interna (ad esempio quando invio email riutilizzare i dati necessari per il rendering del modello di email, quindi non posso usare mailService.sendInvite(userId) , ma mailService.sendInvite(userId, {user: user, event: event}) ).

Dovrei preoccuparmi di recuperare piccole parti degli stessi dati da db più volte per richiesta?

    
posta iofjuupasli 05.05.2015 - 17:44
fonte

3 risposte

2

Suggerisco di accertarmi che il tuo database sia sfruttato al massimo grado prima di evocare qualsiasi tipo di meccanismo di memorizzazione nella cache.

Solo perché un database è "grande" che non significa necessariamente che l'interrogazione per un po 'sarà "lenta". Lento è soggettivo e se può essere fatto nel tempo necessario perché il tempo di risposta dell'applicazione sia sufficiente, allora direi che non è "lento". Se la tabella interrogata viene indicizzata sulla colonna id che stai interrogando, controllare l'accesso non richiederà più tempo se la tabella contiene 10 o 10 milioni.

Inoltre, il motore di database effettuerà il caching internamente per te. Troverà internamente se la riga correlata con l'ID X è stata modificata dall'ultima query, e se non è stata modificata recupererà dalla propria cache.

A causa di questi punti, non vedo che sia un problema controllare l'accesso a ogni richiesta. Se qualcosa di esterno può modificare i privilegi di accesso ai dati nel sistema, fare il proprio caching rischia di compromettere l'accesso di qualcuno, ma la tua app ne consente l'accesso. Il livello del database è il posto migliore per la memorizzazione nella cache, quindi lasciatelo fare.

    
risposta data 23.09.2017 - 16:48
fonte
0

Sembra che tu possa integrare CheckAccess in una funzione di raccolta dei dati di livello superiore.

var GetSomeData = function(req) {
  var data = Data.fetch(req.param_id);
  if (data.userId === req.user._id) {
    return {'error': 401};
  }
  return {'success': data};
}

// ...
// in client code

var reply = GetSomeData(req);
if (reply.error) {
  res.sendStatus(reply.error);
  return res;
}
else {
  return res.json(reply.success);
}

Vedo che metodi attraenti e riutilizzabili come checkAccess() potrebbero essere. Ma questi hanno bisogno di determinate informazioni per controllare effettivamente l'accesso. Puoi trascinare questo contesto di sicurezza come argomento, o passarlo in un metodo costruttore / fabbrica. Prendere in considerazione:

var securityContext = getSecurityContext(request);  // fetches security data
var mailService = new MailService(securityContext);
var orderProcessor = new OrderProcessor(securityContext);
try {
  var orderId = orderProcessor.createOrder(request);
  mailService.sendConfirmationEmail(orderId, ...);
} catch (error) {
  // report the details of the error
}

Con securityContext passato nel costruttore, tutti i tuoi servizi possono riutilizzarlo senza riprogrammarsi. getSecurityContext() dovrebbe recuperare sufficienti dati relativi alla sicurezza per evitare ulteriori round-trips o almeno renderli improbabili.

    
risposta data 05.05.2015 - 17:59
fonte
0

L'accesso al database può essere lento se il database è grande. Quindi, se hai esigenze di prestazioni impegnative, hai ragione a pensarci.

La prima cosa da considerare è se puoi fornire un singolo punto in cui viene chiamato checkAccess. In caso contrario, l'applicazione presenta un rischio per la sicurezza, che è da qualche parte in cui l'accesso deve essere controllato, non è stato.

In secondo luogo, se hai bisogno di fare il caching, ricorda che non sei la prima persona ad affrontare questa domanda. Ecco una soluzione generale per gli utenti di Postgresql:     link Se non stai usando Postgresql, allora ce ne potrebbe essere uno per il tuo database.

Se il database si trova su un'altra macchina, ogni accesso coinvolge lo stack TCP, che è un maiale delle risorse. Una cache di query nel database non risolverà questo problema.

    
risposta data 23.09.2017 - 16:32
fonte

Leggi altre domande sui tag