package org.atlasapi.system.bootstrap.workers;

import java.util.concurrent.ExecutionException;

import org.atlasapi.content.Content;
import org.atlasapi.content.ContentResolver;
import org.atlasapi.content.ContentWriter;
import org.atlasapi.entity.Id;
import org.atlasapi.entity.util.Resolved;
import org.atlasapi.entity.util.WriteResult;
import org.atlasapi.messaging.ResourceUpdatedMessage;

import com.metabroadcast.common.queue.AbstractMessage;
import com.metabroadcast.common.queue.RecoverableException;
import com.metabroadcast.common.queue.Worker;

import com.codahale.metrics.Meter;
import com.codahale.metrics.Timer;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Preconditions.checkNotNull;

public class ContentBootstrapWorker implements Worker<ResourceUpdatedMessage> {

    private static final Logger LOG = LoggerFactory.getLogger(ContentBootstrapWorker.class);

    private final ContentResolver contentResolver;
    private final ContentWriter writer;
    private final Timer metricsTimer;
    private final Meter contentNotWrittenMeter;
    private final Meter failureMeter;

    private ContentBootstrapWorker(
            ContentResolver contentResolver,
            ContentWriter writer,
            Timer metricsTimer,
            Meter contentNotWrittenMeter,
            Meter failureMeter
    ) {
        this.contentResolver = checkNotNull(contentResolver);
        this.writer = checkNotNull(writer);
        this.metricsTimer = checkNotNull(metricsTimer);
        this.contentNotWrittenMeter = checkNotNull(contentNotWrittenMeter);
        this.failureMeter = checkNotNull(failureMeter);
    }

    public static ContentBootstrapWorker create(
            ContentResolver contentResolver,
            ContentWriter writer,
            Timer metricsTimer,
            Meter contentNotWrittenMeter,
            Meter failureMeter
    ) {
        return new ContentBootstrapWorker(
                contentResolver, writer, metricsTimer, contentNotWrittenMeter, failureMeter
        );
    }

    @Override
    public void process(ResourceUpdatedMessage message) throws RecoverableException {
        Id contentId = message.getUpdatedResource().getId();
        LOG.debug("Processing message on id {}, took: PT{}S, message: {}",
                contentId, getTimeToProcessInSeconds(message), message);

        Timer.Context time = metricsTimer.time();
        Resolved<Content> content = resolveContent(contentId);

        try {
            WriteResult<Content, Content> result =
                    writer.writeContent(content.getResources().first().get());

            if (result.written()) {
                LOG.debug("Bootstrapped content {}", result.toString());
                time.stop();
            } else {
                LOG.debug("Content has not been written: {}", result.toString());
                contentNotWrittenMeter.mark();
            }
        } catch (Exception e) {
            LOG.error("Failed to bootstrap content {}", message.getUpdatedResource(), e);
            failureMeter.mark();
            throw Throwables.propagate(e);
        }
    }

    private Resolved<Content> resolveContent(Id contentId) {
        try {
            return Futures.get(
                    contentResolver.resolveIds(ImmutableList.of(contentId)),
                    ExecutionException.class
            );
        } catch (Exception e) {
            throw Throwables.propagate(e);
        }
    }

    private long getTimeToProcessInSeconds(AbstractMessage message) {
        return (System.currentTimeMillis() - message.getTimestamp().millis()) / 1000L;
    }
}

@@ -997,19 +997,19 @@
  Logger 
-LOG
+log
  = Logge
@@ -2359,35 +2359,35 @@
 etId();%0A        
-LOG
+log
 .debug(%22Processi
@@ -2511,141 +2511,686 @@
 e);%0A
-%0A        Timer.Context time = metricsTimer.time();%0A        Resolved%3CContent%3E content = resolveContent(contentId);%0A%0A        try %7B%0A    
+        try %7B%0A            process(contentId);%0A        %7D catch (Exception e) %7B%0A            log.error(%22Failed to bootstrap content %7B%7D%22, message.getUpdatedResource(), e);%0A            failureMeter.mark();%0A            throw Throwables.propagate(e);%0A        %7D%0A    %7D%0A%0A    private void process(Id contentId) throws org.atlasapi.entity.util.WriteException %7B%0A        Timer.Context time = metricsTimer.time();%0A        Resolved%3CContent%3E content = resolveContent(contentId);%0A%0A        if (content.getResources().isEmpty()) %7B%0A            log.error(%22Failed to resolve content %7B%7D%22, contentId);%0A            throw new IllegalArgumentException(%22Failed to resolve content %22 + contentId);%0A        %7D%0A%0A
     
@@ -3232,20 +3232,16 @@
 esult =%0A
-    
         
@@ -3312,28 +3312,24 @@
 );%0A%0A        
-    
 if (result.w
@@ -3344,39 +3344,35 @@
 ) %7B%0A            
-    LOG
+log
 .debug(%22Bootstra
@@ -3421,20 +3421,16 @@
         
-    
 time.sto
@@ -3430,28 +3430,24 @@
 ime.stop();%0A
-    
         %7D el
@@ -3463,23 +3463,19 @@
         
-    LOG
+log
 .debug(%22
@@ -3537,28 +3537,24 @@
             
-    
 contentNotWr
@@ -3576,220 +3576,8 @@
 ();%0A
-            %7D%0A        %7D catch (Exception e) %7B%0A            LOG.error(%22Failed to bootstrap content %7B%7D%22, message.getUpdatedResource(), e);%0A            failureMeter.mark();%0A            throw Throwables.propagate(e);%0A
     

Add logging for failing to resolve content during bootstrap