The Stream API in the Tablestore SDK for Java consumes incremental changes to a table, including inserts, updates, and deletes.
Prerequisites
-
Install the Tablestore SDK for Java and initialize the client.
-
Stream enabled on the table by setting
StreamSpecificationat table creation. For details, see Create a data table.
Description
Stream organizes incremental changes from a table into shards. To consume a stream, call four APIs in sequence: list streams, describe a stream, get a shard iterator, and fetch records.
-
Call
listStream(ListStreamRequest)to list thestreamIdvalues of all Stream-enabled tables in the instance. -
Call
describeStream(DescribeStreamRequest)to retrieve stream metadata (creation time, expiration time, current status) and the list ofShardobjects. -
Call
getShardIterator(GetShardIteratorRequest)to get the read iterator (shardIterator) for a specificShard. The iterator marks where to start fetching incremental records. -
Call
getStreamRecord(GetStreamRecordRequest)with theshardIteratorto fetch a batch of incremental records (a list ofStreamRecordobjects). Use the returnednextShardIteratorto fetch subsequent records.
public ListStreamResponse listStream(ListStreamRequest request) throws TableStoreException, ClientException
public DescribeStreamResponse describeStream(DescribeStreamRequest request) throws TableStoreException, ClientException
public GetShardIteratorResponse getShardIterator(GetShardIteratorRequest request) throws TableStoreException, ClientException
public GetStreamRecordResponse getStreamRecord(GetStreamRecordRequest request) throws TableStoreException, ClientException
The following example consumes the stream_test_demo stream end-to-end and prints the type and primary key of each record.
String demoTable = "stream_test_demo";
// 1. List all tables in the instance with Stream enabled and find the streamId of the target table.
ListStreamRequest listRequest = new ListStreamRequest(demoTable);
ListStreamResponse listResponse = client.listStream(listRequest);
String targetStreamId = null;
for (Stream stream : listResponse.getStreams()) {
if (demoTable.equals(stream.getTableName())) {
targetStreamId = stream.getStreamId();
break;
}
}
System.out.println("Stream ID: " + targetStreamId);
// 2. Query all shards of the Stream.
DescribeStreamRequest describeRequest = new DescribeStreamRequest(targetStreamId);
DescribeStreamResponse describeResponse = client.describeStream(describeRequest);
List<StreamShard> shards = describeResponse.getShards();
System.out.println("Shard count: " + shards.size());
if (!shards.isEmpty()) {
String shardId = shards.get(0).getShardId();
// 3. Get the initial read iterator of the shard.
GetShardIteratorRequest iterRequest =
new GetShardIteratorRequest(targetStreamId, shardId);
GetShardIteratorResponse iterResponse = client.getShardIterator(iterRequest);
String shardIterator = iterResponse.getShardIterator();
// 4. Use the iterator to pull incremental records from the shard.
GetStreamRecordRequest recordRequest = new GetStreamRecordRequest(shardIterator);
recordRequest.setLimit(100);
GetStreamRecordResponse recordResponse = client.getStreamRecord(recordRequest);
List<StreamRecord> records = recordResponse.getRecords();
System.out.println("Records fetched: " + records.size());
for (StreamRecord record : records) {
System.out.println("RecordType: " + record.getRecordType()
+ ", PK: " + record.getPrimaryKey());
}
// nextShardIterator is used to continue pulling subsequent incremental records.
System.out.println("Next iterator: "
+ (recordResponse.getNextShardIterator() != null ? "yes" : "no"));
}
Parameters
List streams request
ListStreamRequest contains the following parameter.
|
Name |
Type |
Description |
|
tableName (optional) |
String |
The name of the table. If omitted, the request returns stream information for every Stream-enabled table in the instance; otherwise, it returns information only for the specified table. |
Describe stream request
DescribeStreamRequest contains the following parameters.
|
Name |
Type |
Description |
|
streamId (required) |
String |
The unique identifier of the stream. Returned by |
|
inclusiveStartShardId (optional) |
String |
The starting |
|
shardLimit (optional) |
int |
The maximum number of shards to return in the response. |
Get shard iterator request
GetShardIteratorRequest contains the following parameters.
|
Name |
Type |
Description |
|
streamId (required) |
String |
The unique identifier of the stream. Returned by |
|
shardId (required) |
String |
The unique identifier of the shard. Returned in the |
|
timestamp (optional) |
long |
The starting timestamp of the iterator, in microseconds. If omitted, reading starts from the beginning of the shard. |
Read incremental data request
GetStreamRecordRequest contains the following parameters.
|
Name |
Type |
Description |
|
shardIterator (required) |
String |
The read iterator. Returned by |
|
limit (optional) |
int |
The maximum number of |
|
tableName (optional) |
String |
The name of the table that contains the target shard. |
Response
Stream list
ListStreamResponse contains the following operation-specific field.
|
Name |
Type |
Description |
|
streams |
List<Stream> |
The Stream information list. Each element includes information such as the table name, Stream ID, and expiration time. Call |
Stream information
DescribeStreamResponse contains the following operation-specific fields.
|
Name |
Type |
Description |
|
streamId |
String |
The Stream ID. |
|
tableName |
String |
The name of the data table. |
|
creationTime |
long |
The time when the Stream was created. |
|
expirationTime |
int |
The expiration time of the Stream. |
|
status |
StreamStatus |
The Stream status. |
|
shards |
List<StreamShard> |
The shards returned on the current page. |
|
nextShardId |
String |
The start shard ID of the next page. A |
|
timeseriesDataTable |
boolean |
Indicates whether the table is a time series data table. Call |
Shard iterator
GetShardIteratorResponse contains the following operation-specific field.
|
Name |
Type |
Description |
|
shardIterator |
String |
The iterator for the specified shard. Use this value in the first |
Incremental data
GetStreamRecordResponse contains the following operation-specific fields.
|
Name |
Type |
Description |
|
records |
List<StreamRecord> |
The incremental records returned in the response. |
|
nextShardIterator |
String |
The iterator for the next read. A |
|
mayMoreRecord |
Boolean |
Indicates whether the current shard may contain more records. |
Examples
Paginate through the shard list
For streams with many shards, paginate with inclusiveStartShardId and shardLimit. A null nextShardId indicates that all shards have been returned.
String currentStreamId = "<your-stream-id>";
String startShardId = null;
int totalShards = 0;
while (true) {
DescribeStreamRequest request = new DescribeStreamRequest(currentStreamId);
if (startShardId != null) {
request.setInclusiveStartShardId(startShardId);
}
request.setShardLimit(50);
DescribeStreamResponse response = client.describeStream(request);
totalShards += response.getShards().size();
// A null nextShardId indicates that all shards have been traversed.
if (response.getNextShardId() == null) {
break;
}
startShardId = response.getNextShardId();
}
System.out.println("Total shards: " + totalShards);
Continuously poll incremental data
Repeatedly call getStreamRecord with nextShardIterator to fetch incremental records from a single shard. A null nextShardIterator indicates that the current shard has been fully consumed.
String currentStreamId = "<your-stream-id>";
String shardId = "<your-shard-id>";
GetShardIteratorRequest iterRequest =
new GetShardIteratorRequest(currentStreamId, shardId);
String shardIterator = client.getShardIterator(iterRequest).getShardIterator();
int totalRecords = 0;
while (shardIterator != null) {
GetStreamRecordRequest recordRequest = new GetStreamRecordRequest(shardIterator);
recordRequest.setLimit(100);
GetStreamRecordResponse response = client.getStreamRecord(recordRequest);
totalRecords += response.getRecords().size();
shardIterator = response.getNextShardIterator();
}
System.out.println("Polling total records: " + totalRecords);