Currenlty I'm developing an application to automate database backup and restore operations. We are dealing with different types of databases, but one of them is MongoDb. Our MongoDb are hosted by MongoDB Atlas, so we use their MongoDB Atlas Administration API do manage all components.
Once I requested for snapshot of cluster with Take One On-Demand Snapshot method, I need to poll Return One Cluster Cloud Backup endpoint to check what is current process status. I do that as long as one of final statuses are reached (COMPLETED, FAILED).
I'm unsure about the best approach for polling the API until I get a final status. My ideas so far:
- Use Thread.sleep() in a loop
- Use a retry utility (like Spring Retry)
- Use Resilience4j library
However, I'm not convinced either approach is optimal, especially regarding scalability and resource usage.
Question: What are the best practices in a Spring Boot application for polling an external REST API until a certain status is reached?
Thanks in advance for all replies and discussions.
Below my simplified code.
I tried apprach with Thread.sleep().
@Service @Slf4j public class MongodbAtlasService implements MongodbService { private final MongodbClient mongodbClient; private final long pollingIntervalMs; private final long snapshotTimeoutMs; private final long accessTokenExpirationTimeMs; @Override @Retryable(retryFor = {...}) public SnapshotStatus waitForSnapshotStatus(String projectId, String cluster, String snapshotId) throws ... { String accessToken = getAccessToken(); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start <= snapshotTimeoutMs) { SnapshotStatus status = mongodbClient.getSnapshotStatus(projectId, cluster, snapshotId, accessToken); if (status == SnapshotStatus.COMPLETED || status == SnapshotStatus.FAILED) { return status; } Thread.sleep(pollingIntervalMs); } } @Slf4j @Component public class MongodbClient { private final RestClient administrationMongodbRestClient; public SnapshotStatus getSnapshotStatus(String projectId, String clusterName, String snapshotId, String accessToken) throws UnknownSnapshotStatusException { ResponseEntity<GetSnapshotInfoResponse> snapshotInfoResponse = administrationMongodbRestClient.get() .uri("/groups/{projectId}/clusters/{clusterName}/backup/snapshots/shardedCluster/{snapshotId}", projectId, clusterName, snapshotId) .header("Authorization", "Bearer " + accessToken) .retrieve() .onStatus( httpStatusCode -> (httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()), (request, response) -> { throw new UnknownSnapshotStatusException(snapshotId); }) .toEntity(GetSnapshotInfoResponse.class); return Optional.ofNullable(snapshotInfoResponse.getBody()) .map(GetSnapshotInfoResponse::getStatus) .orElseThrow(() -> new UnknownSnapshotStatusException(snapshotId)); } }