Authored by ping

增加自动添加马甲定时器

/**
*
*/
package com.yoho.activity.common.enums;
/**
* 描述:
*
* @author ping.huang
* 2016年3月7日
*/
public enum UserTypeEnum {
REAL_USER(1, "真实用户"),
VIRTUAL_USER(2, "马甲用户");
private int value;
private String name;
public String getName() {
return name;
}
private UserTypeEnum(int value, String name){
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
}
... ...
... ... @@ -19,4 +19,6 @@ public interface IDrawlineActivityDAO {
int updateByPrimaryKey(DrawlineActivity record);
List<DrawlineActivity> selectByNotLuckydraw();
List<DrawlineActivity> selectAllActivity();
}
\ No newline at end of file
... ...
package com.yoho.queue.dal;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
... ... @@ -34,4 +35,8 @@ public interface IDrawlineUserQueueDAO {
List<DrawlineUserQueue> selectRealUserQueueByRand(@Param("activityId") int activityId, @Param("uids") String uids, @Param("limit") int limit);
List<DrawlineUserQueue> selectByRand(@Param("activityId") int activityId, @Param("userType") byte userType, @Param("limit") int limit);
List<DrawlineUserQueue> selectByTypeAndActivityIds(@Param("activityIds") String activityIds);
List<Map<String, Object>> selectRealUserCountByActivityIds(@Param("activityIds") String activityIds);
}
\ No newline at end of file
... ...
... ... @@ -18,4 +18,6 @@ public interface IDrawlineVirtualUserDAO {
int updateByPrimaryKey(DrawlineVirtualUser record);
List<DrawlineVirtualUser> selectByUids(List<Integer> uids);
List<DrawlineVirtualUser> selectWaitQueueVirtualUser();
}
\ No newline at end of file
... ...
package com.yoho.queue.dal.model;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import java.io.Serializable;
public class BaseModel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3879004768382010547L;
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
... ...
package com.yoho.queue.dal.model;
public class DrawlineActivity {
public class DrawlineActivity extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 5757130646789565100L;
private Integer id;
private String activityName;
... ...
package com.yoho.queue.dal.model;
public class DrawlineActivityLuckydraw {
public class DrawlineActivityLuckydraw extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 7094960597305219529L;
private Integer id;
private Integer endTime;
... ...
package com.yoho.queue.dal.model;
public class DrawlineLuckyUser {
public class DrawlineLuckyUser extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 8689663500649441830L;
private Integer id;
private String sid;
... ...
package com.yoho.queue.dal.model;
public class DrawlinePrizeSetting {
public class DrawlinePrizeSetting extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 1815363771431579455L;
private Integer id;
private Integer activityId;
... ...
package com.yoho.queue.dal.model;
public class DrawlineUserQueue {
public class DrawlineUserQueue extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 1927983911216419613L;
private Integer id;
private Integer uid;
... ...
package com.yoho.queue.dal.model;
public class DrawlineVirtualUser {
public class DrawlineVirtualUser extends BaseModel {
/**
*
*/
private static final long serialVersionUID = 3196096392951381646L;
private Integer uid;
private String nickname;
... ...
... ... @@ -170,4 +170,7 @@
from drawline_activity
where status = 1 and id not in (select id from drawline_activity_luckydraw where draw_status = 1 and status = 1)
</select>
<select id="selectAllActivity" resultMap="BaseResultMap">
select * from drawline_activity where status=1
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -81,96 +81,17 @@
where activity_id = #{activityId,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.yoho.queue.dal.model.DrawlineLuckyUser">
insert into drawline_lucky_user (id, sid, activity_id,
vip_level, queue_time, status,
insert into drawline_lucky_user (sid, activity_id,
vip_level, queue_time,
create_time, update_time, is_send_inbox,
is_send_prize, uid, user_type
)
values (#{id,jdbcType=INTEGER}, #{sid,jdbcType=VARCHAR}, #{activityId,jdbcType=INTEGER},
#{vipLevel,jdbcType=TINYINT}, #{queueTime,jdbcType=INTEGER}, #{status,jdbcType=TINYINT},
#{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER}, #{isSendInbox,jdbcType=TINYINT},
#{isSendPrize,jdbcType=TINYINT}, #{uid,jdbcType=INTEGER}, #{userType,jdbcType=TINYINT}
values (#{sid,jdbcType=VARCHAR}, #{activityId,jdbcType=INTEGER},
#{vipLevel,jdbcType=TINYINT}, UNIX_TIMESTAMP(),
UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0,
0, #{uid,jdbcType=INTEGER}, #{userType,jdbcType=TINYINT}
)
</insert>
<insert id="insertSelective" parameterType="com.yoho.queue.dal.model.DrawlineLuckyUser">
insert into drawline_lucky_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="sid != null">
sid,
</if>
<if test="activityId != null">
activity_id,
</if>
<if test="vipLevel != null">
vip_level,
</if>
<if test="queueTime != null">
queue_time,
</if>
<if test="status != null">
status,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="isSendInbox != null">
is_send_inbox,
</if>
<if test="isSendPrize != null">
is_send_prize,
</if>
<if test="uid != null">
uid,
</if>
<if test="userType != null">
user_type,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="sid != null">
#{sid,jdbcType=VARCHAR},
</if>
<if test="activityId != null">
#{activityId,jdbcType=INTEGER},
</if>
<if test="vipLevel != null">
#{vipLevel,jdbcType=TINYINT},
</if>
<if test="queueTime != null">
#{queueTime,jdbcType=INTEGER},
</if>
<if test="status != null">
#{status,jdbcType=TINYINT},
</if>
<if test="createTime != null">
#{createTime,jdbcType=INTEGER},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=INTEGER},
</if>
<if test="isSendInbox != null">
#{isSendInbox,jdbcType=TINYINT},
</if>
<if test="isSendPrize != null">
#{isSendPrize,jdbcType=TINYINT},
</if>
<if test="uid != null">
#{uid,jdbcType=INTEGER},
</if>
<if test="userType != null">
#{userType,jdbcType=TINYINT},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.yoho.queue.dal.model.DrawlineLuckyUser">
update drawline_lucky_user
<set>
... ... @@ -243,7 +164,7 @@
#{item.userType})
</foreach>
</insert>
<select id="selectLuckyUserCount" resultType="java.lang.Integer">
select
count(id)
... ...
... ... @@ -151,7 +151,7 @@
activity_id, sort, status,
create_time, update_time)
select #{uid,jdbcType=INTEGER},
#{userType,jdbcType=TINYINT}, #{activityId,jdbcType=INTEGER}, ifnull(max(sort), 0) + 1, #{status,jdbcType=TINYINT}, #{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER} from
#{userType,jdbcType=TINYINT}, #{activityId,jdbcType=INTEGER}, ifnull(max(sort), 0) + 1, #{status,jdbcType=TINYINT}, UNIX_TIMESTAMP(), UNIX_TIMESTAMP() from
drawline_user_queue where activity_id = #{activityId,jdbcType=INTEGER}
</insert>
<select id="selectCountBy" resultType="java.lang.Integer">
... ... @@ -195,4 +195,13 @@
where activity_id = #{activityId,jdbcType=INTEGER} and user_type = #{userType,jdbcType=TINYINT} and status = 1
ORDER BY RAND() LIMIT #{limit,jdbcType=INTEGER}
</select>
<select id="selectByTypeAndActivityIds" resultMap="BaseResultMap">
select * from drawline_user_queue where status=1 and user_type=2 and activity_id in (${activityIds})
</select>
<select id="selectRealUserCountByActivityIds" resultType="java.util.Map">
select activity_id, count(activity_id) nums from drawline_user_queue where status=1 and user_type=1
and create_time between UNIX_TIMESTAMP()-60 and UNIX_TIMESTAMP()
and activity_id in (${activityIds}) group by activity_id
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -128,4 +128,8 @@
</foreach>
</if>
</select>
<select id="selectWaitQueueVirtualUser" resultMap="BaseResultMap">
select * from drawline_virtual_user t1 where t1.status = 1
order by t1.uid
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -3,13 +3,37 @@
*/
package com.yoho.activity.other.timer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.yoho.activity.common.enums.UserTypeEnum;
import com.yoho.activity.common.utils.MapUtil;
import com.yoho.activity.common.utils.MapUtil.FunctionExPlus;
import com.yoho.queue.dal.IDrawlineActivityDAO;
import com.yoho.queue.dal.IDrawlineUserQueueDAO;
import com.yoho.queue.dal.IDrawlineVirtualUserDAO;
import com.yoho.queue.dal.model.DrawlineActivity;
import com.yoho.queue.dal.model.DrawlineUserQueue;
import com.yoho.queue.dal.model.DrawlineVirtualUser;
/**
* 描述:
* 描述:自动插入马甲
* 一分钟执行一次
* 规则
* 第一次判断,该活动只要有一个真实用户参加,就直接插入100个马甲;如果该活动还没有任何用户参加,则不增加马甲
* 从第二分钟开始,每次插入的马甲数,是前一分钟内,新增的真实用户数的5倍
*
* @author ping.huang 2016年3月5日
*/
... ... @@ -17,9 +41,163 @@ import org.springframework.stereotype.Component;
public class AddVirtualUserTimer {
static Logger log = LoggerFactory.getLogger(AddVirtualUserTimer.class);
@Resource
IDrawlineVirtualUserDAO drawlineVirtualUserDAO;
@Resource
IDrawlineActivityDAO drawlineActivityDAO;
@Resource
IDrawlineUserQueueDAO drawlineUserQueueDAO;
//各个活动下,待进入排队的马甲
Map<Integer, List<DrawlineVirtualUser>> waitAddUserMap = new HashMap<Integer, List<DrawlineVirtualUser>>();
//各个活动下,已经进入排队的马甲(该变量可以去掉了)
// Map<Integer, DrawlineVirtualUser> alreadyAddUserMap = null;
//所有的活动
List<DrawlineActivity> activityList = null;
//所有的活动ID
List<Integer> activityIdList = new ArrayList<Integer>();
//是否第一次
Map<Integer, Boolean> first = new HashMap<Integer, Boolean>();
/**
* 初始化一些参数
*/
@PostConstruct
public void init() {
//初始化所有活动
activityList = drawlineActivityDAO.selectAllActivity();
if (activityList == null || activityList.size() == 0) {
return;
}
for (DrawlineActivity activity : activityList) {
activityIdList.add(activity.getId());
}
//查询这些活动下,已经进入排队的马甲
List<DrawlineUserQueue> queueList = drawlineUserQueueDAO.selectByTypeAndActivityIds(StringUtils.join(activityIdList, ","));
//初始化所有的马甲用户
List<DrawlineVirtualUser> userList = drawlineVirtualUserDAO.selectWaitQueueVirtualUser();
List<DrawlineVirtualUser> waitList = null;
for (DrawlineActivity activity : activityList) {
for (DrawlineVirtualUser user : userList) {
//如果该马甲已经在该活动下排队过,则排除
if (userIsExists(activity.getId().intValue(), user.getUid().intValue(), queueList)) {
continue;
}
//没有排队过,则进入等待排队的队列
waitList = waitAddUserMap.get(activity.getId());
if (waitList == null) {
waitList = new ArrayList<DrawlineVirtualUser>();
}
waitList.add(user);
waitAddUserMap.put(activity.getId(), waitList);
}
}
System.out.println("result= " + JSON.toJSONString(waitAddUserMap));
}
@Scheduled(fixedDelay = 60 * 1000)
public void test() {
log.info("------------");
public void run() {
log.info("start add virtuals");
//没有活动,直接退出
if (activityList == null || activityList.size() == 0) {
log.info("activityList is empty over");
return;
}
//查询所有的活动,前一分钟内实际增加的真实用户数
List<Map<String, Object>> realUserCountList = drawlineUserQueueDAO.selectRealUserCountByActivityIds(StringUtils.join(activityIdList, ","));
//前一分钟没有真实用户参加
if (realUserCountList == null || realUserCountList.size() == 0) {
log.info("realUser add is empty");
return;
}
//list转map
Map<Integer, Integer> realUserCountMap = null;
if (realUserCountList != null) {
realUserCountMap = MapUtil.transformListMap(realUserCountList, new FunctionExPlus<Map<String, Object>, Integer, Integer>() {
@Override
public Integer applyKey(Map<String, Object> input) {
return Integer.parseInt(input.get("activity_id").toString());
}
@Override
public Integer applyValue(Map<String, Object> input) {
return Integer.parseInt(input.get("nums").toString());
}
});
}
//活动下,等待排队的马甲
List<DrawlineVirtualUser> waitList = null;
//需要加入的马甲数量
int num = 0, n = 0;
DrawlineUserQueue queueUser = null;
for (DrawlineActivity activity : activityList) {
n = 0;
if (realUserCountMap.get(activity.getId()) == null || realUserCountMap.get(activity.getId()) == 0) {
//该活动还没有一个用户参加,则不增加马甲
continue;
}
waitList = waitAddUserMap.get(activity.getId());
if (waitList == null || waitList.size() == 0) {
log.info("wait queue user is empty");
continue;
}
if (first.get(activity.getId()) == null) {
num = 100;
first.put(activity.getId(), true);
} else {
num = 5 * (realUserCountMap.get(activity.getId()) == null ? 0 : realUserCountMap.get(activity.getId()).intValue());
}
//进入排队
for (int i = 0; i < waitList.size(); i++) {
n++;
if (n > num) {
break;
}
queueUser = new DrawlineUserQueue();
queueUser.setActivityId(activity.getId());
queueUser.setUid(waitList.get(i).getUid());
queueUser.setUserType((byte) UserTypeEnum.VIRTUAL_USER.getValue());
queueUser.setStatus((byte) 1);
//插入排队表,因为排队字段sort必须要连续,为了避免锁表到导致真实用户插入问题,这里需要在循环里面插入数据库
drawlineUserQueueDAO.insertAutoSort(queueUser);
//插入成功后,需要从等待排队的马甲中删除
waitList.remove(waitList.get(i));
i--;
}
}
log.info("end add virtuals");
}
/**
* 查询该活动下,这个马甲有没有排队过
* @param activityId
* @param uid
* @param queueList
* @return
*/
private boolean userIsExists(int activityId, int uid, List<DrawlineUserQueue> queueList) {
if (queueList == null || queueList.size() == 0) {
return false;
}
for (DrawlineUserQueue user : queueList) {
if (user.getActivityId() != null && user.getActivityId().intValue() == activityId && user.getUid() != null && user.getUid().intValue() == uid) {
return true;
}
}
return false;
}
}
... ...
... ... @@ -116,6 +116,7 @@
<logger name="com.yoho.core.rest.client.finder.zookeeper.CuratorXDiscoveryClientWrapper" level="INFO"/>
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
<logger name="org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor" level="INFO"/>
<!-- zk日志 -->
<logger name="org.apache.zookeeper.ClientCnxn" level="INFO" additivity="false">
... ...
... ... @@ -132,6 +132,7 @@
<logger name="org.apache.zookeeper.ClientCnxn" level="WARN"/>
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
<logger name="org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor" level="INFO"/>
<!-- root级别 DEBUG -->
<root level="${yoho.logs.level}">
... ...