protected DescribeStreamResult describeStream(String streamName, @Nullable String startShardId)
			throws InterruptedException {
		final DescribeStreamRequest describeStreamRequest = new DescribeStreamRequest();
		describeStreamRequest.setStreamName(streamName);
		describeStreamRequest.setExclusiveStartShardId(startShardId);

		DescribeStreamResult describeStreamResult = null;

		// Call DescribeStream, with full-jitter backoff (if we get LimitExceededException).
		int attemptCount = 0;
		while (describeStreamResult == null) { // retry until we get a result
			try {
				describeStreamResult = kinesisClient.describeStream(describeStreamRequest);
			} catch (LimitExceededException le) {
				long backoffMillis = fullJitterBackoff(
						describeStreamBaseBackoffMillis,
						describeStreamMaxBackoffMillis,
						describeStreamExpConstant,
						attemptCount++);
				LOG.warn(String.format("Got LimitExceededException when describing stream %s. "
						+ "Backing off for %d millis.", streamName, backoffMillis));
				Thread.sleep(backoffMillis);
			} catch (ResourceNotFoundException re) {
				throw new RuntimeException("Error while getting stream details", re);
			}
		}

		String streamStatus = describeStreamResult.getStreamDescription().getStreamStatus();
		if (!(streamStatus.equals(StreamStatus.ACTIVE.toString())
				|| streamStatus.equals(StreamStatus.UPDATING.toString()))) {
			if (LOG.isWarnEnabled()) {
				LOG.warn(String.format("The status of stream %s is %s ; result of the current "
								+ "describeStream operation will not contain any shard information.",
						streamName, streamStatus));
			}
		}

		return describeStreamResult;
	}
protected DescribeStreamResult describeStream ( String streamName , @ Nullable String startShardId ) throws InterruptedException { final DescribeStreamRequest describeStreamRequest = new DescribeStreamRequest ( ) ; describeStreamRequest . setStreamName ( streamName ) ; describeStreamRequest . setExclusiveStartShardId ( startShardId ) ; DescribeStreamResult describeStreamResult = null ; int attemptCount = 0 ; while ( describeStreamResult == null ) { try { describeStreamResult = kinesisClient . describeStream ( describeStreamRequest ) ; } catch ( LimitExceededException le ) { long backoffMillis = fullJitterBackoff ( describeStreamBaseBackoffMillis , describeStreamMaxBackoffMillis , describeStreamExpConstant , attemptCount ++ ) ; LOG . warn ( String . format ( "Got LimitExceededException when describing stream %s. " + "Backing off for %d millis." , streamName , backoffMillis ) ) ; Thread . sleep ( backoffMillis ) ; } catch ( ResourceNotFoundException re ) { throw new RuntimeException ( "Error while getting stream details" , re ) ; } } String streamStatus = describeStreamResult . getStreamDescription ( ) . getStreamStatus ( ) ; if ( ! ( streamStatus . equals ( StreamStatus . ACTIVE . toString ( ) ) || streamStatus . equals ( StreamStatus . UPDATING . toString ( ) ) ) ) { if ( LOG . isWarnEnabled ( ) ) { LOG . warn ( String . format ( "The status of stream %s is %s ; result of the current " + "describeStream operation will not contain any shard information." , streamName , streamStatus ) ) ; } } return describeStreamResult ; }
Get metainfo for a Kinesis stream, which contains information about which shards this
Kinesis stream possess.

<p>This method is using a "full jitter" approach described in AWS's article,
<a href="https://www.awsarchitectureblog.com/2015/03/backoff.html">
"Exponential Backoff and Jitter"</a>.
This is necessary because concurrent calls will be made by all parallel subtask's fetcher.
This jitter backoff approach will help distribute calls across the fetchers over time.

@param streamName the stream to describe
@param startShardId which shard to start with for this describe operation

@return the result of the describe stream operation