in src/main/java/com/amazonaws/services/neptune/cluster/AddCloneTask.java [363:441]
private void createInstance(String name,
NeptuneClient neptune,
NeptuneClusterMetadata sourceClusterMetadata,
InstanceType instanceType,
DBParameterGroup dbParameterGroup,
DBCluster targetDbCluster) {
System.err.println("Creating target " + name + " instance...");
CreateDbInstanceRequest.Builder requestBuilder = CreateDbInstanceRequest.builder()
.dbInstanceClass(instanceType.value())
.dbInstanceIdentifier(String.format("neptune-export-%s-%s", name, UUID.randomUUID().toString().substring(0, 5)))
.dbClusterIdentifier(targetDbCluster.dbClusterIdentifier())
.dbParameterGroupName(dbParameterGroup.dbParameterGroupName())
.engine("neptune")
.tags(getTags(sourceClusterMetadata.clusterId()))
;
if (StringUtils.isNotEmpty(engineVersion)) {
requestBuilder = requestBuilder.engineVersion(engineVersion);
}
// Retry configuration
int maxRetries = 3;
long initialBackoffMillis = 1000; // 1 second
DBInstance targetDbInstance = null;
CreateDbInstanceRequest request = requestBuilder.build();
// Retry loop with exponential backoff
for (int attempt = 0; attempt <= maxRetries; attempt++) {
try {
targetDbInstance = neptune.createDBInstance(request).dbInstance();
// If we get here, the request was successful
break;
} catch (NeptuneException e) {
// Check if we've exhausted our retries
if (attempt == maxRetries) {
logger.error("Failed to create {} instance after {} attempts, with error {}", name, maxRetries, e.getMessage());
return;
}
// Calculate backoff time with exponential increase and some jitter
long backoffMillis = initialBackoffMillis * (long) Math.pow(2, attempt);
long jitterMillis = (long) (backoffMillis * 0.2 * Math.random()); // 20% jitter
long totalBackoffMillis = backoffMillis + jitterMillis;
logger.debug("Failed to create {} instance (attempt {} of {}): {}. Retrying...", name, attempt + 1, maxRetries, e.getMessage());
try {
Thread.sleep(totalBackoffMillis);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Instance creation interrupted", ie);
}
}
}
if (targetDbInstance == null) {
logger.warn("Failed to create DB instance {} after exhausting all retries", name);
return;
}
String instanceStatus = targetDbInstance.dbInstanceStatus();
while (instanceStatus.equals("creating")) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
instanceStatus = neptune.describeDBInstances(DescribeDbInstancesRequest.builder()
.dbInstanceIdentifier(targetDbInstance.dbInstanceIdentifier()).build())
.dbInstances()
.get(0)
.dbInstanceStatus();
}
}