All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wadpam.open.task.PingController Maven / Gradle / Ivy

The newest version!
package com.wadpam.open.task;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * A ping controller for that create a GAE task every X ms and send to it self.
 * This is useful to ensure that GAE instances are always running and not powered
 * down.
 * @author os
 */
@Controller
@RequestMapping(value = {"_admin/{domain}/ping", "{domain}/_admin/ping"})
public class PingController {
    /** Will only schedule a next PING if current time is beyond this timestamp */
    public static final String NEXT_TIMESTAMP = "_next_timestamp";
    
    static final Logger LOG = LoggerFactory.getLogger(PingController.class);
    
    final MemcacheService MEMCACHE_SERVICE = MemcacheServiceFactory.getMemcacheService(null);
    
    @RequestMapping(value="v10", method= RequestMethod.GET)
    @ResponseBody
    public String setFrequency(
            HttpServletRequest request,
            @PathVariable String domain,
            @RequestParam(defaultValue="60000") Long interval
            ) {
        final String uri = request.getRequestURI();
        
        // create the task
        final long currentMillis = System.currentTimeMillis();
        final String token = Long.toString(currentMillis);
        scheduleTask(uri, currentMillis, interval, token);
        
        // set the timestamp for this task
        MEMCACHE_SERVICE.put(uri, token);
        
        return token;
    }
    
    @RequestMapping(value="v10", method= RequestMethod.POST)
    @ResponseBody
    public String onPing(
            HttpServletRequest request,
            @PathVariable String domain,
            @RequestParam Long interval,
            @RequestParam String token
            ) {
        final String uri = request.getRequestURI();
        final String cachedToken = (String) MEMCACHE_SERVICE.get(uri);
        
        // re-queue the task ?
        if ((null == cachedToken || cachedToken.equals(token)) && 0 < interval) {
            if (null == cachedToken) {
                MEMCACHE_SERVICE.put(uri, token);
            }
            scheduleTask(uri, System.currentTimeMillis(), interval, token);
        }
        else {
            LOG.info("Discarding PING task {} != {}", cachedToken, token);
        }
        
        return cachedToken;
    }

    protected void scheduleTask(final String uri, final long currentMillis, Long interval, final String token) {
        // Will only schedule a next PING if current time is beyond this timestamp
        final Long minNextTime = (Long) MEMCACHE_SERVICE.get(NEXT_TIMESTAMP);
        LOG.debug("Match: {}, overdue {}ms", token, Long.toString(currentMillis - (null != minNextTime ? minNextTime : 0L)));
        if (null == minNextTime || minNextTime <= currentMillis) {
            MEMCACHE_SERVICE.put(NEXT_TIMESTAMP, currentMillis + interval);
            final TaskOptions options = TaskOptions.Builder
                    .withUrl(uri)
                    .etaMillis(currentMillis + interval)
                    .param("interval", interval.toString())
                    .param("token", token);

            final Queue queue = QueueFactory.getDefaultQueue();
            queue.add(options);
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy