Created
October 30, 2015 03:11
-
-
Save atsu666/bdcf6197fa21ac534e8c to your computer and use it in GitHub Desktop.
a-blog cmsのキャッシュ処理周り
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//------- | |
// cache | |
define('ZIP_USE', !DEBUG_MODE and !!ZIP_ENABLE and ('on' == config('zip_http'))); | |
if ( 1 | |
and !DEBUG_MODE | |
and ('on' == config('cache')) | |
and (!SID or (config('subscriber_cache') === 'on' and ACMS_RAM::userAuth(SUID) === 'subscriber' and !$Q->get('admin'))) | |
and !(is_ajax() and config('ajax_nocache') === 'on' and $GetQuery->get('nocache') === 'yes') | |
and !HTTPS | |
and !ACMS_POST | |
) { | |
//------ | |
// CHID | |
define('CHID', md5(REQUEST_URL.RID)); | |
//----------- | |
// publishes | |
$SQL = SQL::newSelect('cache'); | |
$SQL->addWhereIn('cache_status', array('generating', 'regenerating')); | |
$SQL->addWhereOpr('cache_expire', date('Y-m-d H:i:s', REQUEST_TIME), '>'); | |
$SQL->addWhereOpr('cache_blog_id', BID); | |
$SQL->setLimit(MAX_PUBLISHES); | |
$publishes = count($DB->query($SQL->get(dsn()), 'all')); | |
// 作ろうとしているCHIDを探索する | |
$SQL = SQL::newSelect('cache'); | |
$SQL->addWhereOpr('cache_id', CHID); | |
// キャッシュ制御 | |
// 他の子プロセス(prefork時のこと、worker時であればスレッドと言うべき?)を考慮していて少々分岐が多い | |
do { | |
//------------------- | |
// not generated yet | |
if ( !($row = $DB->query($SQL->get(dsn()), 'row')) ) { | |
// 同時publishの制限数を超えたらここで中断(503 Service Unavailable)する | |
if ( MAX_PUBLISHES <= $publishes ) { | |
define('PUBLISHING', 'fail'); | |
userErrorLog('ACMS Warning: Cache Max Publishes Publish.'); | |
die503('Max Publishes Publish'); | |
} | |
// キャッシュ生成中であることを予約 | |
$SQL = SQL::newInsert('cache'); | |
$SQL->addInsert('cache_id', CHID); | |
$SQL->addInsert('cache_data', ''); | |
$SQL->addInsert('cache_expire', date('Y-m-d H:i:s', REQUEST_TIME + MAX_EXECUTION_TIME)); | |
$SQL->addInsert('cache_status', 'generating'); | |
$SQL->addInsert('cache_blog_id', BID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
// タッチの差で、ほかの子プロセスが予約していたら、インサートに失敗しているはずなので中断する | |
// 成功していればブロックを抜ける | |
if ( !!$DB->affected_rows() ) { | |
break; | |
} else { | |
define('PUBLISHING', 'fail'); | |
userErrorLog('ACMS Warning: Cahce Generating Double Insert.'); | |
die503('Generating Double Insert'); | |
} | |
} | |
$expire = $row['cache_expire']; | |
$status = $row['cache_status']; | |
$now = date('Y-m-d H:i:s'); | |
$execution = date('Y-m-d H:i:s', REQUEST_TIME + MAX_EXECUTION_TIME); | |
// 予約済み・または生成済み | |
switch ( $status ) { | |
case 'generated': | |
if ( MAX_PUBLISHES <= $publishes ) { | |
// 同時publishの制限をこえてたら、あきらめて古いキャッシュを利用する | |
httpStatusCode('200 OK Old Generated'); | |
break; | |
} else if ( $expire <= $now ) { | |
// 賞味期限切れだったら作り直しの予約 | |
$SQL = SQL::newUpdate('cache'); | |
$SQL->addUpdate('cache_expire', $execution); | |
$SQL->addUpdate('cache_status', 'regenerating'); | |
$SQL->addWhereOpr('cache_id', CHID); | |
$SQL->addWhereOpr('cache_status', 'generated'); | |
$SQL->addWhereOpr('cache_blog_id', BID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
if ( !!$DB->affected_rows() ) { | |
// 賞味期限切れから再生成が成立したとき | |
break 2; | |
} else { | |
// 作り直しの予約が他でされてたら、それは他に任せて古いキャッシュを利用する | |
httpStatusCode('200 OK Double Generated Exception'); | |
break; | |
} | |
} else { | |
httpStatusCode($row['cache_http_status_code']); | |
break; | |
} | |
case 'generating': | |
// regeneratingでないので、利用できるキャッシュがない | |
if ( MAX_PUBLISHES <= $publishes ) { | |
define('PUBLISHING', 'fail'); | |
userErrorLog('ACMS Warning: Cache Max Publishes Generating.'); | |
die503('Max Publishes Generating'); | |
} else if ( $expire <= $now ) { | |
// 先行するgeneratingの失敗を救済してる部分 | |
$SQL = SQL::newUpdate('cache'); | |
$SQL->addUpdate('cache_expire', $execution); | |
$SQL->addWhereOpr('cache_id', CHID); | |
$SQL->addWhereOpr('cache_status', 'generating'); | |
$SQL->addWhereOpr('cache_expire', $now, '<='); | |
$SQL->addWhereOpr('cache_blog_id', BID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
if ( !!$DB->affected_rows() || config('cache_publish_fail_continue') === 'on' ) { | |
// 有効な制限時間(timeout)を超えてgeneratingしてるのがいたら、自分が試行 | |
break 2; | |
} else { | |
// だれかが試行中なら、あきらめて中断 | |
define('PUBLISHING', 'fail'); | |
userErrorLog('ACMS Warning: Cache Double Generating Exception.'); | |
die503('Double Generating Exception'); | |
} | |
} else if ( config('cache_publish_fail_continue') === 'on' ) { | |
break 2; | |
} else { | |
// 他に試行中のがいそうなので、あきらめて中断 | |
define('PUBLISHING', 'fail'); | |
userErrorLog('ACMS Warning: Cache Double Generating Expire.'); | |
die503('Double Generating Expire'); | |
} | |
case 'regenerating': | |
// generatingとの違いは、使えるキャッシュがあるので古いキャッシュを利用する | |
if ( MAX_PUBLISHES <= $publishes ) { | |
httpStatusCode('200 OK Old Regenerating'); | |
break; | |
} else if ( $expire <= $now ) { | |
$SQL = SQL::newUpdate('cache'); | |
$SQL->addUpdate('cache_expire', $execution); | |
$SQL->addWhereOpr('cache_id', CHID); | |
$SQL->addWhereOpr('cache_status', 'regenerating'); | |
$SQL->addWhereOpr('cache_expire', $now, '<='); | |
$SQL->addWhereOpr('cache_blog_id', BID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
if ( !!$DB->affected_rows() ) { | |
break 2; | |
} else { | |
httpStatusCode('200 OK Double Regenerating Exception'); | |
break; | |
} | |
} else { | |
httpStatusCode('200 OK Double Regenerating Expire'); | |
break; | |
} | |
} | |
//----------- | |
// generated | |
define('PUBLISHING', 'static'); | |
if ( '200 OK' === httpStatusCode() ) { | |
//------------- | |
//client cache | |
$pTime = strtotime($expire) - config('cache_expire'); | |
header('Last-Modified: '.date('r', $pTime)); | |
header('Expires: '.date('r', REQUEST_TIME + config('cache_expire_client'))); | |
if ( IF_MODIFIED_SINCE and strtotime(IF_MODIFIED_SINCE) >= $pTime ) { | |
httpStatusCode('304 Not Modified'); | |
die(header(PROTOCOL.' 304 Not Modified')); | |
} | |
} | |
header(PROTOCOL.' '.httpStatusCode()); | |
header('Content-type: '.$row['cache_mime'].'; charset='.$row['cache_charset']); | |
$contents = $row['cache_data']; | |
if ( ZIP_USE ) { | |
header('Content-Encoding: gzip'); | |
header('Vary: Accept-Encoding'); | |
} else { | |
$contents = gzdecode($contents); | |
} | |
die($contents); | |
} while ( false ); | |
} | |
if ( !defined('CHID') ) define('CHID', null); | |
if ( !defined('PUBLISHING') ) define('PUBLISHING', 'dynamic'); | |
// cmsの処理... | |
//------------ | |
// save cache | |
if ( !!CHID ) { | |
$SQL = SQL::newUpdate('cache'); | |
$SQL->addUpdate('cache_mime', MIME_TYPE); | |
$SQL->addUpdate('cache_charset', config('charset')); | |
$SQL->addUpdate('cache_http_status_code', httpStatusCode()); | |
$SQL->addUpdate('cache_data', $contents); | |
$SQL->addUpdate('cache_status', 'generated'); | |
$SQL->addUpdate('cache_expire', date('Y-m-d H:i:s', REQUEST_TIME + intval(config('cache_expire')))); | |
$SQL->addWhereOpr('cache_id', CHID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
// キャッシュ生成をキックとして、メール添付用アーカイブフォルダをクリアする | |
new ACMS_POST_Form_Cleartemp(); | |
} | |
//------------------------- | |
// シャットダウン時に実行 | |
function shutdown() | |
{ | |
if ( defined('SESSION_NEXT_ID') and SESSION_NEXT_ID ) { | |
$SQL = SQL::newUpdate('session'); | |
$SQL->addUpdate('session_data', acmsSerialize(Field::singleton('session'))); | |
$SQL->addUpdate('session_expire', SESSION_EXPIRE); | |
if ( defined('SESSION_UPDATE') and SESSION_OLD_NEXT_ID <> SESSION_NEXT_ID ) { | |
$SQL->addUpdate('session_id', SESSION_OLD_NEXT_ID); | |
$SQL->addUpdate('session_next_id', SESSION_NEXT_ID); | |
} | |
$SQL->addWhereOpr('session_id', SID); | |
$DB->query($SQL->get(dsn()), 'exec'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment