<?php
// Ultra-short cache + anti-stampede lock for heavy polling.
// Safe on shared hosting. Uses APCu if available, else file cache.

function mc_dir() {
    $dir = __DIR__ . '/../_cache';
    if (!is_dir($dir)) @mkdir($dir, 0775, true);
    return $dir;
}

function mc_file($key) {
    return mc_dir() . '/' . md5($key) . '.json';
}

function mc_age($key) {
    $f = mc_file($key);
    if (!file_exists($f)) return PHP_INT_MAX;
    return time() - filemtime($f);
}

function mc_get($key) {
    if (function_exists('apcu_fetch')) {
        $ok = false;
        $v = apcu_fetch($key, $ok);
        if ($ok) return $v;
    }
    $f = mc_file($key);
    if (!file_exists($f)) return null;
    return @file_get_contents($f);
}

function mc_set($key, $val, $ttl) {
    if (function_exists('apcu_store')) {
        @apcu_store($key, $val, $ttl);
    }
    $f = mc_file($key);
    $tmp = $f . '.tmp';
    @file_put_contents($tmp, $val, LOCK_EX);
    @rename($tmp, $f);
}

function mc_invalidate($key) {
    if (function_exists('apcu_delete')) @apcu_delete($key);
    $f = mc_file($key);
    if (file_exists($f)) @unlink($f);
}

function mc_lock($lockName, callable $fn) {
    $lockFile = mc_dir() . '/' . md5($lockName) . '.lock';
    $fp = @fopen($lockFile, 'c');
    if (!$fp) return $fn();

    if (@flock($fp, LOCK_EX)) {
        $out = $fn();
        @flock($fp, LOCK_UN);
        @fclose($fp);
        return $out;
    }

    @fclose($fp);
    return $fn();
}
