232 lines
10 KiB
Go
232 lines
10 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
)
|
|
|
|
func (r *MySQLRepository) upsertDailyAmountTotals(ctx context.Context, tx *sql.Tx, key dailyAmountKey, totals amountTotals) error {
|
|
_, err := tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_daily_metric (
|
|
stat_date, date_number, sys_origin, country_code, country_name,
|
|
new_user_recharge, official_recharge, mifapay_recharge, google_recharge,
|
|
dealer_recharge, salary_exchange, lucky_gift_total_flow, lucky_gift_payout,
|
|
game_total_flow, game_payout, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE
|
|
country_name = VALUES(country_name),
|
|
new_user_recharge = new_user_recharge + VALUES(new_user_recharge),
|
|
official_recharge = official_recharge + VALUES(official_recharge),
|
|
mifapay_recharge = mifapay_recharge + VALUES(mifapay_recharge),
|
|
google_recharge = google_recharge + VALUES(google_recharge),
|
|
dealer_recharge = dealer_recharge + VALUES(dealer_recharge),
|
|
salary_exchange = salary_exchange + VALUES(salary_exchange),
|
|
lucky_gift_total_flow = lucky_gift_total_flow + VALUES(lucky_gift_total_flow),
|
|
lucky_gift_payout = lucky_gift_payout + VALUES(lucky_gift_payout),
|
|
game_total_flow = game_total_flow + VALUES(game_total_flow),
|
|
game_payout = game_payout + VALUES(game_payout),
|
|
refreshed_at = NOW()
|
|
`, key.day, dateNumber(key.day), key.sysOrigin, key.countryCode, key.countryName,
|
|
totals.newUserRecharge, totals.officialRecharge, totals.mifapayRecharge, totals.googleRecharge,
|
|
totals.dealerRecharge, totals.salaryExchange, totals.luckyGiftTotalFlow, totals.luckyGiftPayout,
|
|
totals.gameTotalFlow, totals.gamePayout)
|
|
return err
|
|
}
|
|
|
|
func (r *MySQLRepository) upsertPeriodAmountTotals(ctx context.Context, tx *sql.Tx, key periodAmountKey, totals amountTotals) error {
|
|
_, err := tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_period_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, new_user_recharge, official_recharge, mifapay_recharge,
|
|
google_recharge, dealer_recharge, salary_exchange, lucky_gift_total_flow, lucky_gift_payout,
|
|
game_total_flow, game_payout, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE
|
|
period_name = VALUES(period_name),
|
|
period_start_date = VALUES(period_start_date),
|
|
period_end_date = VALUES(period_end_date),
|
|
country_name = VALUES(country_name),
|
|
new_user_recharge = new_user_recharge + VALUES(new_user_recharge),
|
|
official_recharge = official_recharge + VALUES(official_recharge),
|
|
mifapay_recharge = mifapay_recharge + VALUES(mifapay_recharge),
|
|
google_recharge = google_recharge + VALUES(google_recharge),
|
|
dealer_recharge = dealer_recharge + VALUES(dealer_recharge),
|
|
salary_exchange = salary_exchange + VALUES(salary_exchange),
|
|
lucky_gift_total_flow = lucky_gift_total_flow + VALUES(lucky_gift_total_flow),
|
|
lucky_gift_payout = lucky_gift_payout + VALUES(lucky_gift_payout),
|
|
game_total_flow = game_total_flow + VALUES(game_total_flow),
|
|
game_payout = game_payout + VALUES(game_payout),
|
|
refreshed_at = NOW()
|
|
`, key.periodType, key.periodKey, key.statTimezone, key.periodName, ptrOrNil(key.startDate), ptrOrNil(key.endDate),
|
|
key.sysOrigin, key.countryCode, key.countryName, totals.newUserRecharge, totals.officialRecharge,
|
|
totals.mifapayRecharge, totals.googleRecharge, totals.dealerRecharge, totals.salaryExchange,
|
|
totals.luckyGiftTotalFlow, totals.luckyGiftPayout, totals.gameTotalFlow, totals.gamePayout)
|
|
return err
|
|
}
|
|
|
|
func (r *MySQLRepository) upsertGameAmountTotals(ctx context.Context, tx *sql.Tx, key gameAmountKey, totals gameAmountTotals) error {
|
|
_, err := tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_game_period_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, game_provider, game_id, game_name,
|
|
consume_amount, payout_amount, profit_amount, order_count, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE
|
|
period_name = VALUES(period_name),
|
|
period_start_date = VALUES(period_start_date),
|
|
period_end_date = VALUES(period_end_date),
|
|
country_name = VALUES(country_name),
|
|
game_name = VALUES(game_name),
|
|
consume_amount = consume_amount + VALUES(consume_amount),
|
|
payout_amount = payout_amount + VALUES(payout_amount),
|
|
profit_amount = profit_amount + VALUES(profit_amount),
|
|
order_count = order_count + VALUES(order_count),
|
|
refreshed_at = NOW()
|
|
`, key.periodType, key.periodKey, key.statTimezone, key.periodName, ptrOrNil(key.startDate), ptrOrNil(key.endDate),
|
|
key.sysOrigin, key.countryCode, key.countryName, key.gameProvider, key.gameID, key.gameName,
|
|
totals.consume, totals.payout, totals.profit, totals.orders)
|
|
return err
|
|
}
|
|
|
|
func (r *MySQLRepository) applyDailyUserGroup(ctx context.Context, tx *sql.Tx, key dailyUserKey, users map[int64]struct{}) error {
|
|
ids := userIDs(users)
|
|
inserted, err := bulkInsertDailyUsers(ctx, tx, key, ids)
|
|
if err != nil || inserted == 0 {
|
|
return err
|
|
}
|
|
column := dailyMetricColumn(key.metricType)
|
|
if column == "" {
|
|
return nil
|
|
}
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_daily_metric (
|
|
stat_date, date_number, sys_origin, country_code, country_name, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE `+column+` = `+column+` + ?, country_name = VALUES(country_name), refreshed_at = NOW()
|
|
`, key.day, dateNumber(key.day), key.sysOrigin, key.countryCode, key.countryName, inserted)
|
|
return err
|
|
}
|
|
|
|
func (r *MySQLRepository) applyPeriodUserGroup(ctx context.Context, tx *sql.Tx, key periodUserKey, users map[int64]struct{}) error {
|
|
ids := userIDs(users)
|
|
inserted, err := bulkInsertPeriodUsers(ctx, tx, key, ids)
|
|
if err != nil || inserted == 0 {
|
|
return err
|
|
}
|
|
column := periodMetricColumn(key.metricType)
|
|
if column == "" {
|
|
return nil
|
|
}
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_period_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE `+column+` = `+column+` + ?, country_name = VALUES(country_name), refreshed_at = NOW()
|
|
`, key.periodType, key.periodKey, key.statTimezone, key.periodName, ptrOrNil(key.startDate), ptrOrNil(key.endDate),
|
|
key.sysOrigin, key.countryCode, key.countryName, inserted)
|
|
return err
|
|
}
|
|
|
|
func (r *MySQLRepository) applyGameUserGroup(ctx context.Context, tx *sql.Tx, key gameUserKey, users map[int64]struct{}) error {
|
|
ids := userIDs(users)
|
|
inserted, err := bulkInsertGameUsers(ctx, tx, key, ids)
|
|
if err != nil || inserted == 0 {
|
|
return err
|
|
}
|
|
_, err = tx.ExecContext(ctx, `
|
|
INSERT INTO country_dashboard_game_period_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, game_provider, game_id, game_name, user_count, refreshed_at
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())
|
|
ON DUPLICATE KEY UPDATE user_count = user_count + VALUES(user_count), country_name = VALUES(country_name),
|
|
game_name = VALUES(game_name), refreshed_at = NOW()
|
|
`, key.periodType, key.periodKey, key.statTimezone, key.periodName, ptrOrNil(key.startDate), ptrOrNil(key.endDate),
|
|
key.sysOrigin, key.countryCode, key.countryName, key.gameProvider, key.gameID, key.gameName, inserted)
|
|
return err
|
|
}
|
|
|
|
func bulkInsertDailyUsers(ctx context.Context, tx *sql.Tx, key dailyUserKey, ids []int64) (int64, error) {
|
|
var inserted int64
|
|
for start := 0; start < len(ids); start += bulkInsertChunkSize {
|
|
end := min(start+bulkInsertChunkSize, len(ids))
|
|
args := make([]interface{}, 0, (end-start)*6)
|
|
for _, userID := range ids[start:end] {
|
|
args = append(args, key.day, key.sysOrigin, key.countryCode, key.countryName, userID, key.metricType)
|
|
}
|
|
result, err := tx.ExecContext(ctx, `
|
|
INSERT IGNORE INTO country_dashboard_daily_user_metric (
|
|
stat_date, sys_origin, country_code, country_name, user_id, metric_type
|
|
) VALUES `+placeholders(end-start, 6), args...)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
inserted += affected
|
|
}
|
|
return inserted, nil
|
|
}
|
|
|
|
func bulkInsertPeriodUsers(ctx context.Context, tx *sql.Tx, key periodUserKey, ids []int64) (int64, error) {
|
|
var inserted int64
|
|
for start := 0; start < len(ids); start += bulkInsertChunkSize {
|
|
end := min(start+bulkInsertChunkSize, len(ids))
|
|
args := make([]interface{}, 0, (end-start)*11)
|
|
for _, userID := range ids[start:end] {
|
|
args = append(args, key.periodType, key.periodKey, key.statTimezone, key.periodName,
|
|
ptrOrNil(key.startDate), ptrOrNil(key.endDate), key.sysOrigin, key.countryCode,
|
|
key.countryName, userID, key.metricType)
|
|
}
|
|
result, err := tx.ExecContext(ctx, `
|
|
INSERT IGNORE INTO country_dashboard_period_user_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, user_id, metric_type
|
|
) VALUES `+placeholders(end-start, 11), args...)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
inserted += affected
|
|
}
|
|
return inserted, nil
|
|
}
|
|
|
|
func bulkInsertGameUsers(ctx context.Context, tx *sql.Tx, key gameUserKey, ids []int64) (int64, error) {
|
|
var inserted int64
|
|
for start := 0; start < len(ids); start += bulkInsertChunkSize {
|
|
end := min(start+bulkInsertChunkSize, len(ids))
|
|
args := make([]interface{}, 0, (end-start)*12)
|
|
for _, userID := range ids[start:end] {
|
|
args = append(args, key.periodType, key.periodKey, key.statTimezone, key.periodName,
|
|
ptrOrNil(key.startDate), ptrOrNil(key.endDate), key.sysOrigin, key.countryCode,
|
|
key.countryName, key.gameProvider, key.gameID, userID)
|
|
}
|
|
result, err := tx.ExecContext(ctx, `
|
|
INSERT IGNORE INTO country_dashboard_game_period_user_metric (
|
|
period_type, period_key, stat_timezone, period_name, period_start_date, period_end_date,
|
|
sys_origin, country_code, country_name, game_provider, game_id, user_id
|
|
) VALUES `+placeholders(end-start, 12), args...)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
affected, err := result.RowsAffected()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
inserted += affected
|
|
}
|
|
return inserted, nil
|
|
}
|
|
|
|
func dateNumber(day time.Time) int {
|
|
year, month, date := day.Date()
|
|
return year*10000 + int(month)*100 + date
|
|
}
|