Files
tencent-im-util/src/main/java/com/imutil/mapper/UsageStatMapper.java
T
yixiongandClaude d22fdcfaad feat: 初始化腾讯IM分发工具骨架,含回调分发链路与历史消息补拉
- 应用骨架: Solon + MyBatis-Plus + PostgreSQL + Redis + Sa-Token
- 核心链路: 回调网关 → 消息落库(幂等) → 分发队列(FOR UPDATE SKIP LOCKED) → worker消费/重试/死信
- 多租户隔离: 前缀法账号映射, 所有业务表带 tenant_id
- 管理后台: FreeMarker 渲染, 租户/授权/队列/用量管理页面
- 历史消息补拉: 水位线驱动, getRoamMsg/getGroupMsg 增量拉取, 兜底回调丢失
- msg_key 统一算法(回调/补拉共享, 跨路径去重)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-08 20:28:32 +08:00

61 lines
2.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.imutil.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.imutil.entity.UsageStat;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import java.time.OffsetDateTime;
/**
* 用量统计 Mapper
* <p>
* 提供按小时窗口的聚合 upsertPG ON CONFLICT 幂等,可重复跑)。
* 两个数据源各自 upsert 指定列,避免互相覆盖:
* - im_message → im_msg_count / im_dau
* - api_call_log → api_call_count
*
* @author imutil
*/
public interface UsageStatMapper extends BaseMapper<UsageStat> {
/**
* 从 im_message 聚合某小时窗口的消息量与活跃用户数,upsert 到 usage_statstat_level=1 小时)
* <p>
* 仅更新 im_msg_count / im_dau,不触碰已有 api_call_count。
*
* @param start 窗口起点(含)
* @param end 窗口终点(不含)
* @param statTime 统计时刻(=窗口起点整点,作为 usage_stat.stat_time
* @return 受影响租户数
*/
@Insert("INSERT INTO usage_stat (tenant_id, stat_time, stat_level, im_msg_count, im_dau, " +
"api_call_count, trtc_duration_sec, trtc_max_concurrent_room, created_at) " +
"SELECT tenant_id, #{statTime}, 1, count(*), count(DISTINCT from_account), 0, 0, 0, now() " +
"FROM im_message WHERE created_at >= #{start} AND created_at < #{end} " +
"GROUP BY tenant_id " +
"ON CONFLICT (tenant_id, stat_time, stat_level) DO UPDATE SET " +
"im_msg_count = EXCLUDED.im_msg_count, im_dau = EXCLUDED.im_dau")
int aggregateMsgHour(@Param("start") OffsetDateTime start,
@Param("end") OffsetDateTime end,
@Param("statTime") OffsetDateTime statTime);
/**
* 从 api_call_log 聚合某小时窗口的腾讯 API 调用次数,upsert 到 usage_statstat_level=1 小时)
* <p>
* 仅更新 api_call_count,不触碰已有 im_msg_count / im_dau。
*
* @return 受影响租户数
*/
@Insert("INSERT INTO usage_stat (tenant_id, stat_time, stat_level, im_msg_count, im_dau, " +
"api_call_count, trtc_duration_sec, trtc_max_concurrent_room, created_at) " +
"SELECT tenant_id, #{statTime}, 1, 0, 0, count(*), 0, 0, now() " +
"FROM api_call_log WHERE called_at >= #{start} AND called_at < #{end} " +
"GROUP BY tenant_id " +
"ON CONFLICT (tenant_id, stat_time, stat_level) DO UPDATE SET " +
"api_call_count = EXCLUDED.api_call_count")
int aggregateApiCallHour(@Param("start") OffsetDateTime start,
@Param("end") OffsetDateTime end,
@Param("statTime") OffsetDateTime statTime);
}