Advertisement
Guest User

Untitled

a guest
Feb 13th, 2020
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.67 KB | None | 0 0
  1. // ########################################################################## //
  2. // ############################## MAIN CLASSES ############################## //
  3. // ########################################################################## //
  4.  
  5. public enum Status {
  6.     NOT_STARTED,
  7.     IN_PROGRESS,
  8.     COMPLETED,
  9.     ERROR
  10. }
  11.  
  12. public interface SchemaLoader {
  13.  
  14.     void loadSchema();
  15.  
  16. }
  17.  
  18. public class SchemaLoaderImpl {
  19.  
  20.     @Override
  21.     public void loadSchema() {
  22.         // Implementation goes here
  23.     }
  24.  
  25. }
  26.  
  27. public class SchemaMaintainer {
  28.  
  29.     private static final long CHECK_TIMEOUT_MILLIS = 5000L; // We want to abort the check after 5 seconds so we don't block the app forever
  30.  
  31.     private volatile Status status = Status.NOT_STARTED;
  32.     private final ExecutorService executor = Executors.newSingleThreadExecutor();
  33.     private final SchemaLoader schemaLoader;
  34.  
  35.     public SchemaMaintainer(SchemaLoader schemaLoader) {
  36.         this.schemaLoader = schemaLoader;
  37.     }
  38.  
  39.     public synchronized void maintainSchema() throws TimeoutException {
  40.         switch (status) {
  41.             case COMPLETED:
  42.                 return;
  43.             case ERROR:
  44.                 throw new RuntimeException("Schema maintenance finished with an error");
  45.             case IN_PROGRESS:
  46.                 throw new RuntimeException("Schema maintenance already in progress");
  47.             case NOT_STARTED:
  48.                 status = Status.IN_PROGRESS;
  49.                 executor.submit(this::loadSchema);
  50.                 waitForLoading();
  51.                 break;
  52.         }
  53.     }
  54.  
  55.     // Visible for testing
  56.     Status getStatus() {
  57.         return status;
  58.     }
  59.  
  60.     private Status loadSchema() {
  61.         try {
  62.             // Loading the schema
  63.             schemaLoader.loadSchema();
  64.             // Schema loading was successful
  65.             synchronized(this) {
  66.                 if (status == Status.ERROR) {
  67.                     // TODO store that schema loading was successful, but a timeout exception occurred in the meantime
  68.                 } else {
  69.                     status = Status.COMPLETED;
  70.                 }
  71.             }
  72.         } catch (Exception e) {
  73.             synchronized(this) {
  74.                 status = Status.ERROR;
  75.                 // TODO store the exception somewhere
  76.             }
  77.         }
  78.     }
  79.  
  80.     private void waitForLoading() throws TimeoutException {
  81.         long endTimeMillis = System.currentTimeMillis() + CHECK_TIMEOUT_MILLIS;
  82.         while (status == Status.IN_PROGRESS) {
  83.             long remainingMillis = end - System.currentTimeMillis();
  84.             if (remainingMillis > 0) {
  85.                 Thread.sleep(50);
  86.                 continue;
  87.             }
  88.             // Timeout
  89.             synchronized(this) {
  90.                 if (status != Status.COMPLETED) {
  91.                     // We only want to throw a TimeoutException if the loading really didn't finish
  92.                     status = Status.ERROR;
  93.                     executor.shutdownNow(); // Abort the loading
  94.                     throw new TimeoutException("Schema maintenance did not finish within " + CHECK_TIMEOUT_MILLIS + " ms");
  95.                 }
  96.             }
  97.         }
  98.     }
  99.  
  100. }
  101.  
  102. // ########################################################################## //
  103. // ############################## TEST CLASSES ############################## //
  104. // ########################################################################## //
  105.  
  106. public class MockSchemaLoader extends SchemaLoader {
  107.  
  108.     private final CountDownLatch latch = new CountDownLatch(1);
  109.     private boolean markError = false; // Used for simulating an error
  110.  
  111.     public void markError() {
  112.         this.markError = true;
  113.     }
  114.  
  115.     public void finishLoading() {
  116.         this.latch.countDown();
  117.     }
  118.  
  119.     @Override
  120.     public void loadSchema() {
  121.         this.latch.await();
  122.  
  123.         // Simulating an error
  124.         if (this.markError) {
  125.             throw new RuntimeException("Error while loading");
  126.         }
  127.     }
  128.  
  129. }
  130.  
  131. public class SchemaMaintainerTest {
  132.  
  133.     @Test
  134.     public void testEverythingOK() {
  135.         MockSchemaLoader schemaLoader = new MockSchemaLoader();
  136.         SchemaMaintainer schemaMaintainer = new SchemaMaintainer(schemaLoader);
  137.         schemaLoader.finishLoading();
  138.         schemaMaintainer.maintainSchema();
  139.         assertEquals(Status.COMPLETED, schemaMaintainer.getStatus());
  140.     }
  141.  
  142.     @Test
  143.     public void testAlreadyCompelted() {
  144.         MockSchemaLoader schemaLoader = new MockSchemaLoader();
  145.         SchemaMaintainer schemaMaintainer = new SchemaMaintainer(schemaLoader);
  146.         schemaLoader.finishLoading();
  147.         schemaMaintainer.maintainSchema();
  148.         assertEquals(Status.COMPLETED, schemaMaintainer.getStatus());
  149.         schemaMaintainer.maintainSchema(); // The previous should have already completed the maintenance and the 2nd invocation should not throw an error
  150.         assertEquals(Status.COMPLETED, schemaMaintainer.getStatus());
  151.     }
  152.  
  153.     @Test
  154.     public void testInProgress() {
  155.         MockSchemaLoader schemaLoader = new MockSchemaLoader();
  156.         SchemaMaintainer schemaMaintainer = new SchemaMaintainer(schemaLoader);
  157.         schemaMaintainer.maintainSchema();
  158.         Exception ex = null;
  159.         try {
  160.             schemaMaintainer.maintainSchema(); // Loading still in progress, so an exception is expected
  161.         } catch (Exception e) {
  162.             ex = e;
  163.         }
  164.         schemaLoader.finishLoading();
  165.         assertNotNull(ex);
  166.         // TODO validate the exception
  167.     }
  168.  
  169.     @Test
  170.     public void testLoadingException() {
  171.         MockSchemaLoader schemaLoader = new MockSchemaLoader();
  172.         SchemaMaintainer schemaMaintainer = new SchemaMaintainer(schemaLoader);
  173.         schemaLoader.markError();
  174.         schemaLoader.finishLoading();
  175.         schemaMaintainer.maintainSchema(); // This should mark the status as ERROR
  176.         assertEquals(Status.ERROR, schemaMaintainer.getStatus());
  177.         // TODO if you save the loading exception, validate it here
  178.     }
  179.  
  180.     @Test
  181.     public void testAlreadyError() {
  182.         MockSchemaLoader schemaLoader = new MockSchemaLoader();
  183.         SchemaMaintainer schemaMaintainer = new SchemaMaintainer(schemaLoader);
  184.         schemaLoader.markError();
  185.         schemaLoader.finishLoading();
  186.         schemaMaintainer.maintainSchema(); // This should mark the status as ERROR
  187.         assertEquals(Status.ERROR, schemaMaintainer.getStatus());
  188.         Exception ex = null;
  189.         try {
  190.             schemaMaintainer.maintainSchema(); // Already errored, so we expect an exception
  191.         } catch (Exception e) {
  192.             ex = e;
  193.         }
  194.         assertNotNull(ex);
  195.         // TODO validate the exception
  196.     }
  197.  
  198. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement