All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.core.cache.CacheManager Maven / Gradle / Ivy

There is a newer version: 10.3.1
Show newest version
package shz.core.cache;

import shz.core.NullHelp;
import shz.core.PRException;
import shz.core.msg.ServerFailureMsg;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;

@SuppressWarnings("unchecked")
public abstract class CacheManager {
    /**
     * 是否查询操作
     */
    protected abstract boolean isGet(CacheParam param);

    /**
     * 判断key是否被设置为null标识
     */
    protected abstract boolean isNull(CacheParam param);

    /**
     * 获取缓存
     */
    protected abstract Object get(CacheParam param);

    /**
     * 匹配缓存
     */
    protected abstract boolean notMatch(CacheParam param);

    /**
     * 剩余时间
     */
    protected long ttlMillis(CacheParam param) {
        return 0L;
    }

    /**
     * 刷新缓存
     */
    protected void refresh(CacheParam param) {
    }

    /**
     * 将该key设置为可能是null标识(注意此方法的实现需要保证线程安全)
     */
    protected abstract boolean setPossibleNull(CacheParam param);

    /**
     * 设置为可能是null标识未成功进入等待
     */
    protected void await(CacheParam param) {
        CountDownLatch latch = new CountDownLatch(1);
        try {
            latch.await(param.timeoutMillis, TimeUnit.MILLISECONDS);
        } catch (InterruptedException ignored) {
        }
    }

    /**
     * 将该key设置为 null标识
     */
    protected abstract void setNull(CacheParam param);

    /**
     * 移除key的可能是null标识
     */
    protected void removePossibleNull(CacheParam param) {
    }

    /**
     * 在finally块中执行,即执行了目标方法后需操作(设置及删除缓存操作)
     *
     * @param response 目标方法返回值,这个值一般用来设置为缓存
     */
    protected abstract void after(CacheParam param, Object response);

    public final  T execute(CacheParam cacheParam, Supplier supplier) {
        if (cacheParam == null) return supplier.get();

        boolean possible = false;
        T response = null;
        //查询操作
        if (isGet(cacheParam)) {
            //过滤器优先匹配,判断是否null标识
            if (notMatch(cacheParam) || isNull(cacheParam)) return null;
            //获取缓存
            response = (T) get(cacheParam);
            if (NullHelp.nonEmpty(response)) {
                long ttlMillis;
                if (cacheParam.time > 0L
                        && cacheParam.ttlRefreshMillis > 0L
                        && (ttlMillis = ttlMillis(cacheParam)) > 0L
                        && ttlMillis <= cacheParam.ttlRefreshMillis) refresh(cacheParam);
                return response;
            }
            //缓存失效或者误判,设置可能 null标识(一种中间状态),设置成功就去查数据库
            if (!(possible = setPossibleNull(cacheParam))) {
                //没有设置成功等待
                await(cacheParam);
                //再次判断(上一个线程可能查完了数据库,最终可能判断这个key为null标识)
                if (isNull(cacheParam)) return null;
                //再次获取
                response = (T) get(cacheParam);
                if (NullHelp.nonEmpty(response)) return response;
                //出现这种情况,可能上一个线程设置缓存失败,也可能是出现异常

                //如果是设置缓存失败,说明查询过数据库,继续执行数据库查询
                if (!(possible = setPossibleNull(cacheParam))) return null;
            }
        }

        try {
            //执行目标方法
            response = supplier.get();
            return response;
        } catch (Throwable t) {
            throw PRException.of(t);
        } finally {
            try {
                after(cacheParam, response);
            } finally {
                if (possible) {
                    try {
                        //数据库没查到,则设置null标识
                        if (NullHelp.isEmpty(response)) setNull(cacheParam);
                    } finally {
                        //清除可能标识
                        removePossibleNull(cacheParam);
                    }
                }
            }
        }
    }

    public final void execute(CacheParam cacheParam, Consumer consumer) {
        if (cacheParam == null) {
            consumer.accept(null);
            return;
        }

        //查询操作
        if (isGet(cacheParam))
            throw PRException.of(ServerFailureMsg.fail("非法操作,获取缓存注解方法不存在返回值,缓存key:%s", cacheParam.key));

        try {
            //执行目标方法
            consumer.accept(null);
        } catch (Throwable t) {
            throw PRException.of(t);
        } finally {
            after(cacheParam, null);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy