Как правильно реализовать общий кеш в ColdFusion? - PullRequest
1 голос
/ 01 октября 2008

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

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

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

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

Передача области APPLICATION в качестве ссылки, когда я хочу, чтобы кэширование на уровне приложения также казалось неправильным. Есть ли лучший способ?

Ответы [ 2 ]

2 голосов
/ 02 октября 2008

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

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

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

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

1 голос
/ 27 октября 2008

Я понимаю ваше желание избежать передачи фактической структуры области видимости, которую вы хотите кэшировать, но ваши альтернативы ограничены. Первое, что приходит на ум, - это просто передать имя (строку) области видимости, в которой вы хотите сохранить кэш, и оценить ее. По своей природе оценка неэффективна и ее следует избегать. Тем не менее, мне было любопытно, как это может быть достигнуто. У меня нет вашего кода, поэтому я просто сделал простую абстракцию 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">

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...