Retry.java

package org.flasby.util.time;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * retries something until
 */
public abstract class Retry<T extends Retry.Retryable> implements Closeable {
    public static interface Retryable extends Closeable {
        public Retryable initialize() throws RuntimeException;
    }

    private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    private final T retryable;

    public Retry(int period, TimeUnit unit) {
        this.retryable = createRetryable();
    }

    final T getRetryable() {
        try {
            CompletableFuture<Retryable> xxx = CompletableFuture.supplyAsync(() -> retryable.initialize() ).handle((s, t) -> {
                System.err.println("goat:  "+s);
                return s != null  ? s : getRetryable();
            });
            // System.err.println("Tonk "+xxx.get() );
            //return xxx.get();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return retryable;
    }

    public final void close() throws IOException {
        retryable.close();
    }

    public abstract T createRetryable();

    static class X implements Retryable {
        int x = -2;
        @Override
        public X initialize() throws RuntimeException {
            System.err.println("X: "+x);
            if ( x++ != 0 ) throw new RuntimeException("x="+x);
            return this;
        }

        @Override
        public void close() throws IOException {
            System.err.println("Closing");
        }

        public void grunt() {
            System.err.println("Grunt: "+x);
        }
    }

    public static void main(String[] args) {
        try (Retry<X> r = new Retry<X>(1, TimeUnit.SECONDS) {
            @Override
            public X createRetryable() {
                return new X();
            }
        }) {
            X x = r.getRetryable();
            x.grunt();
        } catch ( IOException ex ) {
            ex.printStackTrace();
        }
    }
}