質問

私は、キャッシュする価値のあるほぼすべてのものを対象とした動的なエージングキャッシュとして機能するように設計されたCFCを構築しました。 LDAPクエリ、関数の結果、配列、オブジェクト、名前を付けます。計算に時間やリソースがかかり、複数回必要なものは何でも。いくつかのことができるようになりたい:

  • アプリケーション間でCFCを共有する
  • キャッシュの範囲を定義します(サーバー/アプリケーション/セッション/現在のリクエストのみ)
  • 同じリクエストで異なるキャッシュインスタンスを同時に使用する
  • キャッシュコンポーネントを使用してCFCから独立している
  • 一般的に常識(デカップリング、カプセル化、直交性、ロック)に固執する

もちろん、個別のタスクごとに異なるキャッシュインスタンスを使用しますが、アプリケーション間で同じCFCを使用できるようにしたいと考えています。キャッシュ自体は(他に)Structであり、キャッシュインスタンス専用です。スコープ自体が変更される可能性がある場合、キャッシュとロックを適切に実装するにはどうすればよいですか?

ロックには、名前付きロック( 'CacheRead' 'CacheWrite' )を現在使用していますが、これは安全です 奇妙に思えますたとえば、セッションのみの操作に対してサーバー全体のロックが必要なのはなぜですか? (はい、多分これは学術的ですが、とにかく。)

アプリケーションレベルのキャッシングが必要な場合に、APPLICATIONスコープを参照として渡すことも間違っているようです。より良い方法はありますか?

役に立ちましたか?

解決

キャッシュしたい実際のスコープ構造を渡すことを避けたいというあなたの希望を理解していますが、選択肢は限られています。最初に思い浮かぶのは、キャッシュを保存するスコープの名前(文字列)を渡すだけで、評価することです。その性質上、評価は非効率的であり、避けるべきです。とはいえ、どのように達成できるのか興味がありました。私はあなたのコードを持っていないので、私はただ汚れた「ストレージ」を作りました。抽象化CFC(キャッシュをスキップしました。テストしたいものとは無関係です):

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>

そしてそれをテストするビュー:

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

オフトピック:&quot; this&quot;を返すためのセッター関数を書きたい[上記のとおり] jQueryのようなメソッド呼び出しを連鎖できるようにします。ビューの一部は次のように簡単に記述できます。

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

これが可能なのは興味深いことですが、Evaluateのオーバーヘッドコストのために、実稼働環境では使用しないでしょう。これは、キャッシュしたいスコープに渡すのに十分な理由だと思います。

まだ気になっている場合(そしておそらくそうですか?)、目的のスコープから読み取りと書き込みを抽象化する別のCFCを作成し、それをストレージの場所としてキャッシュCFCに渡すことができます(適切なタスク ColdSpring )の場合、その方法でキャッシュを別のスコープに移動することにした場合、編集する必要はありません。 「セッション」で渡すキャッシュCFCを使用する300ページ初期化して、代わりに1つのCFCまたはColdSpring設定を編集できます。

リクエストスコープがある場合に、なぜシングルリクエストキャッシングが必要なのかは完全にはわかりません。探しているのが現在のリクエストに対して何かをキャッシュする方法であり、その後すぐにそれを消滅させるのであれば、リクエストスコープがあなたの望むものかもしれません。通常、キャッシュは複数のリクエストにまたがる場合により有益です。

他のヒント

わかりました-最初はあなたの質問を誤解していたので、混乱を引き起こさないように以前の回答を削除しました。

ロックに関する質問に答えるには:

名前付きロックは常に同じ名前である必要はないため、問題ありません。アクセスしているキャッシュに応じて、動的に名前を付けることができます。プライベート構造体の要素にアクセスする必要がある場合は、名前付きロックにキーを名前として使用させるなどの方法があります。

この方法では、ロックが効果を発揮するのは、何かが同じキャッシュに名前でアクセスしようとした場合だけです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top