add calling list
This commit is contained in:
parent
109532b21a
commit
38c4be39b8
@ -3,10 +3,7 @@ package com.pudonghot.yo.campaign.feign.response;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import com.pudonghot.yo.util.PhoneNumberUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
@ -16,35 +13,25 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@Setter
|
||||
@ToString
|
||||
public class RespCallingList {
|
||||
@JsonProperty("retcode")
|
||||
@JsonAlias("retcode")
|
||||
private String code;
|
||||
@JsonProperty("message")
|
||||
@JsonAlias("message")
|
||||
private String error;
|
||||
|
||||
@JsonProperty("taskid")
|
||||
@JsonAlias("taskid")
|
||||
private String campaignKey;
|
||||
@JsonAlias("taskName")
|
||||
@JsonProperty("taskname")
|
||||
@JsonAlias({"taskName", "taskname"})
|
||||
private String campaignName;
|
||||
@JsonProperty("taskdata")
|
||||
@JsonAlias("taskdata")
|
||||
private CallingData[] data;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class CallingData {
|
||||
@JsonProperty("outid")
|
||||
@JsonAlias("outid")
|
||||
private String caseKey;
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* to pair (phone, caseKey)
|
||||
*
|
||||
* @return pair
|
||||
*/
|
||||
public Pair<String, String> toPair() {
|
||||
return Pair.of(PhoneNumberUtils.cleanupMobile(phone), caseKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.pudonghot.yo.campaign.feign.response;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Jul 22, 2020 14:17:40
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
public class RespCallingListWrapper {
|
||||
private String code;
|
||||
@JsonProperty("message")
|
||||
private String error;
|
||||
private RespCallingList data;
|
||||
|
||||
/**
|
||||
* is response success
|
||||
*
|
||||
* @return true if code == 000000
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return "000000".equals(code);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.pudonghot.yo.campaign.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.pudonghot.yo.model.domain.Campaign;
|
||||
import com.wacai.tigon.service.BaseCrudService;
|
||||
import com.pudonghot.yo.model.domain.CallingList;
|
||||
|
||||
@ -10,6 +11,12 @@ import com.pudonghot.yo.model.domain.CallingList;
|
||||
*/
|
||||
public interface CallingListService extends BaseCrudService<Integer, CallingList> {
|
||||
|
||||
/**
|
||||
* fetch remote calling list
|
||||
* @param campaign campaign
|
||||
*/
|
||||
void fetchRemote(Campaign campaign);
|
||||
|
||||
/**
|
||||
* list limit ready records
|
||||
*
|
||||
@ -17,11 +24,5 @@ public interface CallingListService extends BaseCrudService<Integer, CallingList
|
||||
* @param limit limit
|
||||
* @return CallingLists
|
||||
*/
|
||||
List<CallingList> listReady(final Integer campaignId, final int limit);
|
||||
|
||||
/**
|
||||
* release calling list lock
|
||||
* @param callingList callingList
|
||||
*/
|
||||
void releaseCallingListLock(final CallingList callingList);
|
||||
List<CallingList> listReady(Integer campaignId, int limit);
|
||||
}
|
||||
|
@ -8,4 +8,10 @@ import com.wacai.tigon.service.BaseQueryService;
|
||||
* @date Jul 18, 2020 17:24:50
|
||||
*/
|
||||
public interface CampaignService extends BaseQueryService<Integer, Campaign> {
|
||||
|
||||
/**
|
||||
* dial campaign call
|
||||
* @param campaign campaign
|
||||
*/
|
||||
void dial(final Campaign campaign);
|
||||
}
|
||||
|
@ -3,20 +3,31 @@ package com.pudonghot.yo.campaign.service.impl;
|
||||
import java.util.Map;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import lombok.Setter;
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.pudonghot.yo.util.TimeUtils;
|
||||
import java.util.stream.Collectors;
|
||||
import com.wacai.tigon.mybatis.Search;
|
||||
import com.pudonghot.yo.util.TimeUtils;
|
||||
import com.wacai.tigon.sequence.IdSequence;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.pudonghot.yo.model.domain.Campaign;
|
||||
import com.pudonghot.yo.util.PhoneNumberUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import com.pudonghot.yo.mapper.CallingListMapper;
|
||||
import com.pudonghot.yo.model.domain.CallingList;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import com.pudonghot.yo.campaign.service.CampaignService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import com.pudonghot.yo.campaign.service.CallingListService;
|
||||
import com.wacai.tigon.service.support.BaseCrudServiceSupport;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import com.pudonghot.yo.campaign.feign.response.RespCallingList;
|
||||
import static com.pudonghot.yo.model.domain.Campaign.TargetType.QUEUE;
|
||||
import com.pudonghot.yo.campaign.feign.service.FeignCallingListService;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
@ -28,23 +39,48 @@ public class CallingListServiceImpl
|
||||
extends BaseCrudServiceSupport<Integer, CallingList, CallingListMapper>
|
||||
implements CallingListService {
|
||||
|
||||
@Setter(onMethod_ = {@Lazy, @Autowired})
|
||||
private CampaignService campaignService;
|
||||
@Autowired
|
||||
private IdSequence idSeq;
|
||||
@Autowired
|
||||
private FeignCallingListService callingListService;
|
||||
|
||||
@Value("${yo.br.campaign.callinglist-lock-expire.seconds:300}")
|
||||
@Value("${yo.campaign.calling-list-lock-expire.seconds:300}")
|
||||
private int expireLockDuration;
|
||||
@Value("${yo.campaign.calling-list.fetch-size:24}")
|
||||
private int fetchSize;
|
||||
|
||||
@Scheduled(fixedRateString = "${yo.br.campaign.callinglist-lock-expire.rate:180000}")
|
||||
@Scheduled(fixedRateString = "${yo.campaign.callinglist-lock-expire.rate:120000}")
|
||||
public void expireLock() {
|
||||
log.info("Expire calling list lock task");
|
||||
final Date expireTime = DateUtils.addSeconds(new Date(), -expireLockDuration);
|
||||
scan(new Search(CallingList.ACTIVE, true)
|
||||
.gt(CallingList.CREATED_TIME, DateUtils.addDays(new Date(), -1))
|
||||
.notNull(CallingList.LAST_CONN_ID)
|
||||
.lt(CallingList.LOCK_TIME, expireTime), callingList -> {
|
||||
callingList.setLockTime(null);
|
||||
callingList.setLockKey(null);
|
||||
mapper.update(callingList);
|
||||
log.info("Expire calling list lock task.");
|
||||
final Map<String, Object> update = new HashMap<>(8);
|
||||
update.put(CallingList.LOCK_KEY, null);
|
||||
update.put(CallingList.LOCK_TIME, null);
|
||||
update.put(CallingList.UPDATED_TIME, new Date());
|
||||
|
||||
mapper.update(update,
|
||||
new Search(CallingList.ACTIVE, true)
|
||||
.gt(CallingList.ADDED_TIME, DateUtils.addDays(new Date(), -1))
|
||||
.lt(CallingList.LOCK_TIME,
|
||||
DateUtils.addSeconds(new Date(), -expireLockDuration)));
|
||||
}
|
||||
|
||||
@Scheduled(fixedRateString = "${yo.campaign.task-scheduler.fixed-rate:180000}",
|
||||
initialDelayString = "${yo.campaign.task-scheduler.init-delay:32000}")
|
||||
public void fetchRemoteTaskScheduler() {
|
||||
log.debug("Campaign fetch remote calling list task.");
|
||||
final int secondOfDay = TimeUtils.secondOfDay(new Date());
|
||||
campaignService.scan(new Search(Campaign.ACTIVE, true)
|
||||
.eq(Campaign.STATUS, Campaign.Status.RUNNING)
|
||||
.lt(Campaign.DAILY_FROM, secondOfDay)
|
||||
.gt(Campaign.DAILY_TO, secondOfDay), campaign -> {
|
||||
|
||||
if (campaign.getTargetType() != QUEUE) {
|
||||
log.info("Campaign [{}] target is not queue, ignore.", campaign);
|
||||
return;
|
||||
}
|
||||
fetchRemote(campaign);
|
||||
});
|
||||
}
|
||||
|
||||
@ -52,34 +88,71 @@ public class CallingListServiceImpl
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public List<CallingList> listReady(final Integer campaignId, int limit) {
|
||||
final String lockKey = idSeq.get();
|
||||
final Map<String, Object> update = new HashMap<>(8);
|
||||
update.put(CallingList.LOCK_KEY, lockKey);
|
||||
update.put(CallingList.LOCK_TIME, new Date());
|
||||
update.put(CallingList.STATUS, CallingList.Status.ACHIEVED);
|
||||
public void fetchRemote(final Campaign campaign) {
|
||||
log.info("campaign [{}] fetch calling list data.", campaign);
|
||||
|
||||
final int time = TimeUtils.secondOfDay(new Date());
|
||||
final Integer campaignId = campaign.getId();
|
||||
final String campaignKey = campaign.getCampaignKey();
|
||||
final RespCallingList callingList =
|
||||
callingListService.fetchCallingList(fetchSize,
|
||||
campaignKey,
|
||||
campaign.getName());
|
||||
final RespCallingList.CallingData[] data =
|
||||
callingList.getData();
|
||||
|
||||
mapper.update(update,
|
||||
new Search(CallingList.CAMPAIGN_ID, campaignId)
|
||||
.eq(CallingList.STATUS, CallingList.Status.READY)
|
||||
.isNull(CallingList.LOCK_KEY)
|
||||
.lt(CallingList.DAILY_FROM, time)
|
||||
.gt(CallingList.DAILY_TO, time)
|
||||
.limit(limit));
|
||||
if (data == null || data.length == 0) {
|
||||
log.error("Fetch calling list data error caused. code [{}], error [{}].",
|
||||
callingList.getCode(), callingList.getError());
|
||||
return;
|
||||
}
|
||||
|
||||
return mapper.list(new Search(CallingList.CAMPAIGN_ID, campaignId)
|
||||
.eq(CallingList.LOCK_KEY, lockKey).limit(limit));
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("CallingListData: [{}][{}][{}]",
|
||||
campaignId, campaignKey, StringUtils.join(data, "|"));
|
||||
}
|
||||
|
||||
mapper.insert(Stream.of(data).map(it -> {
|
||||
final CallingList cl = new CallingList();
|
||||
cl.setTenantId(campaign.getTenantId());
|
||||
cl.setTenantCode(campaign.getTenantCode());
|
||||
cl.setCampaignId(campaignId);
|
||||
cl.setCampaignKey(campaignKey);
|
||||
cl.setDailyFrom(campaign.getDailyFrom());
|
||||
cl.setDailyTo(campaign.getDailyTo());
|
||||
cl.setStatus(CallingList.Status.READY);
|
||||
cl.setCaseKey(it.getCaseKey());
|
||||
cl.setPhone(PhoneNumberUtils.cleanupMobile(it.getPhone()));
|
||||
cl.setLastConnected(false);
|
||||
final Date now = new Date();
|
||||
cl.setAddedTime(now);
|
||||
cl.setCalledTimes(0);
|
||||
cl.setCreatedTime(now);
|
||||
return cl;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void releaseCallingListLock(final CallingList callingList) {
|
||||
callingList.setLockKey(null);
|
||||
callingList.setLockTime(null);
|
||||
mapper.update(callingList);
|
||||
public List<CallingList> listReady(final Integer campaignId, final int limit) {
|
||||
final String lockKey = idSeq.get();
|
||||
final Map<String, Object> update = new HashMap<>(8);
|
||||
update.put(CallingList.LOCK_KEY, lockKey);
|
||||
update.put(CallingList.LOCK_TIME, new Date());
|
||||
update.put(CallingList.STATUS, CallingList.Status.ACHIEVED);
|
||||
|
||||
final int secondOfDay = TimeUtils.secondOfDay(new Date());
|
||||
|
||||
mapper.update(update,
|
||||
new Search(CallingList.CAMPAIGN_ID, campaignId)
|
||||
.eq(CallingList.STATUS, CallingList.Status.READY)
|
||||
.isNull(CallingList.LOCK_KEY)
|
||||
.lt(CallingList.DAILY_FROM, secondOfDay)
|
||||
.gt(CallingList.DAILY_TO, secondOfDay)
|
||||
.limit(limit));
|
||||
|
||||
return mapper.list(new Search(CallingList.CAMPAIGN_ID, campaignId)
|
||||
.eq(CallingList.LOCK_KEY, lockKey).limit(limit));
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +1,33 @@
|
||||
package com.pudonghot.yo.campaign.service.impl;
|
||||
|
||||
import lombok.val;
|
||||
import lombok.Setter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.pudonghot.yo.util.LogMDC;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.pudonghot.yo.util.ListUtils;
|
||||
import com.wacai.tigon.mybatis.Search;
|
||||
import com.pudonghot.yo.util.TimeUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.pudonghot.yo.mapper.CampaignMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.pudonghot.yo.model.domain.Campaign;
|
||||
import com.pudonghot.yo.mapper.AgentStatusMapper;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import com.pudonghot.yo.service.CommonCallDataService;
|
||||
import com.pudonghot.yo.fsagent.api.CampaignDialService;
|
||||
import com.pudonghot.yo.campaign.service.CampaignService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import com.pudonghot.yo.fsagent.api.request.ReqCampaignDial;
|
||||
import com.pudonghot.yo.campaign.service.CallingListService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import com.wacai.tigon.service.support.BaseQueryServiceSupport;
|
||||
import com.pudonghot.yo.campaign.feign.response.RespCallingList;
|
||||
import static com.pudonghot.yo.model.domain.Campaign.TargetType.QUEUE;
|
||||
import com.pudonghot.yo.campaign.feign.service.FeignCallingListService;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import com.pudonghot.yo.fsagent.api.request.ReqCampaignDial.CallingRecord;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
@ -48,8 +47,8 @@ public class CampaignServiceImpl
|
||||
private int dialBatchSleep;
|
||||
@Autowired
|
||||
private AgentStatusMapper agentStatusMapper;
|
||||
@Autowired
|
||||
private FeignCallingListService callingListService;
|
||||
@Setter(onMethod_ = {@Lazy, @Autowired})
|
||||
private CallingListService callingListService;
|
||||
@Autowired
|
||||
private CampaignDialService dialService;
|
||||
@Autowired
|
||||
@ -57,7 +56,7 @@ public class CampaignServiceImpl
|
||||
|
||||
@Scheduled(fixedRateString = "${yo.campaign.task-scheduler.fixed-rate:180000}", initialDelayString = "${yo.campaign.task-scheduler.init-delay:32000}")
|
||||
public void taskScheduler() {
|
||||
final int secondOfDay = TimeUtils.secondOfDay(new Date());
|
||||
val secondOfDay = TimeUtils.secondOfDay(new Date());
|
||||
scan(new Search(Campaign.ACTIVE, true)
|
||||
.eq(Campaign.STATUS, Campaign.Status.RUNNING)
|
||||
.lt(Campaign.DAILY_FROM, secondOfDay)
|
||||
@ -73,19 +72,23 @@ public class CampaignServiceImpl
|
||||
});
|
||||
}
|
||||
|
||||
void dial(final Campaign campaign) {
|
||||
final String campaignKey = campaign.getCampaignKey();
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void dial(final Campaign campaign) {
|
||||
val campaignKey = campaign.getCampaignKey();
|
||||
LogMDC.setTraceId(campaignKey);
|
||||
log.info("Campaign [{}] dial.", campaign);
|
||||
final Integer queueId = campaign.getTargetId();
|
||||
final int countOnlineAgentOfQueue =
|
||||
val queueId = campaign.getTargetId();
|
||||
val countOnlineAgentOfQueue =
|
||||
agentStatusMapper.countOnlineOfQueue(queueId);
|
||||
if (countOnlineAgentOfQueue == 0) {
|
||||
log.warn("Campaign has no online agent, ignore.");
|
||||
return;
|
||||
}
|
||||
|
||||
final int countIdleAgentOfQueue =
|
||||
val countIdleAgentOfQueue =
|
||||
agentStatusMapper.countIdleOfQueue(queueId);
|
||||
|
||||
if (countIdleAgentOfQueue == 0) {
|
||||
@ -93,9 +96,9 @@ public class CampaignServiceImpl
|
||||
return;
|
||||
}
|
||||
|
||||
final Integer campaignId = campaign.getId();
|
||||
final int maxChannels = campaign.getNumOfChannels();
|
||||
int campaignChannel =
|
||||
val campaignId = campaign.getId();
|
||||
val maxChannels = campaign.getNumOfChannels();
|
||||
val campaignChannel =
|
||||
commonCallDataService.getCampaignChannel(campaignId);
|
||||
|
||||
if (campaignChannel >= maxChannels) {
|
||||
@ -103,7 +106,7 @@ public class CampaignServiceImpl
|
||||
return;
|
||||
}
|
||||
|
||||
final int optimizationValue = campaign.getOptimizationValue();
|
||||
val optimizationValue = campaign.getOptimizationValue();
|
||||
int fetchCount = 0;
|
||||
if (countIdleAgentOfQueue > 4) {
|
||||
if (optimizationValue > 0) {
|
||||
@ -112,35 +115,24 @@ public class CampaignServiceImpl
|
||||
}
|
||||
}
|
||||
|
||||
final RespCallingList callingList =
|
||||
callingListService.fetchCallingList(
|
||||
fetchCount > 0 ? fetchCount : countIdleAgentOfQueue,
|
||||
campaignKey,
|
||||
campaign.getName());
|
||||
final RespCallingList.CallingData[] data =
|
||||
callingList.getData();
|
||||
val callingLists = callingListService.listReady(
|
||||
campaignId, fetchCount > 0 ? fetchCount : countIdleAgentOfQueue);
|
||||
|
||||
if (data == null || data.length == 0) {
|
||||
log.error("Fetch calling list data error caused. code [{}], message [{}].",
|
||||
callingList.getCode(), callingList.getError());
|
||||
if (callingLists.isEmpty()) {
|
||||
log.info("No ready calling list found, ignore.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("CallingListData: [{}][{}][{}]",
|
||||
campaignId, campaignKey, StringUtils.join(data, "|"));
|
||||
}
|
||||
|
||||
final ReqCampaignDial req= new ReqCampaignDial();
|
||||
val req = new ReqCampaignDial();
|
||||
req.setCampaignId(campaignId);
|
||||
final List<Pair<String, String>> dataList = Stream.of(data)
|
||||
.map(RespCallingList.CallingData::toPair)
|
||||
val dataList = callingLists.stream()
|
||||
.map(it -> new CallingRecord(it.getId(), it.getCaseKey(), it.getPhone()))
|
||||
.collect(Collectors.toList());
|
||||
eachBatch(dataList, dialBatchSize, cl -> {
|
||||
ListUtils.eachBatch(dataList, dialBatchSize, cl -> {
|
||||
req.setCallingList(cl);
|
||||
dialService.queueDial(req);
|
||||
try {
|
||||
log.debug("Sleep [{}] milliseconds.", dialBatchSize);
|
||||
log.debug("Sleep [{}] milliseconds.", dialBatchSleep);
|
||||
TimeUnit.MILLISECONDS.sleep(dialBatchSleep);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
@ -148,15 +140,4 @@ public class CampaignServiceImpl
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
<T> void eachBatch(
|
||||
final List<T> list,
|
||||
final int batch,
|
||||
final Consumer<List<T>> consumer) {
|
||||
|
||||
final int size = list.size();
|
||||
for (int i = 0; i < size; i += batch) {
|
||||
consumer.accept(list.subList(i, Math.min(size, i + batch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,6 @@ dubbo.registry.file=${user.home}/dubbo-cache/${spring.application.name}/dubbo.ca
|
||||
yo.fsagent.dubbo.service.version=1.0.0
|
||||
|
||||
# Calling List
|
||||
yo.campaign.feign.calling-list.base-url=http://localhost:1116
|
||||
yo.campaign.feign.calling-list.channel=campaign.json
|
||||
yo.campaign.feign.calling-list.base-url=http://localhost:8093/callinglist
|
||||
yo.campaign.feign.calling-list.channel=dx-hzqw
|
||||
|
||||
|
@ -23,8 +23,8 @@ public class FeignCallingListServiceTest {
|
||||
|
||||
@Test
|
||||
public void testFetchCallingList() {
|
||||
final val callingList =
|
||||
callingListService.fetchCallingList(1, "11223", "44556");
|
||||
val callingList =
|
||||
callingListService.fetchCallingList(1, "5694", "5694");
|
||||
log.info("Calling list [{}].", callingList);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.pudonghot.yo.campaign.service;
|
||||
|
||||
import lombok.val;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.wacai.tigon.mybatis.Search;
|
||||
import com.pudonghot.yo.campaign.YoCampaign;
|
||||
import com.pudonghot.yo.model.domain.Campaign;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Sep 13, 2020 22:58:41
|
||||
*/
|
||||
@Slf4j
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = YoCampaign.class)
|
||||
public class CallingListServiceTest {
|
||||
@Autowired
|
||||
private CampaignService campaignService;
|
||||
@Autowired
|
||||
private CallingListService callingListService;
|
||||
|
||||
@Test
|
||||
public void testFetchRemote() {
|
||||
val campaign = campaignService.find(
|
||||
new Search(Campaign.CAMPAIGN_KEY, "5694"));
|
||||
callingListService.fetchRemote(campaign);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testList() {
|
||||
val campaign = campaignService.find(
|
||||
new Search(Campaign.CAMPAIGN_KEY, "5694"));
|
||||
val callingLists = callingListService.listReady(campaign.getId(), 2);
|
||||
log.info("Calling list [{}]", callingLists);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.pudonghot.yo.campaign.service;
|
||||
|
||||
import lombok.val;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.wacai.tigon.mybatis.Search;
|
||||
import com.pudonghot.yo.campaign.YoCampaign;
|
||||
import com.pudonghot.yo.model.domain.Campaign;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Sep 13, 2020 23:48:58
|
||||
*/
|
||||
@Slf4j
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = YoCampaign.class)
|
||||
public class CampaignServiceTest {
|
||||
@Autowired
|
||||
private CampaignService campaignService;
|
||||
|
||||
@Test
|
||||
public void testDial() {
|
||||
val campaign = campaignService.find(
|
||||
new Search(Campaign.CAMPAIGN_KEY, "donghuang"));
|
||||
campaignService.dial(campaign);
|
||||
}
|
||||
}
|
17
fetch-event2.sh
Executable file
17
fetch-event2.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo 'Usage: ./fetch-event.sh guid'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
url="http://localhost:8093/openapi/resource/agentevent/donghuang?guid=$1"
|
||||
echo "Listen URL: $url"
|
||||
count=0
|
||||
|
||||
while : ; do
|
||||
((++count))
|
||||
curl $url
|
||||
echo
|
||||
echo "[$count] Event fetched."
|
||||
done
|
@ -41,14 +41,16 @@ public class DialController {
|
||||
public List<String> campaignDial(
|
||||
@RequestParam("campaignId")
|
||||
final Integer campaignId,
|
||||
@RequestParam("recId")
|
||||
final Integer recId,
|
||||
@RequestParam("caseKey")
|
||||
final String caseKey,
|
||||
@RequestParam("phone")
|
||||
final String calledNumber) {
|
||||
|
||||
final val req = new ReqCampaignDial();
|
||||
val req = new ReqCampaignDial();
|
||||
req.setCampaignId(campaignId);
|
||||
req.setCallingList(Arrays.asList(Pair.of(calledNumber, caseKey)));
|
||||
req.setCallingList(Arrays.asList(new ReqCampaignDial.CallingRecord(recId, caseKey, calledNumber)));
|
||||
return campaignDialService.queueDial(req);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
package com.pudonghot.yo.fsagent.listener;
|
||||
|
||||
import java.util.Date;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.pudonghot.yo.util.LogMDC;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.pudonghot.yo.mapper.CallingListMapper;
|
||||
import com.pudonghot.yo.model.domain.CallingList;
|
||||
import com.pudonghot.yo.fsagent.util.EslEventUtils;
|
||||
import com.pudonghot.yo.service.CommonCallDataService;
|
||||
import org.freeswitch.esl.client.transport.event.Event;
|
||||
@ -20,14 +24,15 @@ public class CampaignChannelCreate {
|
||||
|
||||
@Autowired
|
||||
private CommonCallDataService commonCallDataService;
|
||||
|
||||
@Autowired
|
||||
private CallingListMapper callingListMapper;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Async
|
||||
@EventListener(value = Event.class,
|
||||
condition = "#root.args[0].getName() == 'CHANNEL_DESTROY'" +
|
||||
condition = "#root.args[0].getName() == 'CHANNEL_CREATE'" +
|
||||
" and #root.args[0].getDialType() == 'CAMPAIGN'")
|
||||
public void onChannelCreate(final Event event) {
|
||||
final String callId = event.getCallId();
|
||||
@ -39,8 +44,38 @@ public class CampaignChannelCreate {
|
||||
if (campaignId != null) {
|
||||
log.info("Increase campaign [{}] dial number.", campaignId);
|
||||
commonCallDataService.incrCampaignChannel(campaignId);
|
||||
commonCallDataService.incrCampaignDailyDialed(campaignId);
|
||||
|
||||
final String strRecId = event.getRecId();
|
||||
if (StringUtils.isNotBlank(strRecId)) {
|
||||
final Integer recId = Integer.parseInt(strRecId);
|
||||
final String calledNumber = event.getCalledNumber();
|
||||
log.info("Channel created update case [{}:{}] calling list.", strRecId, calledNumber);
|
||||
final CallingList rec = callingListMapper.find(recId);
|
||||
|
||||
if (rec == null) {
|
||||
log.warn("No case [{}:{}] calling list found, ignore.", strRecId, calledNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
rec.setLastCallStartTime(getCallStartTime(event));
|
||||
rec.setCalledTimes(rec.getCalledTimes() + 1);
|
||||
rec.setStatus(CallingList.Status.DIALING);
|
||||
rec.setLockKey(null);
|
||||
rec.setLockTime(null);
|
||||
rec.setUpdatedTime(new Date());
|
||||
rec.setLastConnId(callId);
|
||||
|
||||
callingListMapper.update(rec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Date getCallStartTime(final Event event) {
|
||||
final String startEpoch = event.getHeader("variable_start_epoch");
|
||||
if (StringUtils.isNotBlank(startEpoch)) {
|
||||
return new Date(Long.parseLong(startEpoch) * 1000);
|
||||
}
|
||||
return new Date();
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.pudonghot.yo.fsagent.listener;
|
||||
import java.util.Date;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.pudonghot.yo.util.LogMDC;
|
||||
import com.wacai.tigon.mybatis.Search;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.pudonghot.yo.mapper.CallingListMapper;
|
||||
@ -49,43 +48,29 @@ public class CampaignChannelDestroy {
|
||||
|
||||
callDataService.decrCampaignChannel(campaignId);
|
||||
|
||||
final String caseKey = event.getHeader("variable_x_case_key");
|
||||
if (StringUtils.isNotBlank(caseKey)) {
|
||||
log.info("Update case [{}] calling list call result.", caseKey);
|
||||
|
||||
final CallingList rec = callingListMapper.find(
|
||||
new Search(CallingList.CASE_KEY, caseKey)
|
||||
.desc(CallingList.ID)
|
||||
.limit(1));
|
||||
final String strRecId = event.getRecId();
|
||||
if (StringUtils.isNotBlank(strRecId)) {
|
||||
final Integer recId = Integer.parseInt(strRecId);
|
||||
final String calledNumber = event.getCalledNumber();
|
||||
log.info("Channel destroy update case [{}:{}] calling list call result.",
|
||||
recId, calledNumber);
|
||||
final CallingList rec = callingListMapper.find(recId);
|
||||
|
||||
if (rec == null) {
|
||||
log.warn("No case [{}] calling list found, ignore.", caseKey);
|
||||
log.warn("No case [{}:{}] calling list found, ignore.", strRecId, calledNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
rec.setCalledTimes(rec.getCalledTimes() + 1);
|
||||
rec.setLastConnId(event.getConnId());
|
||||
rec.setLastCallStartTime(getCallStartTime(event));
|
||||
final String strBillSec = event.getHeader("variable_billsec");
|
||||
final Long billSec = StringUtils.isNotBlank(strBillSec) ?
|
||||
Long.parseLong(strBillSec) : 0;
|
||||
rec.setLastCallDuration(billSec);
|
||||
rec.setLastConnected(billSec > 0);
|
||||
rec.setLastHangupCause(event.getHangupCause());
|
||||
rec.setLockKey(null);
|
||||
rec.setLockTime(null);
|
||||
rec.setStatus(CallingList.Status.CALLED);
|
||||
rec.setUpdatedTime(new Date());
|
||||
callingListMapper.update(rec);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Date getCallStartTime(final Event event) {
|
||||
final String startEpoch = event.getHeader("variable_start_epoch");
|
||||
if (StringUtils.isNotBlank(startEpoch)) {
|
||||
return new Date(Long.parseLong(startEpoch) * 1000);
|
||||
}
|
||||
return new Date();
|
||||
}
|
||||
}
|
||||
|
@ -94,11 +94,6 @@ public class ChannelCreate {
|
||||
agent.getId(),
|
||||
agent.getAccount(), null));
|
||||
}
|
||||
|
||||
final Integer campaignId = event.getCampaignId();
|
||||
if (campaignId != null) {
|
||||
commonCallDataService.incrCampaignDailyEstablished(campaignId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
package com.pudonghot.yo.fsagent.service.dubbo.impl;
|
||||
|
||||
import lombok.val;
|
||||
import java.util.*;
|
||||
import com.pudonghot.yo.mapper.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.pudonghot.yo.util.LogMDC;
|
||||
import com.pudonghot.yo.model.domain.*;
|
||||
import org.springframework.util.Assert;
|
||||
import com.pudonghot.yo.model.domain.Queue;
|
||||
import com.wacai.tigon.sequence.IdSequence;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.pudonghot.yo.fsagent.api.request.*;
|
||||
import org.freeswitch.esl.client.inbound.Client;
|
||||
@ -49,8 +48,8 @@ public class CampaignDialServiceImpl implements CampaignDialService {
|
||||
*/
|
||||
@Override
|
||||
public List<String> queueDial(final ReqCampaignDial req) {
|
||||
final Integer campaignId = req.getCampaignId();
|
||||
final Campaign campaign = campaignMapper.find(campaignId);
|
||||
val campaignId = req.getCampaignId();
|
||||
val campaign = campaignMapper.find(campaignId);
|
||||
Assert.state(campaign != null,
|
||||
() -> "No campaign [" + campaignId + "] found");
|
||||
Assert.state(campaign.getActive(),
|
||||
@ -60,32 +59,33 @@ public class CampaignDialServiceImpl implements CampaignDialService {
|
||||
Assert.state(campaign.getTargetType() == Campaign.TargetType.QUEUE,
|
||||
() -> "Campaign [" + campaignId + "] target type is not QUEUE");
|
||||
|
||||
final Queue queue = queueMapper.find(campaign.getTargetId());
|
||||
val queue = queueMapper.find(campaign.getTargetId());
|
||||
Assert.state(queue != null,
|
||||
() -> "Campaign [" + campaignId + "] queue not found");
|
||||
Assert.state(queue.getActive(),
|
||||
() -> "Campaign [" + campaignId + "] queue is not active");
|
||||
|
||||
final Tenant tenant = tenantMapper.find(campaign.getTenantId());
|
||||
val tenant = tenantMapper.find(campaign.getTenantId());
|
||||
Assert.state(tenant != null,
|
||||
() -> "Campaign [" + campaignId + "] tenant not found");
|
||||
Assert.state(tenant.getActive(),
|
||||
() -> "Campaign [" + campaignId + "] tenant is not active");
|
||||
|
||||
final List<Pair<String, String>> callingList = req.getCallingList();
|
||||
final List<String> callUuidList = new ArrayList<>(callingList.size());
|
||||
val callingList = req.getCallingList();
|
||||
val callUuidList = new ArrayList<String>(callingList.size());
|
||||
|
||||
for (final Pair<String, String> callingRec : callingList) {
|
||||
final String calledNumber = callingRec.getLeft();
|
||||
final String caseKey = callingRec.getRight();
|
||||
for (val callingRec : callingList) {
|
||||
val recId = callingRec.getId();
|
||||
val calledNumber = callingRec.getPhone();
|
||||
val caseKey = callingRec.getCaseKey();
|
||||
|
||||
final Trunk trunk = trunkMapper.findOfCampaign(campaignId);
|
||||
val trunk = trunkMapper.findOfCampaign(campaignId);
|
||||
Assert.state(trunk != null,
|
||||
() -> "No trunk of campaign [" + campaignId + "] found");
|
||||
|
||||
final String uuid = idSeq.get();
|
||||
val uuid = idSeq.get();
|
||||
|
||||
final List<String> globalVars = Arrays.asList(
|
||||
val globalVars = Arrays.<String>asList(
|
||||
"x_conn_id=" + uuid,
|
||||
"ignore_early_media=true",
|
||||
"x_dial_type=CAMPAIGN",
|
||||
@ -93,6 +93,7 @@ public class CampaignDialServiceImpl implements CampaignDialService {
|
||||
"x_tenant_id=" + tenant.getId(),
|
||||
"x_tenant_code=" + tenant.getCode(),
|
||||
"x_campaign_id=" + campaignId,
|
||||
"x_rec_id=" + recId,
|
||||
"x_case_key=" + caseKey,
|
||||
"x_called_number=" + calledNumber,
|
||||
"x_trunk_id=" + trunk.getId(),
|
||||
@ -111,7 +112,6 @@ public class CampaignDialServiceImpl implements CampaignDialService {
|
||||
"origination_caller_id_number=" + trunk.getCpn()
|
||||
);
|
||||
|
||||
// originate {x_dial_type=CAMPAIGN,x_tenant_id=13,x_tenant_code=GOBLIN,x_account=SYSTEM,x_called_number=13764268709,x_trunk_id=12,x_cpn=28165766}[originate_timeout=30,x_logic_role=CALLED,origination_caller_id_number=28165766]sofia/gateway/GW000001/013764268709 4.Q XML d1.wacai.info
|
||||
fsClient.bgApi(format("originate {{}}[{}]{} {}.Q XML {}",
|
||||
StringUtils.join(globalVars, ","),
|
||||
StringUtils.join(channelVars, ","),
|
||||
@ -119,9 +119,9 @@ public class CampaignDialServiceImpl implements CampaignDialService {
|
||||
queue.getId(),
|
||||
tenant.getRealm()));
|
||||
|
||||
log.info("CampaignCall [{}:{}].", caseKey, calledNumber);
|
||||
log.info("CampaignCall [{}:{}:{}].", recId, caseKey, calledNumber);
|
||||
|
||||
final Map<String, Object> callData = new HashMap<>(4);
|
||||
val callData = new HashMap<String, Object>(4);
|
||||
callData.put("outid", caseKey);
|
||||
callData.put("phone", calledNumber);
|
||||
callData.put("taskid", campaign.getCampaignKey());
|
||||
|
@ -33,7 +33,7 @@ public class DialServiceTest {
|
||||
|
||||
@Test
|
||||
public void testDial() {
|
||||
final val req = new ReqAgentDial();
|
||||
val req = new ReqAgentDial();
|
||||
req.setTenantId(1);
|
||||
req.setAccount("donghuang");
|
||||
req.setCalledNumber("13764268709");
|
||||
@ -43,7 +43,7 @@ public class DialServiceTest {
|
||||
|
||||
@Test
|
||||
public void testDial2() {
|
||||
final ReqDial req = new ReqDial();
|
||||
val req = new ReqDial();
|
||||
req.setTenantId(13);
|
||||
req.setCallerLeg(CallLeg.queue("queue1"));
|
||||
req.setCalledLeg(CallLeg.outside(3, "13764268709"));
|
||||
@ -55,10 +55,12 @@ public class DialServiceTest {
|
||||
|
||||
@Test
|
||||
public void testCampaignDial() {
|
||||
final val req = new ReqCampaignDial();
|
||||
val req = new ReqCampaignDial();
|
||||
req.setCampaignId(4);
|
||||
final String calledNumber = "13764268709";
|
||||
req.setCallingList(Arrays.asList(Pair.of(calledNumber, calledNumber)));
|
||||
req.setCallingList(
|
||||
Arrays.asList(new ReqCampaignDial.CallingRecord(
|
||||
1, calledNumber, calledNumber)));
|
||||
campaignDialService.queueDial(req);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
package com.pudonghot.yo.fsagent.api.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.*;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
@ -18,5 +15,18 @@ public class ReqCampaignDial implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer campaignId;
|
||||
private List<Pair<String, String>> callingList;
|
||||
private List<CallingRecord> callingList;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class CallingRecord implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer id;
|
||||
private String caseKey;
|
||||
private String phone;
|
||||
}
|
||||
}
|
||||
|
@ -119,8 +119,6 @@ public class DataWrapper implements Serializable {
|
||||
return getVal("variable_x_called_number");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method.
|
||||
* get dial type
|
||||
@ -145,6 +143,26 @@ public class DataWrapper implements Serializable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method.
|
||||
* get calling list record id
|
||||
*
|
||||
* @return calling list record id
|
||||
*/
|
||||
public String getRecId() {
|
||||
return getVal("variable_x_rec_id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method.
|
||||
* get case key
|
||||
*
|
||||
* @return case key
|
||||
*/
|
||||
public String getCaseKey() {
|
||||
return getVal("variable_x_case_key");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method.
|
||||
* get other number
|
||||
|
@ -33,25 +33,25 @@ public class TrunkMapperTest {
|
||||
|
||||
@Test
|
||||
public void testListOfStrategy() {
|
||||
final val trunk = mapper.listOfStrategy(Arrays.asList(1, 2, 3));
|
||||
val trunk = mapper.listOfStrategy(Arrays.asList(1, 2, 3));
|
||||
log.info("Trunk [{}].", trunk);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOfStrategy() {
|
||||
final val trunk = mapper.findOfStrategy(Arrays.asList(1, 2, 3));
|
||||
val trunk = mapper.findOfStrategy(Arrays.asList(1, 2, 3));
|
||||
log.info("Trunk [{}].", trunk);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOfAgentGroup() {
|
||||
final val trunk = mapper.findOfAgentGroup(5);
|
||||
val trunk = mapper.findOfAgentGroup(5);
|
||||
log.info("Trunk [{}].", trunk);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOfCampaign() {
|
||||
final val trunk = mapper.findOfCampaign(3);
|
||||
val trunk = mapper.findOfCampaign(3);
|
||||
log.info("Trunk [{}].", trunk);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import java.util.Date;
|
||||
import com.wacai.tigon.mybatis.Table;
|
||||
import com.pudonghot.yo.model.DailyTime;
|
||||
import com.wacai.tigon.mybatis.NotUpdate;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import com.wacai.tigon.mybatis.UseGeneratedKeys;
|
||||
|
||||
/**
|
||||
* @author Donghuang <br>
|
||||
@ -14,7 +15,6 @@ import com.wacai.tigon.mybatis.UseGeneratedKeys;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@UseGeneratedKeys
|
||||
@Table("br_calling_list")
|
||||
@FieldNameConstants(prefix = "")
|
||||
public class CallingList extends BaseDomain {
|
||||
@ -28,11 +28,11 @@ public class CallingList extends BaseDomain {
|
||||
private String campaignKey;
|
||||
@NotUpdate
|
||||
private Date addedTime;
|
||||
private DailyTime dailyFrom;
|
||||
private DailyTime dailyTo;
|
||||
@NotUpdate
|
||||
private String phone;
|
||||
private Status status;
|
||||
private Integer dailyFrom;
|
||||
private Integer dailyTo;
|
||||
private Integer calledTimes;
|
||||
private String lastConnId;
|
||||
private Date lastCallStartTime;
|
||||
@ -51,6 +51,6 @@ public class CallingList extends BaseDomain {
|
||||
private Date lockTime;
|
||||
|
||||
public enum Status {
|
||||
READY, ACHIEVED, CALLED, CANCELED
|
||||
READY, ACHIEVED, DIALING, CALLED, CANCELED
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ public interface CommonCallDataService {
|
||||
*/
|
||||
String getIvrCallData(String agentId);
|
||||
|
||||
|
||||
/**
|
||||
* save call data
|
||||
*
|
||||
@ -47,7 +46,7 @@ public interface CommonCallDataService {
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign channel
|
||||
*/
|
||||
int getCampaignChannel(Integer campaignId);
|
||||
Integer getCampaignChannel(Integer campaignId);
|
||||
|
||||
/**
|
||||
* increase campaign channel
|
||||
@ -55,7 +54,7 @@ public interface CommonCallDataService {
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign channel
|
||||
*/
|
||||
int incrCampaignChannel(Integer campaignId);
|
||||
Integer incrCampaignChannel(Integer campaignId);
|
||||
|
||||
/**
|
||||
* decrease campaign channel
|
||||
@ -63,51 +62,12 @@ public interface CommonCallDataService {
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign channel
|
||||
*/
|
||||
int decrCampaignChannel(Integer campaignId);
|
||||
Integer decrCampaignChannel(Integer campaignId);
|
||||
|
||||
/**
|
||||
* get campaign daily dialed
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign daily dialed
|
||||
*/
|
||||
int getCampaignDailyDialed(Integer campaignId);
|
||||
|
||||
/**
|
||||
* increase campaign daily dialed
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign daily dialed
|
||||
*/
|
||||
int incrCampaignDailyDialed(Integer campaignId);
|
||||
|
||||
/**
|
||||
* reset campaign daily dialed
|
||||
* reset campaign channel
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
*/
|
||||
void resetCampaignDailyDialed(Integer campaignId);
|
||||
|
||||
/**
|
||||
* get campaign daily established
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign daily established
|
||||
*/
|
||||
int getCampaignDailyEstablished(Integer campaignId);
|
||||
|
||||
/**
|
||||
* increase campaign daily established
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
* @return count of campaign daily established
|
||||
*/
|
||||
int incrCampaignDailyEstablished(Integer campaignId);
|
||||
|
||||
/**
|
||||
* reset campaign daily established
|
||||
*
|
||||
* @param campaignId campaign id
|
||||
*/
|
||||
void resetCampaignDailyEstablished(Integer campaignId);
|
||||
Integer resetCampaignChannel(Integer campaignId);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class CommonAgentEventQueueServiceImpl implements CommonAgentEventQueueSe
|
||||
*/
|
||||
@Override
|
||||
public void publish(final AgentEvent event) {
|
||||
log.debug("Publish agent event [{}].", event);
|
||||
log.info("Publish agent event [{}].", event);
|
||||
AGENT_EVENT_QUEUE.offer(event);
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,8 @@ public class CommonCallDataServiceImpl implements CommonCallDataService {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getCampaignChannel(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.getOrDefault(channelKey(campaignId), 0);
|
||||
public Integer getCampaignChannel(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.getOrDefault(channelKey(campaignId), 0);
|
||||
log.debug("Get campaign [{}] channel [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
@ -82,8 +82,8 @@ public class CommonCallDataServiceImpl implements CommonCallDataService {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int incrCampaignChannel(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.addAndGet(channelKey(campaignId), 1);
|
||||
public Integer incrCampaignChannel(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.addAndGet(channelKey(campaignId), 1);
|
||||
log.info("Increase campaign [{}] channel [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
@ -92,8 +92,8 @@ public class CommonCallDataServiceImpl implements CommonCallDataService {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int decrCampaignChannel(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.addAndGet(channelKey(campaignId), -1);
|
||||
public Integer decrCampaignChannel(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.addAndGet(channelKey(campaignId), -1);
|
||||
log.info("Decrease campaign [{}] channel [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
@ -102,60 +102,12 @@ public class CommonCallDataServiceImpl implements CommonCallDataService {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getCampaignDailyDialed(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.getOrDefault(dialKey(campaignId), 0);
|
||||
log.debug("Get campaign [{}] daily dialed [{}].", campaignId, val);
|
||||
public Integer resetCampaignChannel(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.remove(channelKey(campaignId));
|
||||
log.info("Reset campaign [{}] channel [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int incrCampaignDailyDialed(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.addAndGet(dialKey(campaignId), 1);
|
||||
log.debug("Increase campaign [{}] daily dialed [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void resetCampaignDailyDialed(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.remove(dialKey(campaignId));
|
||||
log.debug("Reset campaign [{}] daily dialed [{}].", campaignId, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int getCampaignDailyEstablished(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.getOrDefault(establishedKey(campaignId), 0);
|
||||
log.debug("Get campaign [{}] daily established [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int incrCampaignDailyEstablished(final Integer campaignId) {
|
||||
final int val = CAMPAIGN_DATA.addAndGet(establishedKey(campaignId), 1);
|
||||
log.debug("Increase campaign [{}] daily established [{}].", campaignId, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void resetCampaignDailyEstablished(final Integer campaignId) {
|
||||
final Integer val = CAMPAIGN_DATA.remove(establishedKey(campaignId));
|
||||
log.debug("Reset campaign [{}] daily established [{}].", campaignId, val);
|
||||
}
|
||||
|
||||
private void put(final String key, final String value) {
|
||||
log.debug("Call data cache [{}] -> [{}].", key, value);
|
||||
CACHE.put(key, value, callDataTimeoutSeconds, TimeUnit.SECONDS);
|
||||
@ -168,12 +120,4 @@ public class CommonCallDataServiceImpl implements CommonCallDataService {
|
||||
private String channelKey(final Integer campaignId) {
|
||||
return "CC:" + campaignId;
|
||||
}
|
||||
|
||||
private String dialKey(final Integer campaignId) {
|
||||
return "CD:" + campaignId;
|
||||
}
|
||||
|
||||
private String establishedKey(final Integer campaignId) {
|
||||
return "CE:" + campaignId;
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public class CommonCampaignServiceImpl
|
||||
log.info("Update campaign [{}] status [{}].", campaign, status);
|
||||
campaign.setStatus(status);
|
||||
mapper.update(campaign);
|
||||
resetData(campaign);
|
||||
commonCallDataService.resetCampaignChannel(campaign.getId());
|
||||
}
|
||||
|
||||
private Campaign findValid(final String campaignKey) {
|
||||
@ -112,10 +112,4 @@ public class CommonCampaignServiceImpl
|
||||
() -> "Campaign [" + campaignKey + "] is not active");
|
||||
return campaign;
|
||||
}
|
||||
|
||||
private void resetData(final Campaign campaign) {
|
||||
final Integer campaignId = campaign.getId();
|
||||
commonCallDataService.resetCampaignDailyDialed(campaignId);
|
||||
commonCallDataService.resetCampaignDailyEstablished(campaignId);
|
||||
}
|
||||
}
|
||||
|
30
lib/util/src/main/java/com/pudonghot/yo/util/ListUtils.java
Normal file
30
lib/util/src/main/java/com/pudonghot/yo/util/ListUtils.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.pudonghot.yo.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Sep 13, 2020 14:11:09
|
||||
*/
|
||||
public class ListUtils {
|
||||
|
||||
/**
|
||||
* list each batch
|
||||
*
|
||||
* @param list list
|
||||
* @param batch batch size
|
||||
* @param consumer consumer
|
||||
* @param <T> element type
|
||||
*/
|
||||
public static <T> void eachBatch(
|
||||
final List<T> list,
|
||||
final int batch,
|
||||
final Consumer<List<T>> consumer) {
|
||||
|
||||
final int size = list.size();
|
||||
for (int i = 0; i < size; i += batch) {
|
||||
consumer.accept(list.subList(i, Math.min(size, i + batch)));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,16 @@
|
||||
package com.pudonghot.yo.campaign.service.impl;
|
||||
package com.pudonghot.yo.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Sep 13, 2020 10:25:44
|
||||
*/
|
||||
@Slf4j
|
||||
public class CampaignServiceImplTest {
|
||||
public class ListUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testEachBatch() {
|
||||
@ -19,6 +18,6 @@ public class CampaignServiceImplTest {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
list.add(i);
|
||||
}
|
||||
new CampaignServiceImpl(null).eachBatch(list, 8, sub -> log.info("{}", sub));
|
||||
ListUtils.eachBatch(list, 8, sub -> log.info("{}", sub));
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.pudonghot.yo.util;
|
||||
|
||||
import org.junit.Test;
|
||||
import java.util.Date;
|
||||
import java.util.Calendar;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
/**
|
||||
* @author Donghuang
|
||||
* @date Sep 13, 2020 23:12:06
|
||||
*/
|
||||
@Slf4j
|
||||
public class TimeUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testEachBatch() {
|
||||
log.info("val: {}", TimeUtils.secondOfDay(
|
||||
DateUtils.addSeconds(DateUtils.truncate(DateUtils.addDays(new Date(), 1), Calendar.DATE), -1)));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user