| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- import { writeFileSync, readFileSync } from 'fs';
- function u(s) {
- return s.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
- }
- const support = u(`package com.fs.company.service.easycall;
- import cn.hutool.core.util.RandomUtil;
- import cn.hutool.json.JSONUtil;
- import com.fs.company.domain.CompanyWxAccount;
- import com.fs.company.mapper.CompanyWxAccountMapper;
- import com.fs.company.param.ExecutionContext;
- import com.fs.course.config.WxConfig;
- import com.fs.system.service.ISysConfigService;
- import lombok.Data;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- import java.time.ZoneId;
- import java.time.temporal.ChronoUnit;
- /**
- * \u4e2a\u5fae\u52a0\u597d\u53cb\u9891\u7387\u6821\u9a8c\uff0c\u652f\u6301\u9ad8\u5e76\u53d1\u4e0b\u8d26\u53f7\u7ea7\u539f\u5b50\u62a2\u5360\u3002
- */
- @Slf4j
- @Component
- public class WxAddWxFrequencySupport {
- @Autowired
- private ISysConfigService sysConfigService;
- @Autowired
- private CompanyWxAccountMapper companyWxAccountMapper;
- @Autowired
- private WxAddWxFrequencyRedisHelper redisHelper;
- @Data
- public static class FrequencyCheckResult {
- private boolean canAddNow;
- private long waitMinutes;
- private long waitMillis;
- private String reason;
- public static FrequencyCheckResult ready() {
- FrequencyCheckResult result = new FrequencyCheckResult();
- result.canAddNow = true;
- result.waitMinutes = 0;
- result.waitMillis = 0;
- return result;
- }
- public static FrequencyCheckResult wait(long waitMinutes, String reason) {
- return waitMillis(Math.max(1, waitMinutes) * 60_000L, reason);
- }
- public static FrequencyCheckResult waitMillis(long waitMillis, String reason) {
- FrequencyCheckResult result = new FrequencyCheckResult();
- result.canAddNow = false;
- result.waitMillis = Math.max(1000L, waitMillis);
- result.waitMinutes = (result.waitMillis + 59_999L) / 60_000L;
- result.reason = reason;
- return result;
- }
- }
- public WxConfig loadWxConfig() {
- String json = sysConfigService.selectConfigByKey("wx.config");
- if (json == null || json.isEmpty()) {
- throw new IllegalStateException("\u672a\u914d\u7f6e wx.config");
- }
- return JSONUtil.toBean(json, WxConfig.class);
- }
- /**
- * \u539f\u5b50\u62a2\u5360\u52a0\u5fae\u69fd\u4f4d\uff08\u540c\u8d26\u53f7\u4e92\u65a5 + \u9891\u7387 + \u65e5\u9650\uff09\u3002
- */
- public FrequencyCheckResult tryAcquireAddWxSlot(CompanyWxAccount account, String workflowInstanceId) {
- if (account == null) {
- return FrequencyCheckResult.waitMillis(5000L, "\u8d26\u53f7\u4e0d\u5b58\u5728");
- }
- seedRedisStateFromDbIfNeeded(account);
- WxConfig config = loadWxConfig();
- int intervalMinutes = resolveRequiredIntervalMinutes(account, config);
- long intervalMs = intervalMinutes * 60_000L;
- int dailyLimit = account.getAddNum() == null ? Integer.MAX_VALUE : account.getAddNum();
- long midnightWaitMs = ChronoUnit.MILLIS.between(LocalDateTime.now(), LocalDate.now().plusDays(1).atStartOfDay());
- if (midnightWaitMs <= 0) {
- midnightWaitMs = 3600_000L;
- }
- WxAddWxFrequencyRedisHelper.SlotAcquireResult acquireResult = redisHelper.tryAcquireSlot(
- account.getId(), workflowInstanceId, intervalMs, dailyLimit,
- redisHelperSecondsUntilMidnight(), midnightWaitMs);
- if (acquireResult.granted()) {
- return FrequencyCheckResult.ready();
- }
- switch (acquireResult.getCode()) {
- case -1:
- log.info("\u8d26\u53f7 {} \u52a0\u5fae\u9891\u7387\u672a\u5230\uff0c\u7b49\u5f85 {} ms",
- account.getWxNickName(), acquireResult.getWaitMs());
- return FrequencyCheckResult.waitMillis(acquireResult.getWaitMs(), "\u52a0\u5fae\u9891\u7387\u95f4\u9694\u672a\u5230");
- case -2:
- log.info("\u8d26\u53f7 {} \u540c\u8d26\u53f7\u52a0\u5fae\u8fdb\u884c\u4e2d\uff0c\u6392\u961f\u7b49\u5f85 {} ms",
- account.getWxNickName(), acquireResult.getWaitMs());
- return FrequencyCheckResult.waitMillis(acquireResult.getWaitMs(), "\u540c\u8d26\u53f7\u52a0\u5fae\u8fdb\u884c\u4e2d");
- case -3:
- log.info("\u8d26\u53f7 {} \u4eca\u65e5\u52a0\u5fae\u5df2\u8fbe\u4e0a\u9650", account.getWxNickName());
- return FrequencyCheckResult.waitMillis(acquireResult.getWaitMs(), "\u4eca\u65e5\u52a0\u5fae\u6570\u91cf\u5df2\u8fbe\u4e0a\u9650");
- default:
- return FrequencyCheckResult.waitMillis(acquireResult.getWaitMs(), "\u52a0\u5fae\u6392\u961f\u7b49\u5f85");
- }
- }
- /**
- * \u53d1\u8d77\u52a0\u5fae\u8bf7\u6c42\u540e\u66f4\u65b0\u6570\u636e\u5e93\u5e76\u91ca\u653e\u8fdb\u884c\u4e2d\u9501\u3002
- */
- public void markAddWxSent(Long accountId) {
- if (accountId == null) {
- return;
- }
- CompanyWxAccount account = companyWxAccountMapper.selectCompanyWxAccountById(accountId);
- if (account != null) {
- account.setLastAddWxTime(LocalDateTime.now());
- int current = account.getIsAddNum() == null ? 0 : account.getIsAddNum();
- account.setIsAddNum(current + 1);
- companyWxAccountMapper.updateCompanyWxAccount(account);
- }
- redisHelper.releaseInflight(accountId);
- }
- public void releaseInflight(Long accountId) {
- redisHelper.releaseInflight(accountId);
- }
- public void scheduleFrequencyRetry(Integer cidGroupNo, String workflowInstanceId, ExecutionContext context, long retryAtMs) {
- redisHelper.scheduleFrequencyRetry(cidGroupNo, workflowInstanceId, context, retryAtMs);
- }
- public java.util.List<String> popDueFrequencyRetries(Integer cidGroupNo, long nowMs, int batchSize) {
- return redisHelper.popDueFrequencyRetries(cidGroupNo, nowMs, batchSize);
- }
- public ExecutionContext loadFrequencyRetryContext(String workflowInstanceId) {
- return redisHelper.loadFrequencyRetryContext(workflowInstanceId);
- }
- public void clearFrequencyRetry(String workflowInstanceId) {
- redisHelper.clearFrequencyRetry(workflowInstanceId);
- }
- public boolean tryMarkFrequencyProcessing(String workflowInstanceId) {
- return redisHelper.tryMarkFrequencyProcessing(workflowInstanceId);
- }
- public void clearFrequencyProcessing(String workflowInstanceId) {
- redisHelper.clearFrequencyProcessing(workflowInstanceId);
- }
- private void seedRedisStateFromDbIfNeeded(CompanyWxAccount account) {
- if (account.getIsAddNum() != null && account.getIsAddNum() > 0) {
- redisHelper.seedDailyCount(account.getId(), account.getIsAddNum());
- }
- if (account.getLastAddWxTime() == null) {
- return;
- }
- WxConfig config = loadWxConfig();
- int minute = resolveRequiredIntervalMinutes(account, config);
- long elapsed = account.getLastAddWxTime().until(LocalDateTime.now(), ChronoUnit.MINUTES);
- if (elapsed <= minute) {
- long nextAllowed = account.getLastAddWxTime().plusMinutes(minute + 1L)
- .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
- redisHelper.seedNextSlot(account.getId(), nextAllowed);
- }
- }
- private int redisHelperSecondsUntilMidnight() {
- long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), LocalDate.now().plusDays(1).atStartOfDay());
- return (int) Math.max(seconds + 60, 3600);
- }
- private int resolveRequiredIntervalMinutes(CompanyWxAccount account, WxConfig config) {
- if (Integer.valueOf(0).equals(account.getIsNew())) {
- return RandomUtil.randomInt(config.getNewAccountAddWxMin(), config.getNewAccountAddWxMax());
- }
- return RandomUtil.randomInt(config.getAccountAddWxMin(), config.getAccountAddWxMax());
- }
- }
- `);
- writeFileSync('src/main/java/com/fs/company/service/easycall/WxAddWxFrequencySupport.java', support, 'utf8');
- const redisHelperPath = 'src/main/java/com/fs/company/service/easycall/WxAddWxFrequencyRedisHelper.java';
- let redisHelper = readFileSync(redisHelperPath, 'utf8');
- redisHelper = redisHelper.replace(
- /\/\*\*[\s\S]*?\*\/\s*@Component\s*public class WxAddWxFrequencyRedisHelper/,
- u(`/**
- * \u4e2a\u5fae\u52a0\u5fae\u9891\u7387 Redis \u539f\u5b50\u64cd\u4f5c\uff08\u8d26\u53f7\u7ea7\u4e92\u65a5\u3001\u9891\u7387\u69fd\u4f4d\u3001\u5ef6\u65f6\u961f\u5217\uff09\u3002
- */
- @Component
- public class WxAddWxFrequencyRedisHelper`)
- );
- writeFileSync(redisHelperPath, redisHelper, 'utf8');
- console.log('fixed WxAddWxFrequencySupport.java and WxAddWxFrequencyRedisHelper.java javadoc');
|