package mysql import ( "context" "crypto/sha256" "encoding/hex" "encoding/json" "errors" "fmt" "math" "strings" mysqlDriver "github.com/go-sql-driver/mysql" "hyapp/pkg/appcode" "hyapp/pkg/xerr" ) func contextWithCommandApp(ctx context.Context, value string) context.Context { if strings.TrimSpace(value) == "" { return appcode.WithContext(ctx, appcode.FromContext(ctx)) } return appcode.WithContext(ctx, value) } func normalizedEntryAppCode(ctx context.Context, value string) string { if strings.TrimSpace(value) == "" { return appcode.FromContext(ctx) } return appcode.Normalize(value) } func checkedMul(unit int64, count int64) (int64, error) { if unit < 0 || count <= 0 { return 0, xerr.New(xerr.InvalidArgument, "amount is invalid") } if unit != 0 && count > math.MaxInt64/unit { return 0, xerr.New(xerr.InvalidArgument, "amount overflow") } return unit * count, nil } func checkedAdd(left int64, right int64) (int64, error) { if right < 0 || left > math.MaxInt64-right { return 0, xerr.New(xerr.CoinSellerStockAmountInvalid, "coin amount overflow") } return left + right, nil } func checkedAddDelta(left int64, right int64) (int64, error) { if (right > 0 && left > math.MaxInt64-right) || (right < 0 && left < math.MinInt64-right) { return 0, xerr.New(xerr.CoinSellerStockAmountInvalid, "coin amount overflow") } return left + right, nil } func stableHash(value string) string { sum := sha256.Sum256([]byte(value)) return hex.EncodeToString(sum[:]) } // boundedDerivedCommandID 为内部子动作保留可读前缀,同时保证最终键不超过所有 // command_id VARCHAR(128) 的共同边界。正常短键保持历史值,极长客户端键才稳定收敛为哈希。 func boundedDerivedCommandID(prefix string, commandID string) string { commandID = strings.TrimSpace(commandID) derived := prefix + commandID if len(derived) <= 128 { return derived } return prefix + stableHash(commandID) } func mustJSON(value any) string { body, err := json.Marshal(value) if err != nil { return "{}" } return string(body) } func transactionID(appCode string, commandID string) string { return "wtx_" + stableHash(appcode.Normalize(appCode)+"|"+commandID) } func coinSellerStockID(appCode string, commandID string) string { return "cstock_" + stableHash(appcode.Normalize(appCode)+"|"+commandID) } func billingReceiptID(appCode string, commandID string) string { return "bill_" + stableHash(appcode.Normalize(appCode)+"|"+commandID) } func eventID(transactionID string, eventType string, userID int64, assetType string) string { return "wev_" + stableHash(fmt.Sprintf("%s|%s|%d|%s", transactionID, eventType, userID, assetType)) } func isMySQLDuplicateError(err error) bool { var mysqlErr *mysqlDriver.MySQLError return errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 }