스프링 부트 메일 헬스체크 캐시하기
토스의 Spring Boot Actuator의 헬스체크 살펴보기라는 글을 보고 스프링 부트 액추에이터에서 기본으로 제공하는 MailHealthIndiator의 헬스 체크 결과를 별도로 요청하는 경우 management.endpoint.health.cache-time-to-live
속성으로 캐시되지 않음을 확인했다. 해당 속성은 전체 헬스 체크 결과를 반환하는 헬스 엔드포인트(/actuator/health)에 해당하는 캐시 옵션으로 메일에 대한 헬스 엔드포인트(/actuator/health/mail)에 대해서는 적용되지 않는다.
스프링 부트 액추에이터의 MailHealthIndicator 는 JavaMailSenderImpl의 testConnection 함수를 호출하여 헬스 체크 결과를 반환하도록 작성되어있다. MailHealthIndicator라는 이름으로 HealthIIndicator를 구현하면 기본적으로 제공하는 MailHealthIndicator 대신에 등록되므로 SMTP 서버로의 연결 수행 결과를 캐시하여 응답하도록 작성해볼 수 있다.
CachableMailHealthIndicator
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.mail.MailHealthIndicator;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.time.Instant;
@Component("mailHealthIndicator")
public class CachableMailHealthIndicator extends MailHealthIndicator implements InitializingBean {
private Cache<String, Health> cache;
public CachableMailHealthIndicator(JavaMailSenderImpl javaMailSender) {
super(javaMailSender);
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
Health cached = cache != null ? cache.getIfPresent("mail") : null;
if (cached != null) {
builder.status(cached.getStatus()).withDetails(cached.getDetails());
return;
}
try {
super.doHealthCheck(builder);
} catch (Exception e) {
builder.down(e);
}
if (cache != null) {
Health health = builder.withDetail("datetime", Instant.now()).build();
cache.put("mail", health);
}
}
@Override
public void afterPropertiesSet() throws Exception {
cache = CacheBuilder.newBuilder()
.maximumSize(1)
.expireAfterWrite(Duration.ofSeconds(30))
.build();
}
}
CacheableMailHealthIndicator는 호스트 정보 뿐만 아니라 캐시된 시간을 포함하여 언제 측정된 결과인지도 확인할 수 있습니다.