You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							124 lines
						
					
					
						
							4.6 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							124 lines
						
					
					
						
							4.6 KiB
						
					
					
				| package integration | |
| 
 | |
| import ( | |
| 	"strings" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/mq_pb" | |
| ) | |
| 
 | |
| // Kafka Protocol Error Codes (copied from protocol package to avoid import cycle) | |
| const ( | |
| 	kafkaErrorCodeNone                    int16 = 0 | |
| 	kafkaErrorCodeUnknownServerError      int16 = 1 | |
| 	kafkaErrorCodeUnknownTopicOrPartition int16 = 3 | |
| 	kafkaErrorCodeNotLeaderOrFollower     int16 = 6 | |
| 	kafkaErrorCodeRequestTimedOut         int16 = 7 | |
| 	kafkaErrorCodeBrokerNotAvailable      int16 = 8 | |
| 	kafkaErrorCodeMessageTooLarge         int16 = 10 | |
| 	kafkaErrorCodeNetworkException        int16 = 13 | |
| 	kafkaErrorCodeOffsetLoadInProgress    int16 = 14 | |
| 	kafkaErrorCodeTopicAlreadyExists      int16 = 36 | |
| 	kafkaErrorCodeInvalidPartitions       int16 = 37 | |
| 	kafkaErrorCodeInvalidConfig           int16 = 40 | |
| 	kafkaErrorCodeInvalidRecord           int16 = 42 | |
| ) | |
| 
 | |
| // MapBrokerErrorToKafka maps a broker error code to the corresponding Kafka protocol error code | |
| func MapBrokerErrorToKafka(brokerErrorCode int32) int16 { | |
| 	switch brokerErrorCode { | |
| 	case 0: // BrokerErrorNone | |
| 		return kafkaErrorCodeNone | |
| 	case 1: // BrokerErrorUnknownServerError | |
| 		return kafkaErrorCodeUnknownServerError | |
| 	case 2: // BrokerErrorTopicNotFound | |
| 		return kafkaErrorCodeUnknownTopicOrPartition | |
| 	case 3: // BrokerErrorPartitionNotFound | |
| 		return kafkaErrorCodeUnknownTopicOrPartition | |
| 	case 6: // BrokerErrorNotLeaderOrFollower | |
| 		return kafkaErrorCodeNotLeaderOrFollower | |
| 	case 7: // BrokerErrorRequestTimedOut | |
| 		return kafkaErrorCodeRequestTimedOut | |
| 	case 8: // BrokerErrorBrokerNotAvailable | |
| 		return kafkaErrorCodeBrokerNotAvailable | |
| 	case 10: // BrokerErrorMessageTooLarge | |
| 		return kafkaErrorCodeMessageTooLarge | |
| 	case 13: // BrokerErrorNetworkException | |
| 		return kafkaErrorCodeNetworkException | |
| 	case 14: // BrokerErrorOffsetLoadInProgress | |
| 		return kafkaErrorCodeOffsetLoadInProgress | |
| 	case 42: // BrokerErrorInvalidRecord | |
| 		return kafkaErrorCodeInvalidRecord | |
| 	case 36: // BrokerErrorTopicAlreadyExists | |
| 		return kafkaErrorCodeTopicAlreadyExists | |
| 	case 37: // BrokerErrorInvalidPartitions | |
| 		return kafkaErrorCodeInvalidPartitions | |
| 	case 40: // BrokerErrorInvalidConfig | |
| 		return kafkaErrorCodeInvalidConfig | |
| 	case 100: // BrokerErrorPublisherNotFound | |
| 		return kafkaErrorCodeUnknownServerError | |
| 	case 101: // BrokerErrorConnectionFailed | |
| 		return kafkaErrorCodeNetworkException | |
| 	case 102: // BrokerErrorFollowerConnectionFailed | |
| 		return kafkaErrorCodeNetworkException | |
| 	default: | |
| 		// Unknown broker error code, default to unknown server error | |
| 		return kafkaErrorCodeUnknownServerError | |
| 	} | |
| } | |
| 
 | |
| // HandleBrokerResponse processes a broker response and returns appropriate error information | |
| // Returns (kafkaErrorCode, errorMessage, error) where error is non-nil for system errors | |
| func HandleBrokerResponse(resp *mq_pb.PublishMessageResponse) (int16, string, error) { | |
| 	if resp.Error == "" && resp.ErrorCode == 0 { | |
| 		// No error | |
| 		return kafkaErrorCodeNone, "", nil | |
| 	} | |
| 
 | |
| 	// Use structured error code if available, otherwise fall back to string parsing | |
| 	if resp.ErrorCode != 0 { | |
| 		kafkaErrorCode := MapBrokerErrorToKafka(resp.ErrorCode) | |
| 		return kafkaErrorCode, resp.Error, nil | |
| 	} | |
| 
 | |
| 	// Fallback: parse string error for backward compatibility | |
| 	// This handles cases where older brokers might not set ErrorCode | |
| 	kafkaErrorCode := parseStringErrorToKafkaCode(resp.Error) | |
| 	return kafkaErrorCode, resp.Error, nil | |
| } | |
| 
 | |
| // parseStringErrorToKafkaCode provides backward compatibility for string-based error parsing | |
| // This is the old brittle approach that we're replacing with structured error codes | |
| func parseStringErrorToKafkaCode(errorMsg string) int16 { | |
| 	if errorMsg == "" { | |
| 		return kafkaErrorCodeNone | |
| 	} | |
| 
 | |
| 	// Check for common error patterns (brittle string matching) | |
| 	switch { | |
| 	case containsAny(errorMsg, "not the leader", "not leader"): | |
| 		return kafkaErrorCodeNotLeaderOrFollower | |
| 	case containsAny(errorMsg, "topic", "not found", "does not exist"): | |
| 		return kafkaErrorCodeUnknownTopicOrPartition | |
| 	case containsAny(errorMsg, "partition", "not found"): | |
| 		return kafkaErrorCodeUnknownTopicOrPartition | |
| 	case containsAny(errorMsg, "timeout", "timed out"): | |
| 		return kafkaErrorCodeRequestTimedOut | |
| 	case containsAny(errorMsg, "network", "connection"): | |
| 		return kafkaErrorCodeNetworkException | |
| 	case containsAny(errorMsg, "too large", "size"): | |
| 		return kafkaErrorCodeMessageTooLarge | |
| 	default: | |
| 		return kafkaErrorCodeUnknownServerError | |
| 	} | |
| } | |
| 
 | |
| // containsAny checks if the text contains any of the given substrings (case-insensitive) | |
| func containsAny(text string, substrings ...string) bool { | |
| 	textLower := strings.ToLower(text) | |
| 	for _, substr := range substrings { | |
| 		if strings.Contains(textLower, strings.ToLower(substr)) { | |
| 			return true | |
| 		} | |
| 	} | |
| 	return false | |
| }
 |