Skip to content

Commit 9491994

Browse files
Moved dependency ready check here from dd-dataverse-ingest. (#29)
* Moved dependency ready check here from dd-datavers-ingest. * Update src/main/java/nl/knaw/dans/lib/util/healthcheck/HealthChecksDependenciesReadyCheck.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/nl/knaw/dans/lib/util/healthcheck/HealthChecksDependenciesReadyCheck.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent bda3efd commit 9491994

3 files changed

Lines changed: 167 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) 2021 DANS - Data Archiving and Networked Services (info@dans.knaw.nl)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package nl.knaw.dans.lib.util.healthcheck;
17+
18+
/**
19+
* Interface for checking if all dependencies are ready.
20+
*/
21+
public interface DependenciesReadyCheck {
22+
/**
23+
* Wait until all dependencies are ready. This method should block until all dependencies are ready.
24+
*
25+
* @param checks the names of the checks to wait for; if empty, all checks are waited for
26+
*/
27+
void waitUntilReady(String... checks);
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (C) 2021 DANS - Data Archiving and Networked Services (info@dans.knaw.nl)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package nl.knaw.dans.lib.util.healthcheck;
17+
18+
import io.dropwizard.util.Duration;
19+
import lombok.AllArgsConstructor;
20+
import lombok.Builder;
21+
import lombok.Data;
22+
import lombok.NoArgsConstructor;
23+
24+
import java.util.List;
25+
26+
@Data
27+
@Builder
28+
@NoArgsConstructor
29+
@AllArgsConstructor
30+
public class DependenciesReadyCheckConfig {
31+
private List<String> healthChecks;
32+
private Duration pollInterval;
33+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (C) 2021 DANS - Data Archiving and Networked Services (info@dans.knaw.nl)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package nl.knaw.dans.lib.util.healthcheck;
17+
18+
import com.codahale.metrics.health.HealthCheck;
19+
import io.dropwizard.core.setup.Environment;
20+
import io.dropwizard.lifecycle.Managed;
21+
import lombok.extern.slf4j.Slf4j;
22+
23+
import java.util.ArrayList;
24+
import java.util.Arrays;
25+
import java.util.List;
26+
import java.util.stream.Collectors;
27+
28+
import static java.lang.Thread.sleep;
29+
30+
/**
31+
* Implementation of {@link DependenciesReadyCheck} that waits until all health checks are healthy.
32+
*/
33+
@Slf4j
34+
public class HealthChecksDependenciesReadyCheck implements DependenciesReadyCheck, Managed {
35+
private final List<HealthCheck> healthChecks = new ArrayList<>();
36+
private final Environment environment;
37+
private final DependenciesReadyCheckConfig config;
38+
39+
private long pollInterval;
40+
private boolean running = false;
41+
42+
public HealthChecksDependenciesReadyCheck(Environment environment, DependenciesReadyCheckConfig config) {
43+
this.environment = environment;
44+
this.config = config;
45+
}
46+
47+
@Override
48+
public void start() throws Exception {
49+
for (var name : config.getHealthChecks()) {
50+
var healthCheck = environment.healthChecks().getHealthCheck(name);
51+
if (healthCheck == null) {
52+
throw new IllegalArgumentException("Health check with name " + name + " not found");
53+
}
54+
healthChecks.add(healthCheck);
55+
}
56+
pollInterval = config.getPollInterval().toMilliseconds();
57+
running = true;
58+
}
59+
60+
@Override
61+
public void stop() {
62+
running = false;
63+
}
64+
65+
@Override
66+
public void waitUntilReady(String... checks) {
67+
List<HealthCheck> checksToWaitFor = getChecksToWaitFor(checks);
68+
while (running && !allHealthy(checksToWaitFor)) {
69+
log.warn("Not all health checks are healthy yet, waiting for {} ms", pollInterval);
70+
try {
71+
sleep(pollInterval);
72+
}
73+
catch (InterruptedException e) {
74+
Thread.currentThread().interrupt();
75+
log.warn("Interrupted while waiting for health checks to become healthy, stopping wait");
76+
break;
77+
}
78+
}
79+
}
80+
81+
private List<HealthCheck> getChecksToWaitFor(String... checks) {
82+
if (checks.length == 0) {
83+
return healthChecks;
84+
}
85+
var checkNames = Arrays.asList(checks);
86+
var registeredChecks = environment.healthChecks();
87+
return checkNames.stream()
88+
.map(name -> {
89+
var healthCheck = registeredChecks.getHealthCheck(name);
90+
if (healthCheck == null) {
91+
throw new IllegalArgumentException("Health check with name " + name + " not found");
92+
}
93+
return healthCheck;
94+
})
95+
.collect(Collectors.toList());
96+
}
97+
98+
private boolean allHealthy(List<HealthCheck> checksToWaitFor) {
99+
for (var healthCheck : checksToWaitFor) {
100+
if (!healthCheck.execute().isHealthy()) {
101+
return false;
102+
}
103+
}
104+
return true;
105+
}
106+
}

0 commit comments

Comments
 (0)