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

com.neko233.toolchain.storage.async.AbstractCacheDataSyncDao Maven / Gradle / Ivy

package com.neko233.toolchain.storage.async;

import com.neko233.toolchain.common.annotation.Experimental;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 抽象数据同步 DAO API, 具体写操作由外部实现
 * ps: 不允许用作 Analysis 类 DAO
 *
 * @author SolarisNeko on 2023-02-05
 **/
@Experimental(comment = "异步 DAO, 读取最新数据覆盖")
public abstract class AbstractCacheDataSyncDao> implements DataSyncApi {

    // 全局数据同步 scheduler
    private static final ScheduledExecutorService GLOBAL_DATA_SYNC_SCHEDULER = Executors.newScheduledThreadPool(1);

    private final BlockingQueue mq;

    private final Map asyncWriteCache = new ConcurrentHashMap<>();

    public AbstractCacheDataSyncDao(int mqMaxSize, DataSyncScheduleParamDto dataSyncScheduleParamDto) {
        dataSyncScheduleParamDto = dataSyncScheduleParamDto == null ? DataSyncScheduleParamDto.temp() : dataSyncScheduleParamDto;

        int initialDelay = Math.max(0, dataSyncScheduleParamDto.getInitDelay());
        int period = Math.max(10, dataSyncScheduleParamDto.getPeriod());
        TimeUnit scheduleTimeUnit = Optional.ofNullable(dataSyncScheduleParamDto.getTimeUnit()).orElse(TimeUnit.SECONDS);

        this.mq = new ArrayBlockingQueue<>(Math.max(10, mqMaxSize));

        // scheduler
        GLOBAL_DATA_SYNC_SCHEDULER.scheduleAtFixedRate(() -> {
            flushAsyncWriteData();
        }, initialDelay, period, scheduleTimeUnit);

        Thread preShutdownThread = new Thread(this::flushAsyncWriteData);
        Runtime.getRuntime().addShutdownHook(preShutdownThread);
    }

    private void flushAsyncWriteData() {
        final List tempDataList = new ArrayList<>(mq.size());
        mq.drainTo(tempDataList);
        insertOrUpdate(tempDataList);

        for (T t : tempDataList) {
            asyncWriteCache.remove(t.uniqueId());
        }

        tempDataList.clear();
    }

    public List getAllAsyncWriteData() {
        return new ArrayList<>(asyncWriteCache.values());
    }


    public T getAsyncWriteData(DataUniqueId queryData) {
        return asyncWriteCache.get(queryData.uniqueId());
    }

    @Override
    public boolean syncData(T data) {
        insertOrUpdate(data);
        return false;
    }

    @Override
    public boolean asyncData(T data) {
        boolean isOk = mq.offer(data);
        if (isOk) {
            asyncWriteCache.merge(data.uniqueId(), data, mergeNewData());
        }
        return isOk;
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy