com.xiaomi.infra.galaxy.talos.client.Utils Maven / Gradle / Ivy
/**
* Copyright 2015, Xiaomi.
* All rights reserved.
* Author: [email protected]
*/
package com.xiaomi.infra.galaxy.talos.client;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import com.google.common.base.Preconditions;
import com.xiaomi.infra.galaxy.rpc.thrift.Credential;
import com.xiaomi.infra.galaxy.talos.thrift.AddSubResourceNameRequest;
import com.xiaomi.infra.galaxy.talos.thrift.ErrorCode;
import com.xiaomi.infra.galaxy.talos.thrift.GalaxyTalosException;
import com.xiaomi.infra.galaxy.talos.thrift.Message;
import com.xiaomi.infra.galaxy.talos.thrift.MessageOffset;
import com.xiaomi.infra.galaxy.talos.thrift.MessageType;
import com.xiaomi.infra.galaxy.talos.thrift.TopicAndPartition;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_CLOUD_AK_PREFIX;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_CLOUD_ORG_PREFIX;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_CLOUD_TEAM_PREFIX;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_IDENTIFIER_DELIMITER;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_NAME_REGEX;
import static com.xiaomi.infra.galaxy.talos.client.Constants.TALOS_CLOUD_TOPIC_NAME_DELIMITER;
public class Utils {
/**
* The format of valid resource name is: ownerId#topicName#UUID
* Note the 'ownerId' may contains the symbol '#',
* so return topicName parsing from the tail of resourceName.
*
* @param topicTalosResourceName
* @return
*/
public static String getTopicNameByResourceName(String topicTalosResourceName) {
String[] itemList = topicTalosResourceName.split(TALOS_IDENTIFIER_DELIMITER);
Preconditions.checkArgument(itemList.length >= 3);
return itemList[itemList.length - 2];
}
public static void checkParameterRange(String parameter, int value,
int minValue, int maxValue) {
if (value < minValue || value > maxValue) {
throw new IllegalArgumentException(parameter + " should be in range [" +
minValue + ", " + maxValue + "], got: " + value);
}
}
public static void checkStartOffsetValidity(long startOffset) {
if (startOffset >= 0 || startOffset == MessageOffset.START_OFFSET.getValue() ||
startOffset == MessageOffset.LATEST_OFFSET.getValue()) {
return;
}
throw new IllegalArgumentException("invalid startOffset: " + startOffset +
". It must be greater than or equal to 0, " +
"or equal to MessageOffset.START_OFFSET/MessageOffset.LATEST_OFFSET");
}
public static String generateClientId() {
return System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8);
}
public static void checkTopicAndPartition(TopicAndPartition topicAndPartition) {
if (topicAndPartition.getTopicName().contains(TALOS_CLOUD_TOPIC_NAME_DELIMITER)) {
throw new IllegalArgumentException(
"The topic name format in TopicAndPartition should not be: orgId/topicName");
}
}
// The format of cloud topicName is: orgId/topicName
public static void checkCloudTopicNameValidity(String topicName) {
if (topicName == null || topicName.length() == 0) {
throw new IllegalArgumentException("Got null topicName");
}
String[] items = topicName.split(TALOS_CLOUD_TOPIC_NAME_DELIMITER);
// either 'xxx/xxx/'(split 2), '/xxx'(split 2) or 'xx//xx'(split 3) are invalid
if (items.length != 2 || topicName.endsWith(TALOS_CLOUD_TOPIC_NAME_DELIMITER)
|| !topicName.startsWith(TALOS_CLOUD_ORG_PREFIX)) {
throw new IllegalArgumentException(
"The format of topicName used by cloud-manager must be: orgId/topicName");
}
// check real topic name validity
checkNameValidity(items[1]);
}
public static void checkNameValidity(String str) {
if (str == null || str.length() <= 0) {
return;
}
if (!Pattern.matches(TALOS_NAME_REGEX, str) || str.length() > 80) {
throw new IllegalArgumentException("invalid str: " + str +
". please name the str only with the regex set: [a-zA-Z0-9_-]" +
". Its length must be [1, 80] and cannot start with '_' or '-'.");
}
}
public static String generateClientId(String prefix) {
checkNameValidity(prefix);
return prefix + generateClientId();
}
public static String generateRequestSequenceId(String clientId,
AtomicLong requestId) {
checkNameValidity(clientId);
return clientId + Constants.TALOS_IDENTIFIER_DELIMITER +
requestId.getAndIncrement();
}
private static ErrorCode getErrorCode(Throwable throwable) {
if (throwable instanceof GalaxyTalosException) {
GalaxyTalosException e = (GalaxyTalosException) throwable;
return e.getErrorCode();
}
return null;
}
public static boolean isTopicNotExist(Throwable throwable) {
return getErrorCode(throwable) == ErrorCode.TOPIC_NOT_EXIST;
}
public static boolean isPartitionNotServing(Throwable throwable) {
return getErrorCode(throwable) == ErrorCode.PARTITION_NOT_SERVING;
}
public static boolean isOffsetOutOfRange(Throwable throwable) {
return getErrorCode(throwable) == ErrorCode.MESSAGE_OFFSET_OUT_OF_RANGE;
}
public static void updateMessage(Message message, MessageType messageType) {
if (!message.isSetCreateTimestamp()) {
message.setCreateTimestamp(System.currentTimeMillis());
}
message.setMessageType(messageType);
}
public static void checkMessageValidity(Message message) {
checkMessageLenValidity(message);
checkMessageSequenceNumberValidity(message);
checkMessageTypeValidity(message);
}
private static void checkMessageLenValidity(Message message) {
if (!message.isSetMessage()) {
throw new IllegalArgumentException("Field \"message\" must be set");
}
byte[] data = message.getMessage();
if (data.length > Constants.TALOS_SINGLE_MESSAGE_BYTES_MAXIMAL ||
data.length < Constants.TALOS_SINGLE_MESSAGE_BYTES_MINIMAL) {
throw new IllegalArgumentException("Data must be less than or equal to " +
Constants.TALOS_SINGLE_MESSAGE_BYTES_MAXIMAL + " bytes, got bytes: " +
data.length);
}
}
private static void checkMessageSequenceNumberValidity(Message message) {
if (!message.isSetSequenceNumber()) {
return;
}
String sequenceNumber = message.getSequenceNumber();
if (sequenceNumber.length() < Constants.TALOS_PARTITION_KEY_LENGTH_MINIMAL ||
sequenceNumber.length() > Constants.TALOS_PARTITION_KEY_LENGTH_MAXIMAL) {
throw new IllegalArgumentException("Invalid sequenceNumber which length " +
"must be at least " + Constants.TALOS_PARTITION_KEY_LENGTH_MINIMAL + " and at most " +
Constants.TALOS_PARTITION_KEY_LENGTH_MAXIMAL + ", got " + sequenceNumber.length());
}
}
private static void checkMessageTypeValidity(Message message) {
if (!message.isSetMessageType()) {
throw new IllegalArgumentException("Filed \"messageType\" must be set");
}
}
public static void checkAddSubResourceNameRequest(Credential credential,
AddSubResourceNameRequest request) {
// check principal
if (credential.getSecretKeyId().startsWith(TALOS_CLOUD_AK_PREFIX)) {
throw new IllegalArgumentException(
"Only Developer principal can add subResourceName");
}
// check topic
if (request.getTopicTalosResourceName().getTopicTalosResourceName()
.startsWith(TALOS_CLOUD_ORG_PREFIX)) {
throw new IllegalArgumentException(
"The topic created by cloud-manager role can not add subResourceName");
}
// check orgId
if (!request.getOrgId().startsWith(TALOS_CLOUD_ORG_PREFIX)) {
throw new IllegalArgumentException("The orgId must starts with 'CL'");
}
// check teamId
if (!request.getAdminTeamId().startsWith(TALOS_CLOUD_TEAM_PREFIX)) {
throw new IllegalArgumentException("The teamId must starts with 'CI'");
}
}
}