/*
 * Copyright 2017 the original author or authors.
 *
 * 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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 org.springframework.cloud.skipper.server.service;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.cloud.skipper.domain.Info;
import org.springframework.cloud.skipper.domain.Release;
import org.springframework.cloud.skipper.server.deployer.ReleaseManager;
import org.springframework.cloud.skipper.server.repository.ReleaseRepository;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * Service which schedules background updates for applications known to
 * {@link ReleaseRepository}.
 *
 * @author Janne Valkealahti
 * @author Glenn Renfro
 *
 */
public class ReleaseStateUpdateService {

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

	private final ReleaseManager releaseManager;

	private final ReleaseRepository releaseRepository;

	private long nextFullPoll;

	/**
	 * Instantiates a new release state update service.
	 *
	 * @param releaseManager the release manager
	 * @param releaseRepository the release repository
	 */
	public ReleaseStateUpdateService(ReleaseManager releaseManager, ReleaseRepository releaseRepository) {
		Assert.notNull(releaseManager, "'releaseManager' must be set");
		Assert.notNull(releaseRepository, "'releaseRepository' must be set");
		this.releaseManager = releaseManager;
		this.releaseRepository = releaseRepository;
		this.nextFullPoll = getNextFullPoll();
		log.info("Setting up ReleaseStateUpdateService");
	}

	@Scheduled(initialDelay = 5000, fixedRate = 5000)
	@Transactional
	public synchronized void update() {
		log.info("Scheduled update state method running...");
		long now = System.currentTimeMillis();
		boolean fullPoll = now > nextFullPoll;
		if (fullPoll) {
			// setup next full poll
			nextFullPoll = getNextFullPoll();
			log.info("Setup next full poll at {}", new Date(nextFullPoll));
		}
		Iterable<Release> releases = releaseRepository.findLatestDeployedOrFailed();
		for (Release release : releases) {
			Info info = release.getInfo();
			if (checkInfo(info)) {
				// poll new apps every time or we do full poll anyway
				boolean isNewApp = (info.getLastDeployed().getTime() > (now - 120000));
				log.info("Considering updating state for {}-v{}", release.getName(), release.getVersion());
				log.info("fullPoll = {}, isNewApp = {}", fullPoll, isNewApp);
				boolean poll = fullPoll || (isNewApp);
				if (poll) {
					try {
						release = releaseManager.status(release);
						log.info("New Release state {} {}", release.getName(), release.getInfo().getStatus(),
								release.getInfo().getStatus() != null
										? release.getInfo().getStatus().getPlatformStatusPrettyPrint()
										: "");
						releaseRepository.save(release);
					}
					catch (Exception e) {
						log.warn("Unable to update release status for release " + release.getName() + "-v"
								+ release.getVersion(), e);
					}
				}
				else {
					log.info("Not updating state for {}-v{}", release.getName(), release.getVersion());
				}
			}
		}
	}

	private boolean checkInfo(Info info) {
		if (info == null) {
			throw new IllegalStateException("Info can not be null.");
		}
		if (info.getLastDeployed() == null) {
			throw new IllegalStateException("Info.LastDeployed can not be null.");
		}
		return true;
	}

	/**
	 * Return next poll time in future in two minute intervals.
	 *
	 * @return estimate of next full poll time
	 */
	private long getNextFullPoll() {
		long next = System.currentTimeMillis() + 120000;
		return next - (next % 120000);
	}
}

@@ -2312,20 +2312,21 @@
 %7B%0A%09%09log.
-info
+debug
 (%22Schedu
@@ -2431,16 +2431,21 @@
 = now %3E 
+this.
 nextFull
@@ -2498,16 +2498,21 @@
 poll%0A%09%09%09
+this.
 nextFull
@@ -2540,28 +2540,29 @@
 l();%0A%09%09%09log.
-info
+debug
 (%22Setup next
@@ -2589,16 +2589,21 @@
 ew Date(
+this.
 nextFull
@@ -2645,16 +2645,21 @@
 eases = 
+this.
 releaseR
@@ -2937,20 +2937,21 @@
 %09%09%09%09log.
-info
+debug
 (%22Consid
@@ -3034,20 +3034,21 @@
 %09%09%09%09log.
-info
+debug
 (%22fullPo
@@ -3179,16 +3179,21 @@
 lease = 
+this.
 releaseM
@@ -3226,20 +3226,21 @@
 %09%09%09%09log.
-info
+debug
 (%22New Re
@@ -3447,24 +3447,29 @@
  %22%22);%0A%09%09%09%09%09%09
+this.
 releaseRepos
@@ -3681,20 +3681,21 @@
 %09%09%09%09log.
-info
+debug
 (%22Not up

Modify log level in ReleaseStateUpdateService