public interface EventEngine {
/**
* 异步发送事件
*
* @param event
*/
public void publishEvent(BizEvent event);
}
public class EventEngineImpl implements EventEngine {
/**
* 异步执行器。也系统需要自行定义线程池
*/
private Executor bizListenerExecutor;
/**
* 是否异步,默认为false
*/
private boolean async;
/**
* 订阅端 KEY是TOPIC,VALUES是监听器集合
*/
private Map<String, List<BizEventListener>> bizSubscribers = Maps.newHashMap();
@Override
public void publishEvent(BizEvent event) {
List<BizEventListener> listeners = bizSubscribers.get(event.getTopic());
if (CollectionUtil.isEmpty(listeners)) {
return;
}
for (BizEventListener bizEventListener : listeners) {
if (bizEventListener.decide(event)) {
if (async) {
bizListenerExecutor.execute(new EventSubscriber(bizEventListener, event));
} else {
bizEventListener.onEvent(event);
}
}
}
}
/**
* Setter method for property <tt>bizListenerExecutor</tt>.
*
* @param bizListenerExecutor value to be assigned to property bizListenerExecutor
*/
public void setBizListenerExecutor(Executor bizListenerExecutor) {
this.bizListenerExecutor = bizListenerExecutor;
}
/**
* Setter method for property <tt>bizSubscribers</tt>.
*
* @param bizSubscribers value to be assigned to property bizSubscribers
*/
public void setBizSubscribers(Map<String, List<BizEventListener>> bizSubscribers) {
this.bizSubscribers = bizSubscribers;
}
/**
* Setter method for property <tt>async</tt>.
*
* @param async value to be assigned to property async
*/
public void setAsync(boolean async) {
this.async = async;
}
}
@Configuration
public class EventEngineConfig {
@Bean("eventRefreshAvatarJob")
public EventEngine initAvatarEngine(RefreshAvatarEventListener avatarEventListener){
Map<String, List<BizEventListener>> bizEvenListenerMap = new HashMap<>();
bizEvenListenerMap.put(EventEngineTopic.USER_AVATAR, Arrays.asList(avatarEventListener));
Executor executor = new ThreadPoolExecutor(1, 1, 10, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1), new NamedThreadFactory("ding-avatar-pool-%d"), new ThreadPoolExecutor.AbortPolicy());
EventEngineImpl eventEngine = new EventEngineImpl();
eventEngine.setBizSubscribers(bizEvenListenerMap);
eventEngine.setAsync(true);
eventEngine.setBizListenerExecutor(executor);
return eventEngine;
}
@Bean("eventEngine")
public EventEngine initEventEngine(ProductStatEventListener productStatEventListener
) {
Map<String, List<BizEventListener>> bizEvenListenerMap = new HashMap<>();
bizEvenListenerMap.put(EventEngineTopic.TOPIC_PRODUCT_STAT, Arrays.asList(productStatEventListener));
Executor executor = new ThreadPoolExecutor(20, 50, 10, TimeUnit.MINUTES, new LinkedBlockingQueue(500),
new NamedThreadFactory("EVENT_ENGINE_POOL"));
EventEngineImpl eventEngine = new EventEngineImpl();
eventEngine.setBizSubscribers(bizEvenListenerMap);
eventEngine.setAsync(true);
eventEngine.setBizListenerExecutor(executor);
return eventEngine;
}
@Bean("eventEngineJob")
public EventEngine initJobEngine(ProductStatScheduleListener productStatScheduleListener,
DeviceScanListener deviceScanListener,
DpDeviceScanListener dpDeviceScanListener,
DeathRateCheckListener deathRateCheckListener,
IndexStatCheckListener indexStatCheckListener) {
Map<String, List<BizEventListener>> bizEvenListenerMap = new HashMap<>();
bizEvenListenerMap.put(EventEngineTopic.TOPIC_PRODUCE_STAT_SCHEDULE, Arrays.asList(productStatScheduleListener));
bizEvenListenerMap.put(EventEngineTopic.TOPIC_DEVICE_SCAN, Arrays.asList(deviceScanListener));
bizEvenListenerMap.put(EventEngineTopic.DP_TOPIC_DEVICE_SCAN, Arrays.asList(dpDeviceScanListener));
bizEvenListenerMap.put(EventEngineTopic.DEATH_RATE_CHECK_SCAN, Arrays.asList(deathRateCheckListener));
bizEvenListenerMap.put(EventEngineTopic.INDEX_STAT_CHECK_SCAN, Arrays.asList(indexStatCheckListener));
Executor executor = new ThreadPoolExecutor(20, 50, 10, TimeUnit.MINUTES, new LinkedBlockingQueue(500),
new NamedThreadFactory("EVENT_ENGINE_POOL"));
EventEngineImpl eventEngine = new EventEngineImpl();
eventEngine.setBizSubscribers(bizEvenListenerMap);
eventEngine.setAsync(true);
eventEngine.setBizListenerExecutor(executor);
return eventEngine;
}
}
/**
* 业务事件监听器
*
*/
public interface BizEventListener extends EventListener {
/**
* 决策是否执行事件
*
* @param event 事件
* @return
*/
public boolean decide(BizEvent event);
/**
* 执行事件
*
* @param event 事件
*/
public void onEvent(BizEvent event);
}
@Slf4j
@Component
public class RefreshAvatarEventListener implements BizEventListener {
@Autowired
private DaUserRepository daUserRepository;
@Autowired
private DingDingApiService dingDingApiService;
/**
* 决策是否执行事件
*
* @param event 事件
* @return
*/
@Override
public boolean decide(BizEvent event) {
return !CollectionUtils.isEmpty((List<DaUserDO>) event.getData());
}
/**
* 执行事件
*
* @param event 事件
*/
@Override
public void onEvent(BizEvent event) {
log.info("--------------------->收到刷新用户头像事件");
refreshAvatar(event);
}
private boolean refreshAvatar(BizEvent event) {
List<DaUserDO> noAvatarUsers = (List<DaUserDO>) event.getData();
List<DaUserDO> avatarUsers = new ArrayList<>();
noAvatarUsers.forEach(user -> {
String avatar = dingDingApiService.getDingDingUserAvatar(user.getInstId(), user.getId()).getValue();
if (StringUtils.isNotBlank(avatar)) {
user.setPhotoUrl(avatar);
avatarUsers.add(user);
}
}
);
return daUserRepository.updateBatchById(avatarUsers);
}
}
@Slf4j
@Component
public class RefreshUserAvatarJob extends JavaProcessor {
@Resource(name = "eventRefreshAvatarJob")
private EventEngine eventEngine;
@Autowired
private DaUserRepository daUserRepository;
@Override
public ProcessResult process(JobContext jobContext) throws Exception {
LogUtil.info(log, "收到RefreshUserAvatarJob处理请求");
List<DaUserDO> noAvatarUsers = daUserRepository.list(new LambdaQueryWrapper<DaUserDO>().isNull(DaUserDO::getPhotoUrl));
eventEngine.publishEvent(new BizEvent(EventEngineTopic.USER_AVATAR, null, noAvatarUsers));
return new ProcessResult(true);
}
}