新增用户每日活跃记录功能
This commit is contained in:
parent
923c03c155
commit
b84935509d
@ -17,6 +17,7 @@ import com.red.circle.other.infra.database.cache.service.user.CountUserActiveInd
|
|||||||
import com.red.circle.other.infra.database.mongo.entity.user.status.OnlineUser;
|
import com.red.circle.other.infra.database.mongo.entity.user.status.OnlineUser;
|
||||||
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
|
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
|
||||||
import com.red.circle.other.infra.database.mongo.service.user.status.OnlineUserService;
|
import com.red.circle.other.infra.database.mongo.service.user.status.OnlineUserService;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.user.active.UserDailyActiveService;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.ExpandService;
|
import com.red.circle.other.infra.database.rds.service.user.user.ExpandService;
|
||||||
import com.red.circle.other.infra.database.rds.service.user.user.OnlineTimeService;
|
import com.red.circle.other.infra.database.rds.service.user.user.OnlineTimeService;
|
||||||
import com.red.circle.other.inner.enums.user.UserOnlineStatusEnum;
|
import com.red.circle.other.inner.enums.user.UserOnlineStatusEnum;
|
||||||
@ -50,6 +51,7 @@ public class OnlineStatusUploadListener implements MessageListener {
|
|||||||
private final OnlineTimeService onlineTimeService;
|
private final OnlineTimeService onlineTimeService;
|
||||||
private final UserProfileGateway userProfileGateway;
|
private final UserProfileGateway userProfileGateway;
|
||||||
private final OnlineStatusCommon onlineStatusCommon;
|
private final OnlineStatusCommon onlineStatusCommon;
|
||||||
|
private final UserDailyActiveService userDailyActiveService;
|
||||||
private final MessageEventProcess messageEventProcess;
|
private final MessageEventProcess messageEventProcess;
|
||||||
private final CountUserActiveIndexService countUserActiveIndexService;
|
private final CountUserActiveIndexService countUserActiveIndexService;
|
||||||
|
|
||||||
@ -80,6 +82,13 @@ public class OnlineStatusUploadListener implements MessageListener {
|
|||||||
teamMemberService.updateActiveTimeNow(eventBody.getUserId());
|
teamMemberService.updateActiveTimeNow(eventBody.getUserId());
|
||||||
// 用户活跃时间刷新
|
// 用户活跃时间刷新
|
||||||
expandService.updateLastActiveTime(eventBody.getUserId());
|
expandService.updateLastActiveTime(eventBody.getUserId());
|
||||||
|
// 记录每日活跃
|
||||||
|
userDailyActiveService.record(
|
||||||
|
eventBody.getUserId(),
|
||||||
|
Objects.toString(eventBody.getSysOrigin()),
|
||||||
|
userProfile.getCountryCode(),
|
||||||
|
expandService.getLanguageStr(eventBody.getUserId())
|
||||||
|
);
|
||||||
|
|
||||||
// 累计在线时长
|
// 累计在线时长
|
||||||
if (Objects.equals(eventBody.getTask(), Boolean.TRUE)) {
|
if (Objects.equals(eventBody.getTask(), Boolean.TRUE)) {
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.red.circle.other.infra.database.cache.key.user;
|
||||||
|
|
||||||
|
import com.red.circle.component.redis.RedisKeys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户每日活跃缓存key.
|
||||||
|
*/
|
||||||
|
public enum UserDailyActiveKey implements RedisKeys {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户当日活跃去重标记. key格式: USER_DAILY_ACTIVE:ACTIVE_FLAG:{userId}:{activeDate}
|
||||||
|
*/
|
||||||
|
ACTIVE_FLAG;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String businessPrefix() {
|
||||||
|
return "USER_DAILY_ACTIVE";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String businessKey() {
|
||||||
|
return this.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.red.circle.other.infra.database.mongo.entity.user.active;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.springframework.data.annotation.Id;
|
||||||
|
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||||
|
import org.springframework.data.mongodb.core.index.CompoundIndexes;
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户每日活跃日志.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@Document("user_daily_active_log")
|
||||||
|
@CompoundIndexes({
|
||||||
|
@CompoundIndex(name = "idx_uid_date", def = "{'userId': 1, 'activeDate': 1}", unique = true),
|
||||||
|
@CompoundIndex(name = "idx_date_origin", def = "{'activeDate': 1, 'sysOrigin': 1}"),
|
||||||
|
@CompoundIndex(name = "idx_date_country", def = "{'activeDate': 1, 'registerCountryCode': 1}")
|
||||||
|
})
|
||||||
|
public class UserDailyActiveLog implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 用户id. */
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/** 活跃日期(北京时间 yyyy-MM-dd). */
|
||||||
|
private String activeDate;
|
||||||
|
|
||||||
|
/** 来源系统. */
|
||||||
|
private String sysOrigin;
|
||||||
|
|
||||||
|
/** 注册国家code. */
|
||||||
|
private String registerCountryCode;
|
||||||
|
|
||||||
|
/** 用户语言. */
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
/** 当日活跃次数. */
|
||||||
|
private Integer activeCount;
|
||||||
|
|
||||||
|
/** 当日首次活跃时间. */
|
||||||
|
private Timestamp firstActiveTime;
|
||||||
|
|
||||||
|
/** 当日最后活跃时间. */
|
||||||
|
private Timestamp lastActiveTime;
|
||||||
|
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
private Timestamp updateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.red.circle.other.infra.database.mongo.service.user.active;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户每日活跃日志服务.
|
||||||
|
*/
|
||||||
|
public interface UserDailyActiveService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录用户当日活跃.
|
||||||
|
*
|
||||||
|
* @param userId 用户id
|
||||||
|
* @param sysOrigin 来源系统
|
||||||
|
* @param registerCountryCode 注册国家code
|
||||||
|
* @param language 用户语言
|
||||||
|
*/
|
||||||
|
void record(Long userId, String sysOrigin, String registerCountryCode, String language);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package com.red.circle.other.infra.database.mongo.service.user.active.impl;
|
||||||
|
|
||||||
|
import com.red.circle.other.infra.database.cache.key.user.UserDailyActiveKey;
|
||||||
|
import com.red.circle.other.infra.database.mongo.entity.user.active.UserDailyActiveLog;
|
||||||
|
import com.red.circle.other.infra.database.mongo.service.user.active.UserDailyActiveService;
|
||||||
|
import com.red.circle.other.infra.utils.ZonedDateTimeUtils;
|
||||||
|
import com.red.circle.tool.core.sequence.IdWorkerUtils;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria;
|
||||||
|
import org.springframework.data.mongodb.core.query.Query;
|
||||||
|
import org.springframework.data.mongodb.core.query.Update;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户每日活跃日志服务.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserDailyActiveServiceImpl implements UserDailyActiveService {
|
||||||
|
|
||||||
|
private final MongoTemplate mongoTemplate;
|
||||||
|
private final StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void record(Long userId, String sysOrigin, String registerCountryCode, String language) {
|
||||||
|
ZonedDateTime now = ZonedDateTimeUtils.nowAsiaShanghai();
|
||||||
|
String activeDate = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
Timestamp nowTs = Timestamp.from(now.toInstant());
|
||||||
|
|
||||||
|
String redisKey = UserDailyActiveKey.ACTIVE_FLAG.getKey(userId, activeDate);
|
||||||
|
boolean isFirst = Boolean.TRUE.equals(
|
||||||
|
stringRedisTemplate.opsForValue().setIfAbsent(redisKey, "1", 2, TimeUnit.DAYS)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isFirst) {
|
||||||
|
UserDailyActiveLog log = new UserDailyActiveLog()
|
||||||
|
.setId(IdWorkerUtils.getId())
|
||||||
|
.setUserId(userId)
|
||||||
|
.setActiveDate(activeDate)
|
||||||
|
.setSysOrigin(sysOrigin)
|
||||||
|
.setRegisterCountryCode(registerCountryCode)
|
||||||
|
.setLanguage(language)
|
||||||
|
.setActiveCount(1)
|
||||||
|
.setFirstActiveTime(nowTs)
|
||||||
|
.setLastActiveTime(nowTs)
|
||||||
|
.setCreateTime(nowTs)
|
||||||
|
.setUpdateTime(nowTs);
|
||||||
|
mongoTemplate.insert(log);
|
||||||
|
} else {
|
||||||
|
mongoTemplate.updateFirst(
|
||||||
|
Query.query(Criteria.where("userId").is(userId).and("activeDate").is(activeDate)),
|
||||||
|
new Update()
|
||||||
|
.inc("activeCount", 1)
|
||||||
|
.set("lastActiveTime", nowTs)
|
||||||
|
.set("updateTime", nowTs),
|
||||||
|
UserDailyActiveLog.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user