Question

J'ai construit un CFC conçu pour servir de cache dynamique et vieillissant destiné à presque tout ce qui mérite d'être mis en cache. Requêtes LDAP, résultats de fonction, tableaux, objets, vous le nommez. Tout ce qui prend du temps ou des ressources à calculer et est nécessaire plus d'une fois. J'aimerais pouvoir faire quelques choses:

  • partager le CFC entre les applications
  • définit l'étendue du cache (serveur / application / session / demande en cours uniquement)
  • utilise différentes instances de cache en même temps, dans la même requête
  • être indépendant des CFC utilisant le composant de cache
  • adhère généralement au bon sens (découplage, encapsulation, orthogonalité, verrouillage)

J'utiliserais bien sûr une instance de cache différente pour chaque tâche distincte, mais j'aimerais pouvoir utiliser le même CFC pour toutes les applications. Le cache lui-même est (quoi d'autre) une structure privée pour l'instance de cache. Comment implémenter correctement la mise en cache et le verrouillage lorsque la portée elle-même est susceptible de changer?

Pour le verrouillage, j'utilise des verrous nommés ( 'CacheRead' , 'CacheWrite' ) actuellement, c'est sûr. mais me semble étrange. Pourquoi voudrais-je un verrou au niveau du serveur pour, par exemple, une opération de session seulement? (Oui, peut-être que cela est académique, mais enfin.)

Transférer la portée de l'application en tant que référence lorsque je souhaite une mise en cache au niveau de l'application semble également être une mauvaise chose à faire. Y a-t-il un meilleur moyen?

Était-ce utile?

La solution

Je comprends votre désir d'éviter de transmettre la structure de la portée que vous souhaitez mettre en cache, mais vos alternatives sont limitées. La première chose qui me vient à l’esprit est simplement de passer le nom (une chaîne) de l’étendue dans laquelle vous voulez que votre cache soit stocké et d’évaluer. De par sa nature, l’évaluation est inefficace et doit être évitée. Cela dit, j'étais curieux de savoir comment cela pourrait être accompli. Je n'ai pas votre code, alors je viens de créer un "stockage" très simple. Abstraction CFC (mise en cache ignorée, car ce n’est pas pertinent pour ce que je veux tester) ici:

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>

Et une vue pour le tester:

<!--- 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">

Hors sujet: j'aime écrire mes fonctions de sélecteur pour renvoyer "this". [comme vu ci-dessus] afin que je puisse chaîner des appels de méthode tels que jQuery. Une partie de la vue pourrait tout aussi bien s’écrire:

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

Il est intéressant de noter que cela est possible, mais je ne l’utiliserais probablement pas en production à cause des frais généraux d’Evaluate. Je dirais que cela constitue une raison suffisante pour transmettre la portée dans laquelle vous souhaitez mettre en cache.

Si cela vous ennuie toujours (et peut-être à juste titre?), vous pouvez créer un autre CFC qui résume la lecture et l'écriture de la portée souhaitée et le transférer dans votre CFC en cache en tant qu'emplacement de stockage (tâche bien adaptée à la tâche). pour ColdSpring ). Ainsi, si vous décidez de déplacer le cache dans une autre étendue, vous n'avez pas à modifier 300 pages, toutes utilisant votre cache CFC en passant "session". pour initier, et à la place, vous pouvez modifier 1 CFC ou votre configuration ColdSpring.

Je ne suis pas tout à fait certain de la raison pour laquelle vous souhaitez utiliser la mise en cache à demande unique alors que vous avez la portée de la demande. Si ce que vous recherchez est un moyen de mettre en cache quelque chose pour la requête en cours et de la faire mourir peu de temps après, la portée de la requête peut être ce que vous voulez. La mise en cache est généralement plus utile lorsqu'elle couvre plusieurs demandes.

Autres conseils

D'accord - depuis que j'ai mal compris votre question, dans un premier temps, j'ai supprimé ma réponse précédente afin de ne pas causer davantage de confusion.

Pour répondre à votre question sur le verrouillage:

Les cadenas nommés devraient convenir, car ils ne doivent pas toujours porter le même nom. Vous pouvez les nommer de manière dynamique en fonction du cache auquel vous accédez. Lorsque vous devez accéder à un élément de la structure privée, vous pouvez faire quelque chose comme demander au verrou nommé d’utiliser la clé comme nom.

De cette façon, le seul cas où un verrou aurait un effet est si quelque chose essayait d'accéder au même cache par son nom.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top