All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaomi.infra.galaxy.talos.client.Utils Maven / Gradle / Ivy

There is a newer version: 2.6.1.4
Show newest version
/**
 * 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'");
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy