Pregunta

He construido un CFC diseñado para servir como un caché dinámico y antiguo destinado a casi todo lo que vale la pena almacenar en caché. Consultas LDAP, resultados de funciones, matrices, objetos, lo que sea. Todo lo que toma tiempo o recursos para calcular y se necesita más de una vez. Me gustaría poder hacer algunas cosas:

  • comparte el CFC entre aplicaciones
  • define el alcance del caché (servidor / aplicación / sesión / solicitud actual solamente)
  • use diferentes instancias de caché al mismo tiempo, en la misma solicitud
  • ser independiente de los CFC utilizando el componente de caché
  • generalmente se adhieren al sentido común (desacoplamiento, encapsulación, ortogonalidad, bloqueo)

Por supuesto, estaría usando una instancia de caché diferente para cada tarea distinta, pero me gustaría poder usar el mismo CFC en todas las aplicaciones. El caché en sí es (lo que más) es un Struct, privado a la instancia de caché. ¿Cómo implementaría correctamente el almacenamiento en caché y el bloqueo cuando el alcance en sí está sujeto a cambios?

Para bloquear, uso bloqueos con nombre ( 'CacheRead' , 'CacheWrite' ) actualmente, esto es seguro pero me parece extraño. ¿Por qué querría un bloqueo de todo el servidor para, por ejemplo, una operación de solo sesión? (Sí, tal vez este sea académico, pero de todos modos.)

Pasar en el ámbito de APLICACIÓN como referencia cuando deseo el almacenamiento en caché a nivel de la aplicación también parece ser algo incorrecto. ¿Hay una mejor manera?

¿Fue útil?

Solución

Entiendo su deseo de evitar pasar la estructura de alcance real que desea almacenar en caché, pero sus alternativas son limitadas. Lo primero que viene a la mente es simplemente pasar el nombre (una cadena) del ámbito en el que desea que se almacene su caché y evaluar. Por su naturaleza, la evaluación es ineficiente y debe evitarse. Dicho esto, tenía curiosidad por cómo podría lograrse. No tengo su código, así que simplemente hice un "almacenamiento" muy simple. abstracción CFC (se omite el almacenamiento en caché, ya que es irrelevante para lo que quiero probar) aquí:

cache.cfc:

<cfcomponent>
    <cfset variables.cacheScope = "session" /><!--- default to session --->
    <cfset variables.cache = ""/>

    <cfscript>
    function init(scope){
        variables.cacheScope = arguments.scope;
        return this;
    }

    function cacheWrite(key, value){
        structInsert(evaluate(variables.cacheScope),arguments.key,arguments.value,true);
        return this;
    }

    function cacheRead(key){
        if (not structKeyExists(evaluate(variables.cacheScope), arguments.key)){
            return "";
        }else{
            variables.cache = evaluate(variables.cacheScope);
            return variables.cache[arguments.key];
        }
    }   
    </cfscript>
</cfcomponent>

Y una vista para probarlo:

<!--- clear out any existing session vars --->
<cfset structClear(session)/>
<!--- show empty session struct --->
<cfdump var="#session#" label="session vars">
<!--- create storage object --->
<cfset cacher = createObject("component", "cache").init("session")/>
<!--- store a value --->
<cfset cacher.cacheWrite("foo", "bar")/>
<!--- read stored value --->
<cfset rtn = cacher.cacheRead("foo")/>
<!--- show values --->
<cfdump var="#rtn#">
<cfdump var="#session#" label="session vars">

Tema desactivado: me gusta escribir mis funciones de configuración para devolver " this " [como se ve arriba] para poder encadenar llamadas a métodos como jQuery. Parte de la vista podría escribirse tan fácilmente como:

<cfset rtn = createObject("component", "cache")
    .init("session")
    .cacheWrite("foo", "bar")
    .cacheRead("foo")/>

Es interesante que esto sea posible, pero probablemente no lo usaría en producción debido al costo general de Evaluate. Yo diría que esta es razón suficiente para pasar al ámbito que desea almacenar en la memoria caché.

Si todavía le molesta (¿y quizás con razón?), podría crear otro CFC que resuma la lectura y la escritura del alcance deseado y pasarlo a su CFC de almacenamiento en caché como la ubicación de almacenamiento (una tarea adecuada) para ColdSpring ), de esa forma si alguna vez decide mover el caché a otro ámbito, no tiene que editar 300 páginas, todas con el paso de CFC de su caché en la sesión " " para iniciar, y en su lugar puede editar 1 CFC o su configuración de ColdSpring.

Sin embargo, no estoy completamente seguro de por qué querría tener un almacenamiento en caché de solicitud única cuando tiene el ámbito de la solicitud. Si lo que busca es una forma de almacenar en caché algo para la solicitud actual y hacer que muera poco después, el alcance de la solicitud puede ser lo que desee. El almacenamiento en caché suele ser más valioso cuando abarca múltiples solicitudes.

Otros consejos

Bien, ya que malinterpreté tu pregunta inicialmente, he eliminado mi respuesta anterior para no causar más confusión.

Para responder a su pregunta sobre el bloqueo:

Los bloqueos con nombre deben estar bien porque no siempre tienen que tener el mismo nombre. Puede nombrarlos dinámicamente dependiendo de qué caché está accediendo. Cuando necesite acceder a un elemento de la estructura privada, podría hacer algo como que la cerradura con nombre use la clave como su nombre.

De esta manera, la única vez que un bloqueo tendría efecto es si algo intentara acceder a la misma memoria caché por nombre.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top