新增用户每日活跃记录功能
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.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.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.OnlineTimeService;
|
||||
import com.red.circle.other.inner.enums.user.UserOnlineStatusEnum;
|
||||
@ -50,6 +51,7 @@ public class OnlineStatusUploadListener implements MessageListener {
|
||||
private final OnlineTimeService onlineTimeService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final OnlineStatusCommon onlineStatusCommon;
|
||||
private final UserDailyActiveService userDailyActiveService;
|
||||
private final MessageEventProcess messageEventProcess;
|
||||
private final CountUserActiveIndexService countUserActiveIndexService;
|
||||
|
||||
@ -80,6 +82,13 @@ public class OnlineStatusUploadListener implements MessageListener {
|
||||
teamMemberService.updateActiveTimeNow(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)) {
|
||||
|
||||
@ -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