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

com.github.likavn.eventbus.provider.redis.RedisZSetPushMsgStreamTask Maven / Gradle / Ivy

There is a newer version: 2.5.0-RC3
Show newest version
/**
 * Copyright 2023-2033, likavn ([email protected]).
 * 

* Licensed 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 com.github.likavn.eventbus.provider.redis; import com.github.likavn.eventbus.core.ListenerRegistry; import com.github.likavn.eventbus.core.TaskRegistry; import com.github.likavn.eventbus.core.base.Lifecycle; import com.github.likavn.eventbus.core.support.task.PeriodTask; import com.github.likavn.eventbus.core.utils.Func; import com.github.likavn.eventbus.provider.redis.support.RedisListener; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import java.util.*; import java.util.stream.Collectors; /** * redis 推送zset消息至stream队列任务 * * @author likavn * @since 2023/01/01 **/ @Slf4j public class RedisZSetPushMsgStreamTask implements Lifecycle { /** * 最大轮询时间间隔,单位:毫秒 */ private static final long POLL_MILLIS = 1000L * 100; /** * 最大消息推送数量,默认10万条 */ private static final long MAX_PUSH_COUNT = 10000L * 10; private final StringRedisTemplate stringRedisTemplate; private final RLock rLock; private final DefaultRedisScript pushMsgStreamRedisScript; private final TaskRegistry taskRegistry; private final List listeners; private final Set pollLockKeys = Collections.synchronizedSet(new HashSet<>()); private List tasks; public RedisZSetPushMsgStreamTask(StringRedisTemplate stringRedisTemplate, TaskRegistry taskRegistry, DefaultRedisScript pushMsgStreamRedisScript, RLock rLock, ListenerRegistry registry) { this.stringRedisTemplate = stringRedisTemplate; this.taskRegistry = taskRegistry; this.pushMsgStreamRedisScript = pushMsgStreamRedisScript; this.rLock = rLock; this.listeners = Func.distinct(RedisListener.getAllListeners(registry), RedisListener::getZSetKey) .stream() // zSetKey必须配置 .filter(t -> t.getZSetKey() != null) .collect(Collectors.toList()); } @Override public synchronized void register() { this.tasks = listeners.stream().map(t -> { PeriodTask task = PeriodTask.create(t.getZSetKey(), POLL_MILLIS, null); task.setRunnable(() -> pollPushTask(task, t)); return task; }).collect(Collectors.toList()); tasks.forEach(taskRegistry::createTask); } /** * 循环获取延时队列到期消息 */ private void pollPushTask(PeriodTask task, RedisListener listener) { boolean isLock = false; try { isLock = rLock.getLock(listener.getLockKey()); if (!isLock) { return; } pollLockKeys.add(listener.getLockKey()); Long nextCurrentTimeMillis = stringRedisTemplate.execute(pushMsgStreamRedisScript, Arrays.asList(listener.getZSetKey(), listener.getStreamKey()), // 到当前时间之前的消息 + 推送数量 String.valueOf(System.currentTimeMillis()), String.valueOf(MAX_PUSH_COUNT)); // 重置轮询时间 if (null != nextCurrentTimeMillis) { task.refreshNextExecutionTime(nextCurrentTimeMillis); } } finally { if (isLock) { rLock.releaseLock(listener.getLockKey()); pollLockKeys.remove(listener.getLockKey()); } } } @Override public void destroy() { // 释放锁 Iterator iterator = pollLockKeys.iterator(); while (iterator.hasNext()) { String pollLockKey = iterator.next(); try { rLock.releaseLock(pollLockKey); } catch (Exception e) { log.error("release pollLockKey error", e); } iterator.remove(); } tasks.forEach(taskRegistry::removeTask); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy