com.amediamanager.scheduled.ElasticTranscoderTasks.java Source code

Java tutorial

Introduction

Here is the source code for com.amediamanager.scheduled.ElasticTranscoderTasks.java

Source

/*
 * Copyright 2014 Amazon Technologies, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and
 * limitations under the License.
 */
package com.amediamanager.scheduled;

import java.io.IOException;

import org.joda.time.Instant;
import org.joda.time.Minutes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.model.DeleteMessageRequest;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.ReceiveMessageResult;
import com.amediamanager.config.ConfigurationSettings;
import com.amediamanager.config.ConfigurationSettings.ConfigProps;
import com.amediamanager.domain.Video;
import com.amediamanager.service.VideoService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * Holds scheduled tasks related to our Elastic Transcoder
 *
 */
public class ElasticTranscoderTasks {
    protected static final Logger LOG = LoggerFactory.getLogger(ElasticTranscoderTasks.class);

    @Autowired
    protected ConfigurationSettings config;

    @Autowired
    protected VideoService videoService;

    @Autowired
    protected AmazonSQS sqsClient;

    protected final ObjectMapper mapper = new ObjectMapper();

    protected void checkStatus() {
        String sqsQueue = config.getProperty(ConfigProps.TRANSCODE_QUEUE);
        LOG.info("Polling transcode queue {} for changes.", sqsQueue);
        ReceiveMessageRequest request = new ReceiveMessageRequest(sqsQueue).withMaxNumberOfMessages(3)
                .withWaitTimeSeconds(20);

        ReceiveMessageResult result = sqsClient.receiveMessage(request);

        for (Message msg : result.getMessages()) {
            handleMessage(msg);
        }
        LOG.info("Finished polling transcode queue {} and handled {} message(s).", sqsQueue,
                result.getMessages().size());
    }

    protected void deleteMessage(final Message message) {
        DeleteMessageRequest request = new DeleteMessageRequest()
                .withQueueUrl(config.getProperty(ConfigProps.TRANSCODE_QUEUE))
                .withReceiptHandle(message.getReceiptHandle());

        sqsClient.deleteMessage(request);
    }

    protected void handleMessage(final Message message) {
        try {
            LOG.info("Handling message received from checkStatus");
            ObjectNode snsMessage = (ObjectNode) mapper.readTree(message.getBody());
            ObjectNode notification = (ObjectNode) mapper.readTree(snsMessage.get("Message").asText());
            String state = notification.get("state").asText();
            String jobId = notification.get("jobId").asText();
            String pipelineId = notification.get("pipelineId").asText();
            Video video = videoService.findByTranscodeJobId(jobId);
            if (video == null) {
                LOG.warn("Unable to process result for job {} because it does not exist.", jobId);
                Instant msgTime = Instant.parse(snsMessage.get("Timestamp").asText());
                if (Minutes.minutesBetween(msgTime, new Instant()).getMinutes() > 20) {
                    LOG.error("Job {} has not been found for over 20 minutes, deleting message from queue", jobId);
                    deleteMessage(message);
                }
                // Leave it on the queue for now.
                return;
            }
            if ("ERROR".equals(state)) {
                LOG.warn("Job {} for pipeline {} failed to complete. Body: \n{}", jobId, pipelineId,
                        notification.get("messageDetails").asText());
                video.setThumbnailKey(videoService.getDefaultVideoPosterKey());
                videoService.save(video);
            } else {
                // Construct our url prefix: https://bucketname.s3.amazonaws.com/output/key/
                String prefix = notification.get("outputKeyPrefix").asText();
                if (!prefix.endsWith("/")) {
                    prefix += "/";
                }

                ObjectNode output = ((ObjectNode) ((ArrayNode) notification.get("outputs")).get(0));
                String previewFilename = prefix + output.get("key").asText();
                String thumbnailFilename = prefix
                        + output.get("thumbnailPattern").asText().replaceAll("\\{count\\}", "00002") + ".png";
                video.setPreviewKey(previewFilename);
                video.setThumbnailKey(thumbnailFilename);
                videoService.save(video);
            }
            deleteMessage(message);
        } catch (JsonProcessingException e) {
            LOG.error("JSON exception handling notification: {}", message.getBody(), e);
        } catch (IOException e) {
            LOG.error("IOException handling notification: {}", message.getBody(), e);
        }
    }

}