refactor: improve system stability, performance, and code structure
All checks were successful
Build Backend / build (push) Successful in 3m2s
Build Backend / build-docker (push) Successful in 2m44s

This commit introduces several architectural improvements and optimizations across the codebase:

- **Performance & Reliability**:
  - Implemented Redis pipelining in `ConversationCache.CacheMessage` to reduce network round-trips.
  - Added a circuit breaker to the JPush client to prevent cascading failures.
  - Introduced batch deletion and batch member addition capabilities in repositories.
  - Added message idempotency support using `client_msg_id` and a Redis-based cache.
  - Optimized WebSocket handling with connection limits (total and per-user) and improved error logging.

- **Code Refactoring**:
  - Refactored `Router` to use a `RouterDeps` struct, simplifying the constructor and improving maintainability.
  - Unified model ID generation logic using new `id_helper.go` (supporting UUID and Snowflake).
  - Standardized JSON serialization/deserialization in models using `json_helper.go`.
  - Refactored DTO conversion logic, specifically for `UserResponse` (using functional options) and `Report` responses.
  - Removed redundant/deprecated DTOs like `PostDetailResponse` and `TradeItemDetailResponse`.

- **Cache Improvements**:
  - Enhanced `LayeredCache` with `SetRaw` to avoid double-encoding when promoting values from Redis to local cache.
  - Added `DeleteBatch` support to the cache interface.

- **Other Changes**:
  - Cleaned up `config.go` by removing redundant default values and explicit environment variable overrides.
  - Improved WebSocket registration flow to handle connection limits gracefully.
This commit is contained in:
2026-05-04 13:07:03 +08:00
parent b2b55ea52d
commit ee78071d4d
65 changed files with 1293 additions and 975 deletions

View File

@@ -108,6 +108,12 @@ type AdminBatchHandleResponse struct {
// ==================== 转换函数 ====================
func baseAdminReportFields(report *model.Report) (string, string) {
reason := string(report.Reason)
status := string(report.Status)
return reason, status
}
// ConvertReportToResponse 将 Report 模型转换为响应
func ConvertReportToResponse(report *model.Report) *ReportResponse {
return &ReportResponse{
@@ -122,6 +128,19 @@ func ConvertReportToResponse(report *model.Report) *ReportResponse {
}
}
func fillAdminReportCommon(resp *AdminReportListResponse, report *model.Report, reporter *model.User, handler *model.User) {
if reporter != nil {
resp.Reporter = ConvertUserToResponse(reporter)
}
if handler != nil {
resp.Handler = ConvertUserToResponse(handler)
}
if report.HandledAt != nil {
handledAt := FormatTime(*report.HandledAt)
resp.HandledAt = &handledAt
}
}
// ConvertReportToAdminListResponse 将 Report 转换为管理端列表响应
func ConvertReportToAdminListResponse(report *model.Report, reporter *model.User, handler *model.User) *AdminReportListResponse {
resp := &AdminReportListResponse{
@@ -136,51 +155,34 @@ func ConvertReportToAdminListResponse(report *model.Report, reporter *model.User
Result: report.Result,
CreatedAt: FormatTime(report.CreatedAt),
}
if reporter != nil {
resp.Reporter = ConvertUserToResponse(reporter)
}
if handler != nil {
resp.Handler = ConvertUserToResponse(handler)
}
if report.HandledAt != nil {
handledAt := FormatTime(*report.HandledAt)
resp.HandledAt = &handledAt
}
fillAdminReportCommon(resp, report, reporter, handler)
return resp
}
// ConvertReportToAdminDetailResponse 将 Report 转换为管理端详情响应
func ConvertReportToAdminDetailResponse(report *model.Report, reporter *model.User, handler *model.User, targetContent *ReportTargetContent) *AdminReportDetailResponse {
resp := &AdminReportDetailResponse{
ID: report.ID,
ReporterID: report.ReporterID,
TargetType: string(report.TargetType),
TargetID: report.TargetID,
Reason: string(report.Reason),
Description: report.Description,
Status: string(report.Status),
HandledBy: report.HandledBy,
Result: report.Result,
CreatedAt: FormatTime(report.CreatedAt),
ID: report.ID,
ReporterID: report.ReporterID,
TargetType: string(report.TargetType),
TargetID: report.TargetID,
Reason: string(report.Reason),
Description: report.Description,
Status: string(report.Status),
HandledBy: report.HandledBy,
Result: report.Result,
CreatedAt: FormatTime(report.CreatedAt),
TargetContent: targetContent,
}
if reporter != nil {
resp.Reporter = ConvertUserToResponse(reporter)
}
if handler != nil {
resp.Handler = ConvertUserToResponse(handler)
}
if report.HandledAt != nil {
handledAt := FormatTime(*report.HandledAt)
resp.HandledAt = &handledAt
}
return resp
}