<?php
namespace app\mobile\service;

use think\facade\Db;

/** 同站点PHP进程共享读锁可并行保存，基础数据换表独占写锁。 */
class CheckSyncGuard
{
    public static function run($exclusive,$work) {
        $c=Db::connect()->getConfig();
        // mobile/adminVue的runtime子目录可能不同，必须用站点根目录下同一个锁文件。
        $file=app()->getRootPath().'runtime/check-sync-'.hash('sha256',$c['database'].':'.$c['prefix']).'.lock';
        $handle=fopen($file,'c');
        if(!$handle)throw new \RuntimeException('无法打开点检同步锁');
        $deadline=microtime(true)+5;
        try {
            do {
                if(flock($handle,($exclusive?LOCK_EX:LOCK_SH)|LOCK_NB)){
                    try{return $work();}finally{flock($handle,LOCK_UN);}
                }
                usleep(20000);
            }while(microtime(true)<$deadline);
            throw new \think\exception\HttpResponseException(json(['code'=>1,'message'=>'点检基础数据正在同步，请稍后重试','data'=>null],409));
        }finally{fclose($handle);}
    }
}
