package storage import ( "context" "database/sql" "time" "dashboard-cdc-worker/internal/dashboard" ) func (r *MySQLRepository) UpsertUserCountry(ctx context.Context, tx *sql.Tx, user dashboard.UserCountry) error { _, err := tx.ExecContext(ctx, ` INSERT INTO dashboard_cdc_user_country ( user_id, sys_origin, country_code, country_name, is_deleted, user_created_at, user_updated_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE sys_origin = VALUES(sys_origin), country_code = VALUES(country_code), country_name = VALUES(country_name), is_deleted = VALUES(is_deleted), user_created_at = VALUES(user_created_at), user_updated_at = VALUES(user_updated_at), updated_at = NOW() `, user.UserID, user.SysOrigin, user.Country.Code, user.Country.Name, user.IsDeleted, nullTime(user.CreatedAt), nullTime(user.UpdatedAt)) if err == nil { r.userCache.Set(user.UserID, user) } return err } func (r *MySQLRepository) UserCountry(ctx context.Context, userID int64) (dashboard.UserCountry, bool, error) { if user, ok := r.userCache.Get(userID); ok { return user, true, nil } var user dashboard.UserCountry var countryCode, countryName string var isDeleted bool var createdAt, updatedAt sql.NullTime err := r.db.QueryRowContext(ctx, ` SELECT user_id, sys_origin, country_code, country_name, is_deleted, user_created_at, user_updated_at FROM dashboard_cdc_user_country WHERE user_id = ? `, userID).Scan(&user.UserID, &user.SysOrigin, &countryCode, &countryName, &isDeleted, &createdAt, &updatedAt) if err == sql.ErrNoRows { return r.userCountryFromSource(ctx, userID) } if err != nil { return dashboard.UserCountry{}, false, err } user.Country = dashboard.Country{Code: countryCode, Name: countryName} user.IsDeleted = isDeleted if createdAt.Valid { user.CreatedAt = createdAt.Time } if updatedAt.Valid { user.UpdatedAt = updatedAt.Time } r.userCache.Set(userID, user) return user, true, nil } func (r *MySQLRepository) userCountryFromSource(ctx context.Context, userID int64) (dashboard.UserCountry, bool, error) { var user dashboard.UserCountry var countryCode, countryName string var isDeleted bool var createdAt, updatedAt sql.NullTime err := r.db.QueryRowContext(ctx, ` SELECT id, origin_sys, IFNULL(NULLIF(country_code, ''), ?), IFNULL(NULLIF(country_name, ''), IFNULL(NULLIF(country_code, ''), ?)), IFNULL(is_del, 0), create_time, update_time FROM user_base_info WHERE id = ? `, r.cfg.Dashboard.UnknownCountryCode, r.cfg.Dashboard.UnknownCountryCode, userID). Scan(&user.UserID, &user.SysOrigin, &countryCode, &countryName, &isDeleted, &createdAt, &updatedAt) if err == sql.ErrNoRows { return dashboard.UserCountry{}, false, nil } if err != nil { return dashboard.UserCountry{}, false, err } user.Country = dashboard.Country{Code: countryCode, Name: countryName} user.IsDeleted = isDeleted if createdAt.Valid { user.CreatedAt = createdAt.Time } if updatedAt.Valid { user.UpdatedAt = updatedAt.Time } _, _ = r.db.ExecContext(ctx, ` INSERT INTO dashboard_cdc_user_country ( user_id, sys_origin, country_code, country_name, is_deleted, user_created_at, user_updated_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE updated_at = updated_at `, user.UserID, user.SysOrigin, user.Country.Code, user.Country.Name, user.IsDeleted, nullTime(user.CreatedAt), nullTime(user.UpdatedAt)) r.userCache.Set(userID, user) return user, true, nil } func nullTime(value time.Time) interface{} { if value.IsZero() { return nil } return value }