package io.cattle.platform.deferred.util;

import java.util.ArrayList;
import java.util.List;

import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.cattle.platform.eventing.EventService;
import io.cattle.platform.eventing.model.Event;

public class DeferredUtils {

    private static final Logger log = LoggerFactory.getLogger(DeferredUtils.class);

    private static final ManagedThreadLocal<List<Runnable>> TL = new ManagedThreadLocal<List<Runnable>>() {
        @Override
        protected List<Runnable> initialValue() {
            return new ArrayList<Runnable>();
        }
    };

    public static void deferPublish(final EventService service, final Event event) {
        defer(new Runnable() {
            @Override
            public void run() {
                service.publish(event);
            }
        });
    }

    public static void defer(Runnable runnable) {
        TL.get().add(runnable);
    }

    public static void resetDeferred() {
        TL.get().clear();
    }

    public static void runDeferred() {
        for ( Runnable runnable : TL.get() ) {
            try {
                runnable.run();
            } catch ( Throwable t ) {
                log.error("Failed to run deferred action", t);
            }
        }
    }
}

@@ -86,16 +86,54 @@
 il.List;
+%0Aimport java.util.concurrent.Callable;
 %0A%0Aimport
@@ -349,16 +349,73 @@
 l.Event;
+%0Aimport io.cattle.platform.util.exception.ExceptionUtils;
 %0A%0Apublic
@@ -1052,24 +1052,24 @@
 runnable) %7B%0A
-
         TL.g
@@ -1087,32 +1087,534 @@
 nnable);%0A    %7D%0A%0A
+    public static %3CT%3E T nest(Callable%3CT%3E callable) %7B%0A        List%3CRunnable%3E old = TL.get();%0A        TL.set(new ArrayList%3CRunnable%3E());%0A        try %7B%0A            T result = callable.call();%0A            runDeferred();%0A            return result;%0A        %7D catch (Exception e) %7B%0A            ExceptionUtils.rethrowExpectedRuntime(e);%0A        %7D finally %7B%0A            TL.set(old);%0A        %7D%0A%0A        /* This really isn't possible to get to due to rethrowExpectedRuntime() above */%0A        return null;%0A    %7D%0A%0A
     public stati

allow nesting deferred contexts