Кеширование данных, и как с ним бороться.

декабря 6, 2007

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

Сценарий 2:
Мы пишем клиентскую часть игры для он-лайн казино. Все процессы связанные с логикой игры происходят на жутко засекреченном сервере, наш клиент только отображает красиво все эти процессы. В определенный момент отправляет серверу данные о действиях игрока, в ответ получая XML с состоянием дел: Баланс игрока, комбинацию карт (или символов, если это слот-машина) ну и много всего разного.

Несмотря на то что мы не запрашиваем реально существующий XML, все равно результат заносится в кеш, и по следующему подобному запросу мы получим старые данные. В итоге – игрок выиграл 100000, но не знает, что это случилось.

Самый простой способ это приклеить Math.random() к запросу. Тогда браузер воспримет такой запрос как абсолютно новый и радостно вернет нам нужные данные в самом свежем виде. Но, полагаться на Math.random() всегда я бы не стал.

И я не стал. Как раз когда мне довелось писать кучу игр для казино, возник вопрос о железной защите от кеша. В итоге родился шизофренический метод, который позже я перелопатил в класс с одним единственным статичным методом. Базируется он на самой непостоянной субстанции – времени.

Однако на этом мы успокаиваться не будем. Иногда нам нужно чтобы свежие данные приходили не так часто. Допустим у меня есть сайт-портфолио, состоящий из нескольких html-страниц. На каждой имеется флеш-галерея работ. Если я буду отключать кеш для каждой загрузки – то мой посетитель будет упорно грузить свежие данные при каждом возвращении на страницу. Выход – обновляться скажем только каждый час, или день.

В общем хватит слов. Класс элементарный – и все будет ясно из его кода.

Метод один Cache.disable(key:String, level:Number);
key – это строка, которую нужно приклеить к запросу. Или банальный «?» («&» если в запросе уже есть пары имя=значение), или что-то сокровенное вроде «?nocache=».
level – уровень защиты от кеша. Передаем одну из констант:
Cache.MONTH, Cache.DAY, Cache.HOUR, Cache.MINUTE, Cache.FULL

код класса:

/**
* class Cache
* @author Mikhail Ivanchuk
* @version 0.1
*/
class ru.decafe.utils.Cache {
 
	public static var MONTH:Number = 1;
	public static var DAY:Number = 2;
	public static var HOUR:Number = 3;
	public static var MINUTE:Number = 4;
	public static var FULL:Number = 5;
	public static function disable(key:String, level:Number):String {
		if (level == undefined) level = Cache.FULL;
		var browser:Boolean = (_level0._url.substr(0,4) == "http");
		// timestamp
		var timestamp:Date = new Date();
		var timestampY:Number = timestamp.getYear();
		var timestampMN:Number = timestamp.getMonth();
		var timestampD:Number = timestamp.getDate();
		var timestampH:Number = timestamp.getHours();
		var timestampM:Number = timestamp.getMinutes();
		var timestampS:Number = timestamp.getSeconds();
		var timestampMS:Number = timestamp.getMilliseconds();
		var timestampMT:Number = Date.UTC(timestampY,timestampMN,timestampD,timestampH,timestampM,timestampS,timestampMS);
		//date string
		var dateString:String = timestampY.toString(16) +timestampMN.toString(16);
		if (level <= Cache.MONTH) return (browser?(key+dateString):"");
		dateString += timestampD.toString(16);
		if (level <= Cache.DAY) return (browser?(key+dateString):"");
		dateString += timestampH.toString(16);
		if (level <= Cache.HOUR) return (browser?(key+dateString):"");
		dateString += timestampM.toString(16);
		if (level <= Cache.MINUTE) return (browser?(key+dateString):"");
		dateString += timestampS.toString(16)+timestampMS.toString(16)+timestampMT.toString(16);
		// random
		var addition:String = (Math.floor(Math.random()*1024)).toString(16);
		return (browser?(key+dateString+addition):"");
	}
}

Popularity: 11% [?]

Entry Filed under: AS2.0,ActionScript

Один комментарий

  • 1. k0t0vich  |  января 3, 2008 at 16:36

    Еще один вариант, который я использую, это брать в качестве ключа время изменения файла, который необходимо подгрузить ( для swf и картинок)
    При апдейте файлов на сервер я запускаю php скрипт который формирует xml страничку с названием файла, размером и датой последнего изменения.
    Далее я просто использую фы-цию getCacheURL(string) которая возвращает измененную строку.
    Преимущества такого подхода: изменяется линк только для измененных файлов.




МЕТА

Метки

2d 3D ActionScript adobe ae after effects animation animator_at_work AS2.0 AS3.0 astro bones bug bugfix debug deep linking draw drawing extension Flash flash CS4 flex fscommand fx html IK Math mindstream music-video NB opensource security swfaddress TextField traps uafpug useful utils video Новости анимация кинематика кости поток сознания туториал

Календарь

Декабрь 2007
Пн Вт Ср Чт Пт Сб Вс
    Янв »
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Архив

Ссылки

Радио