public function hallSeats($showtimeId){
if ( !$result = \Yii::$app->cache->get('theater_halls_seats' . $showtimeId) ) {
$result = $this->get('some/api/halls', [
'showtimeId' => $showtimeId,
]);
\Yii::$app->cache->add('theater_halls_seats' . $showtimeId , $result, 20);
}
return $result;
}
static function getData($waiting_deep = 0)
{
//достаем $prts из кэша
if (!(Yii::$app->cache->exists(self::CACHE_KEY__PRTS) AND is_array($prts = Yii::$app->cache->get(self::CACHE_KEY__PRTS)) AND isset($prts['version']) AND isset($prts['data']) AND is_array($prts['data']))) {
// данных в кэше нет
// выполняем процедуру подготовки данных с блокировкой для других процессов - чтобы другой процесс не начал делать тоже самое. В кэш поместить флаг блокировки Yii::$app->cache->set(CACHE_KEY__PRTS_FLAG_LOCK), а после подготовки данных и помещения их в кэш снять этот флаг блокировки. Если другой параллельный запрос не находит данных в кэше и при этом выставлен флаг блокировки Yii::$app->cache->exists(CACHE_KEY__PRTS_FLAG_LOCK), то он будет ожидать несколько(столькол сколько задана максимальная глубина ожидания) раз. Ограничиваем число ожиданий и интервал этих ожиданий.
if (Yii::$app->cache->exists(self::CACHE_KEY__PRTS_FLAG_LOCK) AND Yii::$app->cache->get(self::CACHE_KEY__PRTS_FLAG_LOCK)) {
if ($waiting_deep <= self::PRTS_FIND__WAITING_DEEP_MAX) {
usleep(self::PRTS_FIND__INTERVAL_WAITING_NEXT_CHECK_MICROSECONDS);
$prts = self::findPromoactionsRuleToShow($waiting_deep++);
} else {
return false;
}
} else {
Yii::$app->cache->set(self::CACHE_KEY__PRTS_FLAG_LOCK, true, 10); //сбросить флаг блокировки через 10 секунд в любом случае. Необходимо на случай ошибок при подготовки правил и следовательно невозможности в штатном режиме сбросить флаг блокировки.
if (!($prts = self::prepareData())!==false){
// кладем данные в кэш
Yii::$app->cache->set(self::DATA_PRTS, $prts);
}
// Сбрасываем флаг блокировки
// Yii::$app->cache->set(self::CACHE_KEY__PRTS_FLAG_LOCK, false);
Yii::$app->cache->delete(self::CACHE_KEY__PRTS_FLAG_LOCK);
}
}
return true;
}