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

com.fizzgate.plugin.auth.ApiConfig2appsService Maven / Gradle / Ivy

There is a newer version: 3.3.0
Show newest version
/*
 *  Copyright (C) 2020 the original author or authors.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see .
 */

package com.fizzgate.plugin.auth;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.stereotype.Service;

import com.fizzgate.config.AggregateRedisConfig;
import com.fizzgate.util.Consts;
import com.fizzgate.util.JacksonUtils;
import com.fizzgate.util.ReactorUtils;
import com.fizzgate.util.ThreadContext;

import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 * @author hongqiaowei
 */

@Service
public class ApiConfig2appsService {

    private static final Logger log                       = LoggerFactory.getLogger(ApiConfig2appsService.class);

    private static final String fizzApiConfigAppSetSize   = "fizz_api_config_app_set_size";

    private static final String fizzApiConfigAppKeyPrefix = "fizz_api_config_app:";

    private static final String fizzApiConfigAppChannel   = "fizz_api_config_app_channel";

    private Map> apiConfig2appsMap = new HashMap<>(128);

    @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE)
    private ReactiveStringRedisTemplate rt;

    @PostConstruct
    public void init() throws Throwable {
        this.init(this::lsnChannel);
    }

    public void refreshLocalCache() throws Throwable {
        this.init(null);
    }

    private void init(Runnable doAfterLoadCache) throws Throwable {
        Map> apiConfig2appsMapTmp = new HashMap<>(128);
        rt.opsForHash().entries(fizzApiConfigAppSetSize)
                .collectList()
                .map(
                    es -> {
                        log(es);
                        Mono initiateFlux = ReactorUtils.getInitiateMono();
                        for (Map.Entry e : es) {
                            Integer apiConfigId = Integer.parseInt( (String) e.getKey()   );
                            int     appSetCount = Integer.parseInt( (String) e.getValue() );
                            for (int i = 0; i < appSetCount; i++) {
                                int iFinal = i;
                                initiateFlux = initiateFlux.flatMap(
                                    o -> {
                                        return
                                        rt.opsForSet().members(fizzApiConfigAppKeyPrefix + apiConfigId + '_' + iFinal)
                                                      .collectList()
                                                      .map(
                                                          as -> {
                                                              save(apiConfigId, as, apiConfig2appsMapTmp);
                                                              return ReactorUtils.NULL;
                                                          }
                                                      )
                                                      ;
                                    }
                                );
                            }
                        }
                        return initiateFlux;
                    }
                )
                .subscribe(
                    m -> {
                        m.subscribe(
                            e -> {
                                apiConfig2appsMap = apiConfig2appsMapTmp;
                                if (doAfterLoadCache != null) {
                                    doAfterLoadCache.run();
                                }
                            }
                        );
                    }
                );
    }

    private void log(List> es) {
        StringBuilder b = ThreadContext.getStringBuilder();
        b.append(fizzApiConfigAppSetSize).append('\n');
        for (Map.Entry e : es) {
            String key = (String) e.getKey();
            String value = (String) e.getValue();
            b.append(key).append(":").append(value).append(' ');
        }
        log.info(b.toString());
    }

    private void save(Integer apiConfigId, List as, Map> apiConfig2appsMap) {
        Set appSet = apiConfig2appsMap.computeIfAbsent(apiConfigId, k -> new HashSet<>());
        appSet.addAll(as);
        log(apiConfigId, as);
    }

    private void log(Integer apiConfigId, List apps) {
        StringBuilder b = ThreadContext.getStringBuilder();
        b.append(apiConfigId).append(" add: ");
        for (String a : apps) {
            b.append(a).append(' ');
        }
        log.info(b.toString());
    }

    private void lsnChannel() {
        rt.listenToChannel(fizzApiConfigAppChannel)
                .doOnError(
                        t -> {
                            log.error("lsn api config 2 apps channel", t);
                        }
                )
                .doOnComplete(
                        () -> {
                            log.info("success to lsn on api config 2 apps channel");
                        }
                )
                .doOnNext(
                    msg -> {
                        String json = msg.getMessage();
                        // log.info("apiConfig2apps: " + json, LogService.BIZ_ID, "ac2as" + System.currentTimeMillis());
                        org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, "ac2as" + System.currentTimeMillis());
                        log.info("apiConfig2apps: " + json);
                        try {
                            ApiConfig2apps data = JacksonUtils.readValue(json, ApiConfig2apps.class);
                            updateApiConfig2appsMap(data);
                        } catch (Throwable t) {
                            log.error(Consts.S.EMPTY, t);
                        }
                    }
                )
                .subscribe()
                ;
    }

    private void updateApiConfig2appsMap(ApiConfig2apps data) {
        Set apps = apiConfig2appsMap.get(data.id);
        if (data.isDeleted) {
            if (apps != null) {
                data.apps.forEach(apps::remove);
                log.info("remove " + data);
            }
        } else {
            if (apps == null) {
                apps = new HashSet<>(32);
                apiConfig2appsMap.put(data.id, apps);
            }
            apps.addAll(data.apps);
            log.info("add " + data);
        }
    }

    public boolean contains(int api, String app) {
        Set apps = apiConfig2appsMap.get(api);
        if (apps == null) {
            return false;
        } else {
            return apps.contains(app);
        }
    }

    public Set remove(int id) {
        return apiConfig2appsMap.remove(id);
    }

    public Map> getApiConfig2appsMap() {
        return apiConfig2appsMap;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy