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

com.neko233.toolchain.vcs.vscMessage.VcsMessageManager Maven / Gradle / Ivy

package com.neko233.toolchain.vcs.vscMessage;

import com.neko233.toolchain.vcs.vscMessage.data.VcsMessage;
import com.neko233.toolchain.vcs.vscMessage.exception.VersionDiffTooLargeException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 用户 VCS data 管理
 *
 * @param  type
 * @author SolarisNeko on 2023-01-01
 */
@Slf4j
public class VcsMessageManager {


    private int maxSize;
    private final Map versionNumberMap;

    private final Map>> vcsDataRouteMap;

    public VcsMessageManager() {
        this.maxSize = 20;
        this.versionNumberMap = new ConcurrentHashMap<>();
        this.vcsDataRouteMap = new ConcurrentHashMap<>();
    }


    public int add(String routePath, T data) {
        synchronized (this) {
            LinkedList> vcsMessageList = vcsDataRouteMap.computeIfAbsent(routePath, k -> new LinkedList<>());
            int newVersion = versionNumberMap.merge(routePath, 1, (v1, v2) -> v1 + 1);

            final VcsMessage vcsMessage = (VcsMessage) VcsMessage.builder()
                    .routePath(routePath)
                    .version(newVersion)
                    .data(data)
                    .build();

            if (vcsMessageList.size() >= maxSize) {
                vcsMessageList.removeFirst();
            }
            vcsMessageList.add(vcsMessage);

            // 版本
            return newVersion;
        }
    }


    /**
     * diff( client.server.version, server.server.version ) return vcs-data list
     *
     * @param clientHoldServerVersion 客户端持有 server 的版本号
     * @return client.server.version 和 server.server.version 差异版本的消息
     */
    public List> getDiffVcsDataList(String routePath, Integer clientHoldServerVersion)
            throws VersionDiffTooLargeException {
        synchronized (this) {
            LinkedList> vcsMessageList = vcsDataRouteMap.computeIfAbsent(routePath, k -> new LinkedList<>());
            Integer serverEndVersion = versionNumberMap.getOrDefault(routePath, 1);

            if (clientHoldServerVersion == null) {
                return new ArrayList<>(0);
            }
            if (clientHoldServerVersion.equals(serverEndVersion)) {
                return null;
            }
            if (vcsMessageList.isEmpty()) {
                return null;
            }

            int serverStartVersion = vcsMessageList.getFirst().getVersion();
            if (serverStartVersion > clientHoldServerVersion || clientHoldServerVersion > serverEndVersion) {
                log.error("vcs data manager, version diff too large. client.server.version = {}, server.head.version = {}, server.end.version = {}"
                        , clientHoldServerVersion, serverStartVersion, serverEndVersion);
                throw new VersionDiffTooLargeException();
            }

            return vcsMessageList.stream()
                    .filter(vcsMessage -> vcsMessage.getVersion() >= clientHoldServerVersion)
                    .collect(Collectors.toList());
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy