![JAR search and dependency download from the Maven repository](/logo.png)
com.xiaomi.infra.galaxy.sds.examples.stream.StreamDemo Maven / Gradle / Ivy
package com.xiaomi.infra.galaxy.sds.examples.stream;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xiaomi.infra.galaxy.rpc.thrift.GrantType;
import com.xiaomi.infra.galaxy.rpc.thrift.Grantee;
import com.xiaomi.infra.galaxy.sds.client.ClientFactory;
import com.xiaomi.infra.galaxy.sds.thrift.AdminService;
import com.xiaomi.infra.galaxy.sds.thrift.CommonConstants;
import com.xiaomi.infra.galaxy.sds.thrift.Credential;
import com.xiaomi.infra.galaxy.sds.thrift.Datum;
import com.xiaomi.infra.galaxy.sds.thrift.DatumUtil;
import com.xiaomi.infra.galaxy.sds.thrift.IncrementRequest;
import com.xiaomi.infra.galaxy.sds.thrift.MutationLogEntry;
import com.xiaomi.infra.galaxy.sds.thrift.PutRequest;
import com.xiaomi.infra.galaxy.sds.thrift.PutResult;
import com.xiaomi.infra.galaxy.sds.thrift.RemoveRequest;
import com.xiaomi.infra.galaxy.sds.thrift.RemoveResult;
import com.xiaomi.infra.galaxy.sds.thrift.StreamSpec;
import com.xiaomi.infra.galaxy.sds.thrift.StreamViewType;
import com.xiaomi.infra.galaxy.sds.thrift.TableInfo;
import com.xiaomi.infra.galaxy.sds.thrift.TableSchema;
import com.xiaomi.infra.galaxy.sds.thrift.TableService;
import com.xiaomi.infra.galaxy.sds.thrift.TableSpec;
import com.xiaomi.infra.galaxy.sds.thrift.UserType;
import com.xiaomi.infra.galaxy.talos.admin.TalosAdmin;
import com.xiaomi.infra.galaxy.talos.client.SimpleTopicAbnormalCallback;
import com.xiaomi.infra.galaxy.talos.client.TalosClientConfig;
import com.xiaomi.infra.galaxy.talos.client.TalosClientConfigKeys;
import com.xiaomi.infra.galaxy.talos.consumer.MessageCheckpointer;
import com.xiaomi.infra.galaxy.talos.consumer.MessageProcessor;
import com.xiaomi.infra.galaxy.talos.consumer.MessageProcessorFactory;
import com.xiaomi.infra.galaxy.talos.consumer.TalosConsumer;
import com.xiaomi.infra.galaxy.talos.consumer.TalosConsumerConfig;
import com.xiaomi.infra.galaxy.talos.thrift.CreateTopicRequest;
import com.xiaomi.infra.galaxy.talos.thrift.CreateTopicResponse;
import com.xiaomi.infra.galaxy.talos.thrift.MessageAndOffset;
import com.xiaomi.infra.galaxy.talos.thrift.Permission;
import com.xiaomi.infra.galaxy.talos.thrift.TopicAndPartition;
import com.xiaomi.infra.galaxy.talos.thrift.TopicAttribute;
import com.xiaomi.infra.galaxy.talos.thrift.TopicInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
/**
* Copyright 2015, Xiaomi.
* All rights reserved.
* Author: [email protected]
*/
public class StreamDemo {
private static final Logger LOG = LoggerFactory.getLogger(StreamDemo.class);
static Random rand = new Random(0);
static final int PARTITAL_DELETE_NUMBER = 2;
static final int ADMIN_CONN_TIMEOUT = 3000;
static final int ADMIN_SOCKET_TIMEOUT = 50000;
static final int TABLE_CONN_TIMEOUT = 3000;
static final int TABLE_SOCKET_TIMEOUT = 10000;
private Credential createSdsCredential(String secretKeyId, String secretKey, UserType userType) {
return new Credential()
.setSecretKeyId(secretKeyId)
.setSecretKey(secretKey)
.setType(userType);
}
private com.xiaomi.infra.galaxy.rpc.thrift.Credential createTalosCredential(String secretKeyId,
String secretKey, com.xiaomi.infra.galaxy.rpc.thrift.UserType userType) {
return new com.xiaomi.infra.galaxy.rpc.thrift.Credential()
.setSecretKeyId(secretKeyId)
.setSecretKey(secretKey)
.setType(userType);
}
private AdminService.Iface createAdminClient(String endpoint, Credential credential) {
ClientFactory clientFactory = new ClientFactory().setCredential(credential);
return clientFactory.newAdminClient(endpoint + CommonConstants.ADMIN_SERVICE_PATH,
ADMIN_SOCKET_TIMEOUT, ADMIN_CONN_TIMEOUT);
}
private TableService.Iface createTableClient(String endpoint, Credential credential) {
ClientFactory clientFactory = new ClientFactory().setCredential(credential);
return clientFactory.newTableClient(endpoint + CommonConstants.TABLE_SERVICE_PATH,
TABLE_SOCKET_TIMEOUT, TABLE_CONN_TIMEOUT);
}
private void initSdsClient() {
Credential credential = createSdsCredential(accountKey, accountSecret, UserType.DEV_XIAOMI);
adminClient = createAdminClient(sdsServiceEndpoint, credential);
credential = createSdsCredential(appKey, appSecret, UserType.APP_SECRET);
tableClient = createTableClient(sdsServiceEndpoint, credential);
}
private void initTalosClient() {
Properties pro = new Properties();
pro.setProperty(TalosClientConfigKeys.GALAXY_TALOS_SERVICE_ENDPOINT, talosServiceEndpoint);
TalosClientConfig talosClientConfig = new TalosClientConfig(pro);
com.xiaomi.infra.galaxy.rpc.thrift.Credential credential = createTalosCredential(
accountKey, accountSecret, com.xiaomi.infra.galaxy.rpc.thrift.UserType.DEV_XIAOMI);
talosAdmin = new TalosAdmin(talosClientConfig, credential);
}
public StreamDemo() {
initSdsClient();
initTalosClient();
}
private PutRequest getReplayPutRequest(String tableName, Map record) {
return new PutRequest().setTableName(tableName)
.setRecord(record);
}
private IncrementRequest getReplayIncrementRequest(String tableName, Map record) {
Map keys = new HashMap();
Map amounts = new HashMap();
for (Map.Entry entry : record.entrySet()) {
if (DataProvider.rowKeyDef(enableEntityGroup).keySet()
.contains(entry.getKey())) {
keys.put(entry.getKey(), entry.getValue());
} else {
amounts.put(entry.getKey(), entry.getValue());
}
}
return new IncrementRequest().setTableName(tableName)
.setKeys(keys)
.setAmounts(amounts);
}
private RemoveRequest getReplayRemoveRequest(String tableName, Map record,
boolean rowDeleted) {
if (rowDeleted) {
Preconditions.checkArgument(DataProvider.rowKeyDef(enableEntityGroup).keySet()
.equals(record.keySet()));
return new RemoveRequest().setTableName(tableName)
.setKeys(record);
} else {
List attributes = new ArrayList();
Map keys = new HashMap();
for (Map.Entry entry : record.entrySet()) {
if (DataProvider.rowKeyDef(enableEntityGroup).keySet()
.contains(entry.getKey())) {
keys.put(entry.getKey(), entry.getValue());
} else {
attributes.add(entry.getKey());
}
}
return new RemoveRequest().setTableName(tableName)
.setKeys(keys)
.setAttributes(attributes);
}
}
private void replayMutationLogEntry(List messages, String destTableName)
throws Exception {
for (MutationLogEntry entry : messages) {
LOG.info("Consuming mutation log entry : " + entry);
switch (entry.getType()) {
case PUT:
PutRequest put = getReplayPutRequest(destTableName, entry.getRecord());
PutResult putResult = tableClient.put(put);
Preconditions.checkArgument(putResult.isSuccess());
LOG.info("record " + entry.getRecord() + " is put to " + destTableName);
break;
case INCREMENT:
IncrementRequest increment = getReplayIncrementRequest(destTableName, entry.getRecord());
tableClient.increment(increment);
LOG.info("record " + entry.getRecord() + " is increment to " + destTableName);
break;
case DELETE:
RemoveRequest remove = getReplayRemoveRequest(destTableName, entry.getRecord(), entry.isRowDeleted());
RemoveResult removeResult = tableClient.remove(remove);
Preconditions.checkArgument(removeResult.isSuccess());
LOG.info("record " + entry.getRecord() + " is removed from " + destTableName);
break;
default:
Preconditions.checkArgument(false);
}
}
}
// callback for consumer to process messages, that is, consuming logic
private class MutateLogProcessor implements MessageProcessor {
@Override
public void init(TopicAndPartition topicAndPartition, long messageOffset) {
}
@Override
public void process(List messages, MessageCheckpointer messageCheckpointer) {
try {
if (messages.size() > 0) {
List logEntries = new ArrayList(messages.size());
for (MessageAndOffset entry : messages) {
try {
MutationLogEntry logEntry = DatumUtil.deserialize(entry.getMessage().getMessage(),
MutationLogEntry.class);
logEntries.add(logEntry);
} catch (Exception e) {
LOG.error("Deserialize message " + entry + " got exception ", e);
throw e;
}
}
if (!logEntries.isEmpty()) {
try {
replayMutationLogEntry(logEntries, destTableName);
} catch (Exception e) {
LOG.error("Replay mutation log entries " + logEntries + " got exception ", e);
throw e;
}
}
}
} catch (Exception e) {
LOG.error("Process mutation log entries for topic " + topicName + " get exception ", e);
throw new RuntimeException(e);
}
}
@Override
public void shutdown(MessageCheckpointer messageCheckpointer) {
}
}
// using for thread-safe when processing different partition data
private class MutateLogProcessorFactory implements MessageProcessorFactory {
public MutateLogProcessorFactory() {
}
@Override
public MutateLogProcessor createProcessor() {
return new MutateLogProcessor();
}
}
private TalosConsumer createTalosConsumer()
throws Exception {
if (!streamViewType.equals(StreamViewType.MUTATE_LOG)) {
throw new RuntimeException("Unexpected stream view type : " + streamViewType);
}
Properties pro = new Properties();
pro.setProperty(TalosClientConfigKeys.GALAXY_TALOS_SERVICE_ENDPOINT, talosServiceEndpoint);
TalosConsumerConfig talosConsumerConfig = new TalosConsumerConfig(pro);
com.xiaomi.infra.galaxy.rpc.thrift.Credential credential = createTalosCredential(
appKey, appSecret, com.xiaomi.infra.galaxy.rpc.thrift.UserType.APP_SECRET);
return new TalosConsumer(consumerGroup, talosConsumerConfig, credential,
topicInfo.getTopicTalosResourceName(), new MutateLogProcessorFactory(), clientPrefix,
new SimpleTopicAbnormalCallback());
}
private boolean shouldDo() {
return rand.nextBoolean();
}
public void produceData()
throws Exception {
LOG.info("Begin to produce data for table " + tableName);
for (int i = 0; i < 100; i++) {
Map record = DataProvider.randomRecord(
DataProvider.attributesDef(enableEntityGroup));
Map keys = DataProvider.getRecordKeys(tableSchema, record);
Map dataRecord = Maps.difference(record, keys).entriesOnlyOnLeft();
// put
PutRequest put = new PutRequest();
put.setTableName(tableName)
.setRecord(record);
PutResult putResult = tableClient.put(put);
Preconditions.checkArgument(putResult.isSuccess());
// increment
if (shouldDo()) {
Map amounts = DataProvider.randomIncrementAmounts(tableSchema,
dataRecord.keySet());
IncrementRequest increment = new IncrementRequest();
increment.setTableName(tableName)
.setKeys(keys)
.setAmounts(amounts);
tableClient.increment(increment);
}
// partial delete
if (shouldDo()) {
List attributes = DataProvider.randomSelect(dataRecord.keySet(),
PARTITAL_DELETE_NUMBER);
RemoveRequest remove = new RemoveRequest();
remove.setTableName(tableName)
.setAttributes(attributes)
.setKeys(keys);
RemoveResult removeResult = tableClient.remove(remove);
Preconditions.checkArgument(removeResult.isSuccess());
}
}
LOG.info("Produce data finished for table " + tableName);
}
public TableSchema createSrcTable(String tableName, String topicName, StreamSpec streamSpec)
throws Exception {
Map streamSpecs = new HashMap();
streamSpecs.put(topicName, streamSpec);
TableSpec tableSpec = DataProvider.createTableSpec(appId, enableEntityGroup,
enableEntityGroupHash, streamSpecs);
TableInfo tableInfo = adminClient.createTable(tableName, tableSpec);
LOG.info("Src table " + tableName + " is created");
return tableInfo.getSpec().getSchema();
}
public void createDestTable() throws Exception {
TableSpec tableSpec = DataProvider.createTableSpec(appId, enableEntityGroup,
enableEntityGroupHash);
adminClient.createTable(destTableName, tableSpec);
LOG.info("Dest table " + destTableName + " is created");
}
private TopicInfo createTopic() throws Exception {
CreateTopicRequest createTopicRequest = new CreateTopicRequest();
createTopicRequest.setTopicName(topicName);
Map aclMap = new HashMap();
Grantee grantee = new Grantee();
grantee.setIdentifier(appId)
.setType(GrantType.APP_ROOT);
aclMap.put(grantee, Permission.TOPIC_READ_AND_MESSAGE_FULL_CONTROL);
createTopicRequest.setAclMap(aclMap);
TopicAttribute topicAttribute = new TopicAttribute();
topicAttribute.setPartitionNumber(topicPartitionNumber);
createTopicRequest.setTopicAttribute(topicAttribute);
CreateTopicResponse createTopicResponse = talosAdmin.createTopic(createTopicRequest);
LOG.info("Topic " + topicName + " is created");
return createTopicResponse.getTopicInfo();
}
private StreamSpec createStreamSpec() throws Exception {
StreamSpec streamSpec = new StreamSpec();
streamSpec.setViewType(streamViewType)
.setAttributes(Lists.newArrayList(DataProvider.columnsDef().keySet()))
.setEnableStream(true);
LOG.info("Stream " + streamSpec + " is created");
return streamSpec;
}
public void createTable() throws Exception {
topicInfo = createTopic();
streamSpec = createStreamSpec();
tableSchema = createSrcTable(tableName, topicName, streamSpec);
}
// sds config
private static final String sdsServiceEndpoint = "$sdsServiceEndpoint";
private static final String tableName = "streamDemoTable";
private static final String destTableName = "destStreamDemoTable";
private static final boolean enableEntityGroup = true;
private static final boolean enableEntityGroupHash = true;
private static final StreamViewType streamViewType = StreamViewType.MUTATE_LOG;
private static final String accountKey = "$your_accountKey";
private static final String accountSecret = "$your_accountSecret";
private static final String appId = "$your_appId";
private static final String appKey = "$your_appKey";
private static final String appSecret = "$your_appSecret";
private static AdminService.Iface adminClient;
private static TableService.Iface tableClient;
private static TableSchema tableSchema;
private static StreamSpec streamSpec;
// talos config
private static final String talosServiceEndpoint = "$talosServiceEndpoint";
private static final String topicName = "streamDemoTopic";
private static final int topicPartitionNumber = 8;
private static final String clientPrefix = "departmentName-";
private static final String consumerGroup = "groupName";
private static TalosAdmin talosAdmin;
private static TopicInfo topicInfo;
public static void main(String[] args) throws Exception {
StreamDemo streamDemo = new StreamDemo();
streamDemo.createTable();
streamDemo.createDestTable();
streamDemo.createTalosConsumer();
streamDemo.produceData();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy