2026-05-27 18:11:30 +08:00

79 lines
2.5 KiB
Go

package storage
import (
"context"
"crypto/sha1"
"database/sql"
"encoding/hex"
"strings"
"time"
"github.com/shopspring/decimal"
"dashboard-cdc-worker/internal/dashboard"
)
func (r *MySQLRepository) upsertGameEventFact(ctx context.Context, tx *sql.Tx, c dashboard.Contribution, storageZone *time.Location) error {
if !isGameFact(c) {
return nil
}
if storageZone == nil {
storageZone = time.UTC
}
deltaSign := c.DeltaSign
if deltaSign == 0 {
deltaSign = 1
}
sign := decimal.NewFromInt(int64(deltaSign))
consume := c.GameConsume.Mul(sign)
payout := c.GamePayoutBy.Mul(sign)
profit := c.GameProfit.Mul(sign)
orderCount := c.GameOrder * int64(deltaSign)
_, err := tx.ExecContext(ctx, `
INSERT INTO dashboard_game_event_fact (
fact_key, source_schema, source_table, source_pk, source_action,
sys_origin, stat_date, event_time, user_id, country_code, country_name,
game_provider, game_id, game_name, consume_amount, payout_amount, profit_amount, order_count
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
source_action = VALUES(source_action),
sys_origin = VALUES(sys_origin),
stat_date = VALUES(stat_date),
event_time = VALUES(event_time),
user_id = VALUES(user_id),
country_code = VALUES(country_code),
country_name = VALUES(country_name),
game_provider = VALUES(game_provider),
game_id = VALUES(game_id),
game_name = VALUES(game_name),
consume_amount = VALUES(consume_amount),
payout_amount = VALUES(payout_amount),
profit_amount = VALUES(profit_amount),
order_count = VALUES(order_count),
updated_at = NOW()
`, gameFactKey(c), c.SourceSchema, c.SourceTable, c.SourcePK, c.SourceAction,
c.SysOrigin, dashboard.DailyDate(c.EventTime, storageZone), c.EventTime, c.UserID,
c.Country.Code, c.Country.Name, c.GameProvider, c.GameID, c.GameName,
consume, payout, profit, orderCount)
return err
}
func isGameFact(c dashboard.Contribution) bool {
return !c.EventTime.IsZero() &&
c.SysOrigin != "" &&
c.UserID != 0 &&
c.GameProvider != "" &&
c.GameID != "" &&
(!c.GameConsume.IsZero() || !c.GamePayoutBy.IsZero() || !c.GameProfit.IsZero() || c.GameOrder != 0 || c.GameUser)
}
func gameFactKey(c dashboard.Contribution) string {
parts := []string{c.EventKey, c.SourceSchema, c.SourceTable, c.SourcePK, c.SourceAction}
raw := strings.Join(parts, "|")
if len(raw) <= 255 && strings.Trim(raw, "|") != "" {
return raw
}
sum := sha1.Sum([]byte(raw))
return "game-fact:" + hex.EncodeToString(sum[:])
}