Вопрос

Я создал CFC, предназначенный для использования в качестве динамического устаревшего кэша, предназначенного практически для всего, что стоит кэшировать.Запросы LDAP, результаты функций, массивы, объекты — что угодно.Все, что требует времени или ресурсов для расчета и требуется более одного раза.Я хотел бы иметь возможность сделать несколько вещей:

  • совместно использовать CFC между приложениями
  • определить область кеша (только сервер/приложение/сеанс/текущий запрос)
  • использовать разные экземпляры кеша одновременно в одном запросе
  • быть независимым от CFC, используя компонент кэша
  • обычно придерживаются здравого смысла (развязка, инкапсуляция, ортогональность, блокировка)

Я бы, конечно, использовал разные экземпляры кэша для каждой отдельной задачи, но мне бы хотелось иметь возможность использовать один и тот же CFC во всех приложениях.Сам кеш (что еще) является структурой, частной для экземпляра кеша.Как мне правильно реализовать кеширование и блокировку, если сама область действия может быть изменена?

Для блокировки я использую именованные блокировки ('CacheRead', 'CacheWrite') В настоящее время это безопасно, но поражает меня как странного.Зачем мне блокировка на уровне всего сервера, скажем, только для сеансовой операции?(Да, возможно, это является академический, но тем не менее.)

Передача области ПРИЛОЖЕНИЯ в качестве ссылки, когда мне нужно кэширование на уровне приложения, также кажется неправильным.Есть ли способ лучше?

Это было полезно?

Решение

Я понимаю ваше желание избежать передачи фактической структуры области, которую вы хотите кэшировать, но ваши альтернативы ограничены.Первое, что приходит на ум, — это просто передать имя (строку) области, в которой вы хотите сохранить свой кеш, и выполнить оценку.По своей природе оценка неэффективна, и ее следует избегать.Тем не менее, мне было любопытно, как этого можно добиться.У меня нет вашего кода, поэтому я просто сделал очень простую абстракцию «хранилища» CFC (пропустил кеширование, поскольку оно не имеет отношения к тому, что я хочу протестировать) здесь:

кэш.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">

Не по теме:Мне нравится писать свои функции установки так, чтобы они возвращали «это» [как показано выше], чтобы я мог связывать вызовы методов, таких как jQuery.Часть представления можно было бы так же легко записать так:

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

Интересно, что это возможно, но я бы, вероятно, не стал использовать это в производстве из-за накладных расходов на Evaluate.Я бы сказал, что это достаточная причина, чтобы передать область, в которую вы хотите кэшировать.

Если вас это все еще беспокоит (и, возможно, это правильно?), вы можете создать еще один CFC, который абстрагирует чтение и запись из желаемой области, и передать его в свой кэширующий CFC в качестве места хранения (задача, хорошо подходящая для ХолодВесна), таким образом, если вы когда-нибудь решите переместить кеш в другую область, вам не придется редактировать 300 страниц, используя CFC вашего кеша, передавая «сеанс» для инициализации, и вместо этого вы можете редактировать 1 CFC или вашу конфигурацию ColdSpring.

Я не совсем понимаю, зачем вам кэширование одного запроса, если у вас есть область запроса.Если вы ищете способ кэшировать что-то для текущего запроса и вскоре после этого завершить его, область запроса может быть той, что вам нужна.Кэширование обычно более ценно, когда оно охватывает несколько запросов.

Другие советы

Хорошо, поскольку изначально я неправильно понял ваш вопрос, я удалил свой предыдущий ответ, чтобы не вызывать дальнейшей путаницы.

Чтобы ответить на ваш вопрос о блокировке:

Именованные блокировки подойдут, потому что они не обязательно должны всегда иметь одно и то же имя.Вы можете называть их динамически в зависимости от того, к какому кешу вы обращаетесь.Когда вам нужно получить доступ к элементу частной структуры, вы можете сделать что-то вроде того, чтобы именованный замок использовал ключ в качестве своего имени.

Таким образом, блокировка будет иметь эффект только в том случае, если что-то попытается получить доступ к тому же кешу по имени.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top