diff --git a/soul-common/src/main/java/org/dromara/soul/common/enums/ConfigGroupEnum.java b/soul-common/src/main/java/org/dromara/soul/common/enums/ConfigGroupEnum.java index c134343fd0b3..de5564f7f402 100644 --- a/soul-common/src/main/java/org/dromara/soul/common/enums/ConfigGroupEnum.java +++ b/soul-common/src/main/java/org/dromara/soul/common/enums/ConfigGroupEnum.java @@ -33,20 +33,17 @@ public enum ConfigGroupEnum { * App auth config group enum. */ APP_AUTH, - - + /** * Plugin config group enum. */ PLUGIN, - - + /** * Rule config group enum. */ RULE, - - + /** * Selector config group enum. */ diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/HttpSyncDataService.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/HttpSyncDataService.java index 7c333f9b75fb..842a3a839bb1 100644 --- a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/HttpSyncDataService.java +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/HttpSyncDataService.java @@ -22,18 +22,20 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.dromara.soul.common.concurrent.SoulThreadFactory; import org.dromara.soul.common.constant.HttpConstants; -import org.dromara.soul.common.dto.AppAuthData; import org.dromara.soul.common.dto.ConfigData; -import org.dromara.soul.common.dto.MetaData; -import org.dromara.soul.common.dto.PluginData; -import org.dromara.soul.common.dto.RuleData; -import org.dromara.soul.common.dto.SelectorData; import org.dromara.soul.common.enums.ConfigGroupEnum; import org.dromara.soul.common.exception.SoulException; import org.dromara.soul.common.utils.ThreadUtils; @@ -42,7 +44,7 @@ import org.dromara.soul.sync.data.api.PluginDataSubscriber; import org.dromara.soul.sync.data.api.SyncDataService; import org.dromara.soul.sync.data.http.config.HttpConfig; -import org.dromara.soul.sync.data.http.handler.HttpSyncDataHandler; +import org.dromara.soul.sync.data.http.refresh.DataRefreshFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -52,17 +54,6 @@ import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; -import java.time.Duration; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - /** * HTTP long polling implementation. * @@ -71,15 +62,10 @@ */ @SuppressWarnings("all") @Slf4j -public class HttpSyncDataService extends HttpSyncDataHandler implements SyncDataService, AutoCloseable { +public class HttpSyncDataService implements SyncDataService, AutoCloseable { private static final AtomicBoolean RUNNING = new AtomicBoolean(false); - /** - * cache group config with md5 info. - */ - private static final ConcurrentMap GROUP_CACHE = new ConcurrentHashMap<>(); - private static final Gson GSON = new Gson(); /** @@ -98,22 +84,22 @@ public class HttpSyncDataService extends HttpSyncDataHandler implements SyncData private List serverList; + private DataRefreshFactory factory; + public HttpSyncDataService(final HttpConfig httpConfig, final PluginDataSubscriber pluginDataSubscriber, final List metaDataSubscribers, final List authDataSubscribers) { - super(pluginDataSubscriber, metaDataSubscribers, authDataSubscribers); + factory = new DataRefreshFactory(pluginDataSubscriber, metaDataSubscribers, authDataSubscribers); this.httpConfig = httpConfig; this.serverList = Lists.newArrayList(Splitter.on(",").split(httpConfig.getUrl())); this.start(httpConfig); } private void start(final HttpConfig httpConfig) { - // init RestTemplate OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(); factory.setConnectTimeout((int) this.connectionTimeout.toMillis()); factory.setReadTimeout((int) HttpConstants.CLIENT_POLLING_READ_TIMEOUT); this.httpClient = new RestTemplate(factory); - // It could be initialized multiple times, so you need to control that. if (RUNNING.compareAndSet(false, true)) { // fetch all group configs. @@ -146,12 +132,10 @@ private void fetchGroupConfig(final ConfigGroupEnum... groups) throws SoulExcept } private void doFetchGroupConfig(final String server, final ConfigGroupEnum... groups) { - StringBuilder params = new StringBuilder(); for (ConfigGroupEnum groupKey : groups) { params.append("groupKeys").append("=").append(groupKey.name()).append("&"); } - String url = server + "/configs/fetch?" + StringUtils.removeEnd(params.toString(), "&"); log.info("request configs: [{}]", url); String json = null; @@ -162,131 +146,40 @@ private void doFetchGroupConfig(final String server, final ConfigGroupEnum... gr log.warn(message); throw new SoulException(message, e); } - // update local cache boolean updated = this.updateCacheWithJson(json); if (updated) { log.info("get latest configs: [{}]", json); return; } - // not updated. it is likely that the current config server has not been updated yet. wait a moment. log.info("The config of the server[{}] has not been updated or is out of date. Wait for 30s to listen for changes again.", server); ThreadUtils.sleep(TimeUnit.SECONDS, 30); - } - - /** - * If the MD5 values are different and the last update time of the old data is less than - * the last update time of the new data, the configuration cache is considered to have been changed. - * @param newVal the lasted config - * @param groupEnum the group enum - * @return true: if need update - */ - private boolean updateCacheIfNeed(final ConfigData newVal, final ConfigGroupEnum groupEnum) { - // first init cache - if (GROUP_CACHE.putIfAbsent(groupEnum, newVal) == null) { - return true; - } - ResultHolder holder = new ResultHolder(false); - GROUP_CACHE.merge(groupEnum, newVal, (oldVal, value) -> { - // must compare the last update time - if (oldVal == null || (!StringUtils.equals(oldVal.getMd5(), newVal.getMd5()) - && oldVal.getLastModifyTime() < newVal.getLastModifyTime())) { - log.info("update {} config: {}", groupEnum, newVal); - holder.result = true; - return newVal; - } - log.info("Get the same config, the [{}] config cache will not be updated, md5:{}", groupEnum, oldVal.getMd5()); - return oldVal; - }); - return holder.result; - } - + /** * update local cache. * @param json the response from config server. * @return true: the local cache was updated. false: not updated. */ private boolean updateCacheWithJson(final String json) { - JsonObject jsonObject = GSON.fromJson(json, JsonObject.class); JsonObject data = jsonObject.getAsJsonObject("data"); - // if the config cache will be updated? - boolean updated = false; - - // plugin - JsonObject pluginData = data.getAsJsonObject(ConfigGroupEnum.PLUGIN.name()); - if (pluginData != null) { - ConfigData result = GSON.fromJson(pluginData, new TypeToken>() { - }.getType()); - if (this.updateCacheIfNeed(result, ConfigGroupEnum.PLUGIN)) { - updated = true; - this.flushAllPlugin(result.getData()); - } - } - - // rule - JsonObject ruleData = data.getAsJsonObject(ConfigGroupEnum.RULE.name()); - if (ruleData != null) { - ConfigData result = GSON.fromJson(ruleData, new TypeToken>() { - }.getType()); - if (this.updateCacheIfNeed(result, ConfigGroupEnum.RULE)) { - updated = true; - this.flushAllRule(result.getData()); - } - } - - // selector - JsonObject selectorData = data.getAsJsonObject(ConfigGroupEnum.SELECTOR.name()); - if (selectorData != null) { - ConfigData result = GSON.fromJson(selectorData, new TypeToken>() { - }.getType()); - if (this.updateCacheIfNeed(result, ConfigGroupEnum.SELECTOR)) { - updated = true; - this.flushAllSelector(result.getData()); - } - } - - // appAuth - JsonObject appAuthData = data.getAsJsonObject(ConfigGroupEnum.APP_AUTH.name()); - if (appAuthData != null) { - ConfigData result = GSON.fromJson(appAuthData, new TypeToken>() { - }.getType()); - if (this.updateCacheIfNeed(result, ConfigGroupEnum.APP_AUTH)) { - updated = true; - this.flushAllAppAuth(result.getData()); - } - } - - // metaData - JsonObject metaData = data.getAsJsonObject(ConfigGroupEnum.META_DATA.name()); - if (metaData != null) { - ConfigData result = GSON.fromJson(metaData, new TypeToken>() { - }.getType()); - if (this.updateCacheIfNeed(result, ConfigGroupEnum.META_DATA)) { - updated = true; - this.flushMetaData(result.getData()); - } - } - - return updated; + return factory.executor(data); } @SuppressWarnings("unchecked") private void doLongPolling(final String server) { - MultiValueMap params = new LinkedMultiValueMap<>(8); for (ConfigGroupEnum group : ConfigGroupEnum.values()) { - ConfigData cacheConfig = GROUP_CACHE.get(group); + ConfigData cacheConfig = factory.cacheConfigData(group); String value = String.join(",", cacheConfig.getMd5(), String.valueOf(cacheConfig.getLastModifyTime())); params.put(group.name(), Lists.newArrayList(value)); } HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity httpEntity = new HttpEntity(params, headers); - String listenerUrl = server + "/configs/listener"; log.debug("request listener configs: [{}]", listenerUrl); JsonArray groupJson = null; @@ -298,7 +191,6 @@ private void doLongPolling(final String server) { String message = String.format("listener configs fail, server:[%s], %s", server, e.getMessage()); throw new SoulException(message, e); } - if (groupJson != null) { // fetch group configuration async. ConfigGroupEnum[] changedGroups = GSON.fromJson(groupJson, ConfigGroupEnum[].class); @@ -352,14 +244,4 @@ public void run() { log.warn("Stop http long polling."); } } - - private static final class ResultHolder { - - private boolean result; - - ResultHolder(final boolean result) { - this.result = result; - } - } - } diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/config/HttpConfig.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/config/HttpConfig.java index f4c3f7efa678..f7c3c82642d1 100644 --- a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/config/HttpConfig.java +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/config/HttpConfig.java @@ -19,6 +19,9 @@ import lombok.Data; +/** + * The type Http config. + */ @Data public class HttpConfig { diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/handler/HttpSyncDataHandler.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/handler/HttpSyncDataHandler.java deleted file mode 100644 index 652827f54ace..000000000000 --- a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/handler/HttpSyncDataHandler.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.dromara.soul.sync.data.http.handler; - -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.dromara.soul.common.dto.AppAuthData; -import org.dromara.soul.common.dto.MetaData; -import org.dromara.soul.common.dto.PluginData; -import org.dromara.soul.common.dto.RuleData; -import org.dromara.soul.common.dto.SelectorData; -import org.dromara.soul.sync.data.api.AuthDataSubscriber; -import org.dromara.soul.sync.data.api.MetaDataSubscriber; -import org.dromara.soul.sync.data.api.PluginDataSubscriber; - -import java.util.List; - -/** - * The type Http cache handler. - * - * @author xiaoyu(Myth) - */ -@Slf4j -public class HttpSyncDataHandler { - - private final PluginDataSubscriber pluginDataSubscriber; - - private final List metaDataSubscribers; - - private final List authDataSubscribers; - - /** - * Instantiates a new Http sync data handler. - * - * @param metaDataSubscribers the meta data subscribers - * @param authDataSubscribers the auth data subscribers - */ - public HttpSyncDataHandler(final PluginDataSubscriber pluginDataSubscriber, - final List metaDataSubscribers, - final List authDataSubscribers) { - this.pluginDataSubscriber = pluginDataSubscriber; - this.metaDataSubscribers = metaDataSubscribers; - this.authDataSubscribers = authDataSubscribers; - } - - /** - * Flush all plugin. If the collection is empty, the cache will be emptied. - * - * @param pluginDataList the plugin config - */ - public void flushAllPlugin(final List pluginDataList) { - if (CollectionUtils.isEmpty(pluginDataList)) { - log.info("clear all plugin data cache"); - pluginDataSubscriber.refreshPluginDataAll(); - } else { - pluginDataSubscriber.refreshPluginDataAll(); - pluginDataList.forEach(pluginDataSubscriber::onSubscribe); - } - } - - /** - * Flush all selector. - * - * @param selectorDataList the selector config - */ - public void flushAllSelector(final List selectorDataList) { - if (CollectionUtils.isEmpty(selectorDataList)) { - log.info("clear all selector cache, old cache"); - selectorDataList.forEach(pluginDataSubscriber::unSelectorSubscribe); - pluginDataSubscriber.refreshSelectorDataAll(); - } else { - // update cache for UpstreamCacheManager - pluginDataSubscriber.refreshSelectorDataAll(); - selectorDataList.forEach(pluginDataSubscriber::onSelectorSubscribe); - } - } - - /** - * Flush all rule. - * - * @param ruleDataList the rule config - */ - public void flushAllRule(final List ruleDataList) { - if (CollectionUtils.isEmpty(ruleDataList)) { - log.info("clear all rule cache"); - pluginDataSubscriber.refreshRuleDataAll(); - } else { - pluginDataSubscriber.refreshRuleDataAll(); - ruleDataList.forEach(pluginDataSubscriber::onRuleSubscribe); - } - } - - /** - * Flush all app auth. - * - * @param appAuthDataList the app auth config - */ - public void flushAllAppAuth(final List appAuthDataList) { - if (CollectionUtils.isEmpty(appAuthDataList)) { - log.info("clear all appAuth data cache"); - authDataSubscribers.forEach(AuthDataSubscriber::refresh); - } else { - appAuthDataList.forEach(authData -> authDataSubscribers.forEach(subscriber -> subscriber.onSubscribe(authData))); - } - } - - /** - * Flush meta data. - * - * @param metaDataList the meta data list - */ - public void flushMetaData(final List metaDataList) { - if (CollectionUtils.isEmpty(metaDataList)) { - log.info("clear all metaData cache"); - metaDataSubscribers.forEach(MetaDataSubscriber::refresh); - } else { - metaDataList.forEach(metaData -> metaDataSubscribers.forEach(subscriber -> subscriber.onSubscribe(metaData))); - } - } -} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AbstractDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AbstractDataRefresh.java new file mode 100644 index 000000000000..656021354ec5 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AbstractDataRefresh.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.enums.ConfigGroupEnum; + +/** + * The type Abstract data refresh. + * + * @param the type parameter + */ +@Slf4j +public abstract class AbstractDataRefresh implements DataRefresh { + + /** + * The Group cache. + */ + protected static final ConcurrentMap> GROUP_CACHE = new ConcurrentHashMap<>(); + + /** + * The constant GSON. + */ + protected static final Gson GSON = new Gson(); + + /** + * Convert json object. + * + * @param data the data + * @return the json object + */ + protected abstract JsonObject convert(JsonObject data); + + /** + * From json config data. + * + * @param data the data + * @return the config data + */ + protected abstract ConfigData fromJson(JsonObject data); + + /** + * Refresh. + * + * @param data the data + */ + protected abstract void refresh(List data); + + @Override + public Boolean refresh(final JsonObject data) { + boolean updated = false; + JsonObject jsonObject = convert(data); + if (null != jsonObject) { + ConfigData result = fromJson(jsonObject); + if (this.updateCacheIfNeed(result)) { + updated = true; + refresh(result.getData()); + } + } + return updated; + } + + /** + * Update cache if need boolean. + * + * @param result the result + * @return the boolean + */ + protected abstract boolean updateCacheIfNeed(ConfigData result); + + /** + * If the MD5 values are different and the last update time of the old data is less than + * the last update time of the new data, the configuration cache is considered to have been changed. + * + * @param newVal the lasted config + * @param groupEnum the group enum + * @return true : if need update + */ + protected boolean updateCacheIfNeed(final ConfigData newVal, final ConfigGroupEnum groupEnum) { + // first init cache + if (GROUP_CACHE.putIfAbsent(groupEnum, newVal) == null) { + return true; + } + ResultHolder holder = new ResultHolder(false); + GROUP_CACHE.merge(groupEnum, newVal, (oldVal, value) -> { + // must compare the last update time + if (!StringUtils.equals(oldVal.getMd5(), newVal.getMd5()) && oldVal.getLastModifyTime() < newVal.getLastModifyTime()) { + log.info("update {} config: {}", groupEnum, newVal); + holder.result = true; + return newVal; + } + log.info("Get the same config, the [{}] config cache will not be updated, md5:{}", groupEnum, oldVal.getMd5()); + return oldVal; + }); + return holder.result; + } + + private static final class ResultHolder { + + private boolean result; + + /** + * Instantiates a new Result holder. + * + * @param result the result + */ + ResultHolder(final boolean result) { + this.result = result; + } + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AppAuthDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AppAuthDataRefresh.java new file mode 100644 index 000000000000..eb7eb5f48a1f --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/AppAuthDataRefresh.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.soul.common.dto.AppAuthData; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.AuthDataSubscriber; + +/** + * The type app auth data refresh. + */ +@Slf4j +@RequiredArgsConstructor +public class AppAuthDataRefresh extends AbstractDataRefresh { + + private final List authDataSubscribers; + + @Override + protected JsonObject convert(final JsonObject data) { + return data.getAsJsonObject(ConfigGroupEnum.APP_AUTH.name()); + } + + @Override + protected ConfigData fromJson(final JsonObject data) { + return GSON.fromJson(data, new TypeToken>() { + }.getType()); + } + + @Override + protected boolean updateCacheIfNeed(final ConfigData result) { + return updateCacheIfNeed(result, ConfigGroupEnum.APP_AUTH); + } + + @Override + public ConfigData cacheConfigData() { + return GROUP_CACHE.get(ConfigGroupEnum.APP_AUTH); + } + + @Override + protected void refresh(final List data) { + if (CollectionUtils.isEmpty(data)) { + log.info("clear all appAuth data cache"); + authDataSubscribers.forEach(AuthDataSubscriber::refresh); + } else { + data.forEach(authData -> authDataSubscribers.forEach(subscriber -> subscriber.onSubscribe(authData))); + } + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefresh.java new file mode 100644 index 000000000000..044d3355e064 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefresh.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import org.dromara.soul.common.dto.ConfigData; + +/** + * The interface Data refresh. + */ +public interface DataRefresh { + + /** + * Refresh boolean. + * + * @param data the data + * @return the boolean + */ + Boolean refresh(JsonObject data); + + /** + * Cache config data config data. + * + * @return the config data + */ + ConfigData cacheConfigData(); +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefreshFactory.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefreshFactory.java new file mode 100644 index 000000000000..c5c1c5b11b89 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/DataRefreshFactory.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import java.util.EnumMap; +import java.util.List; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.AuthDataSubscriber; +import org.dromara.soul.sync.data.api.MetaDataSubscriber; +import org.dromara.soul.sync.data.api.PluginDataSubscriber; + +/** + * The type Data refresh factory. + */ +public final class DataRefreshFactory { + + private static final EnumMap ENUM_MAP = new EnumMap<>(ConfigGroupEnum.class); + + /** + * Instantiates a new Data refresh factory. + * + * @param pluginDataSubscriber the plugin data subscriber + * @param metaDataSubscribers the meta data subscribers + * @param authDataSubscribers the auth data subscribers + */ + public DataRefreshFactory(final PluginDataSubscriber pluginDataSubscriber, + final List metaDataSubscribers, + final List authDataSubscribers) { + ENUM_MAP.put(ConfigGroupEnum.PLUGIN, new PluginDataRefresh(pluginDataSubscriber)); + ENUM_MAP.put(ConfigGroupEnum.SELECTOR, new SelectorDataRefresh(pluginDataSubscriber)); + ENUM_MAP.put(ConfigGroupEnum.RULE, new RuleDataRefresh(pluginDataSubscriber)); + ENUM_MAP.put(ConfigGroupEnum.APP_AUTH, new AppAuthDataRefresh(authDataSubscribers)); + ENUM_MAP.put(ConfigGroupEnum.META_DATA, new MetaDataRefresh(metaDataSubscribers)); + } + + /** + * Executor. + * + * @param data the data + * @return the boolean + */ + public boolean executor(final JsonObject data) { + final boolean[] success = {false}; + ENUM_MAP.values().parallelStream().forEach(dataRefresh -> success[0] = dataRefresh.refresh(data)); + return success[0]; + } + + /** + * Cache config data. + * + * @param group the group + * @return the config data + */ + public ConfigData cacheConfigData(final ConfigGroupEnum group) { + return ENUM_MAP.get(group).cacheConfigData(); + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/MetaDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/MetaDataRefresh.java new file mode 100644 index 000000000000..4bc1fb39fe23 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/MetaDataRefresh.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.dto.MetaData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.MetaDataSubscriber; + +/** + * The type meta data refresh. + */ +@Slf4j +@RequiredArgsConstructor +public class MetaDataRefresh extends AbstractDataRefresh { + + private final List metaDataSubscribers; + + @Override + protected JsonObject convert(final JsonObject data) { + return data.getAsJsonObject(ConfigGroupEnum.META_DATA.name()); + } + + @Override + protected ConfigData fromJson(final JsonObject data) { + return GSON.fromJson(data, new TypeToken>() { + }.getType()); + } + + @Override + protected boolean updateCacheIfNeed(final ConfigData result) { + return updateCacheIfNeed(result, ConfigGroupEnum.META_DATA); + } + + @Override + public ConfigData cacheConfigData() { + return GROUP_CACHE.get(ConfigGroupEnum.META_DATA); + } + + @Override + protected void refresh(final List data) { + if (CollectionUtils.isEmpty(data)) { + log.info("clear all metaData cache"); + metaDataSubscribers.forEach(MetaDataSubscriber::refresh); + } else { + data.forEach(metaData -> metaDataSubscribers.forEach(subscriber -> subscriber.onSubscribe(metaData))); + } + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/PluginDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/PluginDataRefresh.java new file mode 100644 index 000000000000..a73738994985 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/PluginDataRefresh.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.dto.PluginData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.PluginDataSubscriber; + +/** + * The type Plugin data refresh. + */ +@Slf4j +@RequiredArgsConstructor +public class PluginDataRefresh extends AbstractDataRefresh { + + private final PluginDataSubscriber pluginDataSubscriber; + + @Override + protected JsonObject convert(final JsonObject data) { + return data.getAsJsonObject(ConfigGroupEnum.PLUGIN.name()); + } + + @Override + protected ConfigData fromJson(final JsonObject data) { + return GSON.fromJson(data, new TypeToken>() { + }.getType()); + } + + @Override + protected boolean updateCacheIfNeed(final ConfigData result) { + return updateCacheIfNeed(result, ConfigGroupEnum.PLUGIN); + } + + @Override + public ConfigData cacheConfigData() { + return GROUP_CACHE.get(ConfigGroupEnum.PLUGIN); + } + + @Override + protected void refresh(final List data) { + if (CollectionUtils.isEmpty(data)) { + log.info("clear all plugin data cache"); + pluginDataSubscriber.refreshPluginDataAll(); + } else { + pluginDataSubscriber.refreshPluginDataAll(); + data.forEach(pluginDataSubscriber::onSubscribe); + } + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/RuleDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/RuleDataRefresh.java new file mode 100644 index 000000000000..b7286db3d97a --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/RuleDataRefresh.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.dto.RuleData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.PluginDataSubscriber; + +/** + * The type Rule data refresh. + */ +@Slf4j +@RequiredArgsConstructor +public class RuleDataRefresh extends AbstractDataRefresh { + + private final PluginDataSubscriber pluginDataSubscriber; + + @Override + protected JsonObject convert(final JsonObject data) { + return data.getAsJsonObject(ConfigGroupEnum.RULE.name()); + } + + @Override + protected ConfigData fromJson(final JsonObject data) { + return GSON.fromJson(data, new TypeToken>() { + }.getType()); + } + + @Override + protected boolean updateCacheIfNeed(final ConfigData result) { + return updateCacheIfNeed(result, ConfigGroupEnum.RULE); + } + + @Override + public ConfigData cacheConfigData() { + return GROUP_CACHE.get(ConfigGroupEnum.RULE); + } + + @Override + protected void refresh(final List data) { + if (CollectionUtils.isEmpty(data)) { + log.info("clear all rule cache, old cache"); + data.forEach(pluginDataSubscriber::unRuleSubscribe); + pluginDataSubscriber.refreshRuleDataAll(); + } else { + // update cache for UpstreamCacheManager + pluginDataSubscriber.refreshRuleDataAll(); + data.forEach(pluginDataSubscriber::onRuleSubscribe); + } + } +} diff --git a/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/SelectorDataRefresh.java b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/SelectorDataRefresh.java new file mode 100644 index 000000000000..cc385ee115e2 --- /dev/null +++ b/soul-sync-data-center/soul-sync-data-http/src/main/java/org/dromara/soul/sync/data/http/refresh/SelectorDataRefresh.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.soul.sync.data.http.refresh; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.soul.common.dto.ConfigData; +import org.dromara.soul.common.dto.SelectorData; +import org.dromara.soul.common.enums.ConfigGroupEnum; +import org.dromara.soul.sync.data.api.PluginDataSubscriber; + +/** + * The type Selector data refresh. + */ +@Slf4j +@RequiredArgsConstructor +public class SelectorDataRefresh extends AbstractDataRefresh { + + private final PluginDataSubscriber pluginDataSubscriber; + + @Override + protected JsonObject convert(final JsonObject data) { + return data.getAsJsonObject(ConfigGroupEnum.SELECTOR.name()); + } + + @Override + protected ConfigData fromJson(final JsonObject data) { + return GSON.fromJson(data, new TypeToken>() { + }.getType()); + } + + @Override + protected boolean updateCacheIfNeed(final ConfigData result) { + return updateCacheIfNeed(result, ConfigGroupEnum.SELECTOR); + } + + @Override + public ConfigData cacheConfigData() { + return GROUP_CACHE.get(ConfigGroupEnum.SELECTOR); + } + + @Override + protected void refresh(final List data) { + if (CollectionUtils.isEmpty(data)) { + log.info("clear all selector cache, old cache"); + data.forEach(pluginDataSubscriber::unSelectorSubscribe); + pluginDataSubscriber.refreshSelectorDataAll(); + } else { + // update cache for UpstreamCacheManager + pluginDataSubscriber.refreshSelectorDataAll(); + data.forEach(pluginDataSubscriber::onSelectorSubscribe); + } + } +}