package com.hqyg.disjob.register.rpc;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.hqyg.disjob.common.util.LoggerUtil;
import com.hqyg.disjob.rpc.client.HURL;
import com.hqyg.disjob.rpc.client.HURLParamType;
/**
*
* <pre>
*
* File: FailbackRegistry.java
*
* Copyright (c) 2016, globalegrow.com All Rights Reserved.
*
* Description:
* 注册发现失败接口
*
* Revision History
* Date, Who, What;
* 2016年5月16日 Disjob Initial.
*
* </pre>
*/
public abstract class FailbackRegistry extends AbstractRegistry {
private Set<HURL> failedRegistered = new ConcurrentHashSet<HURL>();
private Set<HURL> failedUnregistered = new ConcurrentHashSet<HURL>();
private ConcurrentHashMap<HURL, ConcurrentHashSet<NotifyListener>> failedSubscribed =
new ConcurrentHashMap<HURL, ConcurrentHashSet<NotifyListener>>();
private ConcurrentHashMap<HURL, ConcurrentHashSet<NotifyListener>> failedUnsubscribed =
new ConcurrentHashMap<HURL, ConcurrentHashSet<NotifyListener>>();
private static ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1);
public FailbackRegistry(HURL url) {
super();
long retryPeriod = url.getIntParameter(HURLParamType.registryRetryPeriod.getName(), HURLParamType.registryRetryPeriod.getIntValue());
retryExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
retry();
} catch (Exception e) {
LoggerUtil.warn(String.format("[%s] False when retry in failback registry", registryClassName), e);
}
}
}, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
}
public void register(HURL url){
}
/**
* 调用模板订阅处理,若失败会将失败的内容存入内存重试直到成功
*/
@Override
public void subscribe(HURL url, NotifyListener listener) {
removeForFailedSubAndUnsub(url, listener);
try {
super.subscribe(url, listener);
} catch (Exception e) {
addToFailedMap(failedSubscribed, url, listener);
}
}
/**
* 取消订阅,暂未实现
*/
@Override
public void unsubscribe(HURL url, NotifyListener listener) {
removeForFailedSubAndUnsub(url, listener);
try {
super.unsubscribe(url, listener);
} catch (Exception e) {
/*if (isCheckingUrls(getUrl(), url)) {
throw new EjobFrameWorkException(String.format("[%s] false to unsubscribe %s from %s", registryClassName, url, getUrl()),
e);
}*/
addToFailedMap(failedUnsubscribed, url, listener);
}
}
@Override
@SuppressWarnings("unchecked")
public List<HURL> discover(HURL url) {
try {
return super.discover(url);
} catch (Exception e) {
// 如果discover失败,返回一个empty list吧,毕竟是个下行动作,
LoggerUtil.warn(String.format("Failed to discover url:%s ", url), e);
return Collections.EMPTY_LIST;
}
}
private boolean isCheckingUrls(HURL... urls) {
for (HURL url : urls) {
if (!Boolean.parseBoolean(url.getParameter(HURLParamType.check.getName(), HURLParamType.check.getValue()))) {
return false;
}
}
return true;
}
private void removeForFailedSubAndUnsub(HURL url, NotifyListener listener) {
Set<NotifyListener> listeners = failedSubscribed.get(url);
if (listeners != null) {
listeners.remove(listener);
}
listeners = failedUnsubscribed.get(url);
if (listeners != null) {
listeners.remove(listener);
}
}
private void addToFailedMap(ConcurrentHashMap<HURL, ConcurrentHashSet<NotifyListener>> failedMap, HURL url, NotifyListener listener) {
Set<NotifyListener> listeners = failedMap.get(url);
if (listeners == null) {
failedMap.putIfAbsent(url, new ConcurrentHashSet<NotifyListener>());
listeners = failedMap.get(url);
}
listeners.add(listener);
}
private void retry() {
if (!failedRegistered.isEmpty()) {
Set<HURL> failed = new HashSet<HURL>(failedRegistered);
LoggerUtil.info("[{}] Retry register {}", registryClassName, failed);
try {
for (HURL url : failed) {
super.register(url);
failedRegistered.remove(url);
}
} catch (Exception e) {
LoggerUtil.warn(String.format("[%s] Failed to retry register, retry later, failedRegistered.size=%s, cause=%s",
registryClassName, failedRegistered.size(), e.getMessage()), e);
}
}
if (!failedUnregistered.isEmpty()) {
Set<HURL> failed = new HashSet<HURL>(failedUnregistered);
LoggerUtil.info("[{}] Retry unregister {}", registryClassName, failed);
try {
for (HURL url : failed) {
super.unregister(url);
failedUnregistered.remove(url);
}
} catch (Exception e) {
LoggerUtil.warn(String.format("[%s] Failed to retry unregister, retry later, failedUnregistered.size=%s, cause=%s",
registryClassName, failedUnregistered.size(), e.getMessage()), e);
}
}
if (!failedSubscribed.isEmpty()) {
Map<HURL, Set<NotifyListener>> failed = new HashMap<HURL, Set<NotifyListener>>(failedSubscribed);
for (Map.Entry<HURL, Set<NotifyListener>> entry : new HashMap<HURL, Set<NotifyListener>>(failed).entrySet()) {
if (entry.getValue() == null || entry.getValue().size() == 0) {
failed.remove(entry.getKey());
}
}
if (failed.size() > 0) {
LoggerUtil.info("[{}] Retry subscribe {}", registryClassName, failed);
try {
for (Map.Entry<HURL, Set<NotifyListener>> entry : failed.entrySet()) {
HURL url = entry.getKey();
Set<NotifyListener> listeners = entry.getValue();
for (NotifyListener listener : listeners) {
super.subscribe(url, listener);
listeners.remove(listener);
}
}
} catch (Exception e) {
LoggerUtil.warn(String.format("[%s] Failed to retry subscribe, retry later, failedSubscribed.size=%s, cause=%s",
registryClassName, failedSubscribed.size(), e.getMessage()), e);
}
}
}
if (!failedUnsubscribed.isEmpty()) {
Map<HURL, Set<NotifyListener>> failed = new HashMap<HURL, Set<NotifyListener>>(failedUnsubscribed);
for (Map.Entry<HURL, Set<NotifyListener>> entry : new HashMap<HURL, Set<NotifyListener>>(failed).entrySet()) {
if (entry.getValue() == null || entry.getValue().size() == 0) {
failed.remove(entry.getKey());
}
}
if (failed.size() > 0) {
LoggerUtil.info("[{}] Retry unsubscribe {}", registryClassName, failed);
try {
for (Map.Entry<HURL, Set<NotifyListener>> entry : failed.entrySet()) {
HURL url = entry.getKey();
Set<NotifyListener> listeners = entry.getValue();
for (NotifyListener listener : listeners) {
super.unsubscribe(url, listener);
listeners.remove(listener);
}
}
} catch (Exception e) {
LoggerUtil.warn(String.format("[%s] Failed to retry unsubscribe, retry later, failedUnsubscribed.size=%s, cause=%s",
registryClassName, failedUnsubscribed.size(), e.getMessage()), e);
}
}
}
}
}