ShutdownHook implements Runnable { @Override public void run() { if (shutdownDelayInSec > 0) { try { logger.info("delay {} seconds prior to shutdown", shutdownDelayInSec); Thread.sleep(shutdownDelayInSec * 1000); } catch (InterruptedException e) { logger.warn("sleep is interrupted", e); } } ActionLog actionLog = logManager.begin("=== shutdown begin ===", null); logContext(actionLog); long endTime = System.currentTimeMillis() + shutdownTimeoutInMs; shutdown(endTime, STAGE_0, STAGE_5); logManager.end("=== shutdown end ==="); shutdown(endTime, STAGE_7, STAGE_9); logger.info("shutdown completed, elapsed={}", actionLog.elapsed()); } ShutdownHook(LogManager logManager); void add(int stage, Shutdown shutdown); @Override void run(); static final int STAGE_0; static final int STAGE_1; static final int STAGE_2; static final int STAGE_3; static final int STAGE_4; static final int STAGE_5; static final int STAGE_7; static final int STAGE_8; static final int STAGE_9; }
@Test void run() throws Exception { var shutdown1 = mock(ShutdownHook.Shutdown.class); doThrow(new Error("failed to shutdown")).when(shutdown1).execute(anyLong()); var shutdown2 = mock(ShutdownHook.Shutdown.class); shutdownHook.add(ShutdownHook.STAGE_0, shutdown1); shutdownHook.add(ShutdownHook.STAGE_7, shutdown2); shutdownHook.run(); verify(shutdown2).execute(anyLong()); }