Reutilizar datos ya recuperados para solicitud

7

Tengo una acción que recupera el modelo de usuario de db para verificar el acceso.

Luego tengo un método que en algunos casos requiere el mismo modelo.

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 pregunta no es sobre cómo reutilizar los datos exactamente en ese caso (la solución más sencilla que encontré es usar res.local ).

Mi confusión es acerca de obtener los mismos datos de db dos veces, cuando en teoría puede ser reutilizado.

No es una solicitud pesada, por lo que es poco probable que la capa de almacenamiento en caché aumente la velocidad de acceso en comparación con el acceso a db. Pero el uso de la memoria caché puede introducir muchos dolores de cabeza con la invalidación.

Encontré que el uso de la memoria caché relacionada con la solicitud ( res.local ) puede resolver el problema en particular, pero hace que mi código sea más detallado y complejo. Verifico cada dato si fue recuperado, y también debería tomar una decisión si es posible que estos datos estén desactualizados. También paso argumentos a través de varios métodos para reutilizarlo, por lo que contamina mi API interna (por ejemplo, cuando envío un correo electrónico, reutilizo los datos necesarios para representar la plantilla de correo electrónico, por lo que no puedo usar mailService.sendInvite(userId) , sino mailService.sendInvite(userId, {user: user, event: event}) ).

¿Debo preocuparme por obtener partes pequeñas de los mismos datos de db varias veces por solicitud?

    
pregunta iofjuupasli 05.05.2015 - 17:44

3 respuestas

2

Le sugiero que se asegure de que su base de datos se esté aprovechando en toda su extensión antes de evocar cualquier tipo de mecanismo de almacenamiento en caché.

Solo porque una base de datos es "grande", lo que no significa necesariamente que consultar un poco será "lento". Lento es subjetivo, y si se puede hacer en el plazo requerido para que el tiempo de respuesta de la aplicación sea suficiente, entonces diría que no es "lento". Si la tabla que se consulta está indexada en la columna de identificación que está consultando, la verificación del acceso no llevará más tiempo que si la tabla contiene 10 o 10 millones.

Además, el motor de la base de datos se almacenará en caché internamente para usted. Se realizará un seguimiento interno si la fila que se correlaciona con la ID X se ha cambiado desde la última consulta, y si no se ha modificado, se recuperará de su propio caché.

Debido a estos puntos, no lo veo como un problema para verificar el acceso a cada solicitud. Si algo externo puede cambiar los privilegios de acceso a los datos en el sistema, entonces hacer su propio almacenamiento en caché corre el riesgo de que se corte el acceso de alguien pero su aplicación permita el acceso. La capa de la base de datos es el mejor lugar para el almacenamiento en caché, así que déjelo.

    
respondido por el Thomas Carlisle 23.09.2017 - 16:48
0

Parece que podrías integrar CheckAccess en una función de obtención de datos de nivel superior.

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);
}

Veo cómo podrían ser los métodos atractivos y reutilizables como checkAccess() . Pero estos necesitan cierta información para comprobar realmente el acceso. Puede arrastrar este contexto de seguridad como un argumento, o pasarlo a un método constructor / fábrica. Considera:

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 pasado en el constructor, cualquiera de sus servicios puede reutilizarlo sin volver a buscarlo. getSecurityContext() debería obtener suficientes datos relacionados con la seguridad para evitar más viajes de ida y vuelta, o al menos hacerlos improbables.

    
respondido por el 9000 05.05.2015 - 17:59
0

El acceso a la base de datos puede ser lento si la base de datos es grande. Por lo tanto, si tiene necesidades de rendimiento exigentes, tiene razón al pensar en esto.

Lo primero es considerar si puede proporcionar un único punto donde se llama checkAccess. Si no es así, su aplicación tiene un riesgo de seguridad, que es un lugar donde se debe verificar el acceso, no lo ha sido.

En segundo lugar, si necesita el almacenamiento en caché, recuerde que no es la primera persona que enfrenta esta pregunta. Aquí hay una solución general, para usuarios de Postgresql:     enlace Si no está usando Postgresql, entonces puede haber uno para su base de datos.

Si la base de datos está en otra máquina, entonces cada acceso involucra la pila TCP, que es una fuente de recursos. Un caché de consultas en la base de datos no solucionará esto.

    
respondido por el Hugh Morris 23.09.2017 - 16:32

Lea otras preguntas en las etiquetas