package services;
import akka.actor.ActorSystem;
import akka.actor.Cancellable;
import managers.MediaManager;
import models.services.EmailService;
import org.joda.time.DateTime;
import org.joda.time.Seconds;
import play.api.inject.ApplicationLifecycle;
import play.libs.F;
import scala.concurrent.duration.Duration;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* Created by Iven on 08.12.2015.
*/
@Singleton
public class ScheduleService {
private EmailService emailService;
private MediaManager mediaManager;
private ActorSystem system;
private ApplicationLifecycle lifecycle;
@Inject
public ScheduleService(EmailService emailService, MediaManager mediaManager, ApplicationLifecycle lifecycle) {
system = ActorSystem.create();
this.emailService = emailService;
this.mediaManager = mediaManager;
this.lifecycle = lifecycle;
schedule();
}
private void schedule() {
// set the email schedule to next full hour clock for sending daily and hourly emails
Cancellable emailScheudler = system.scheduler().schedule(
Duration.create(nextExecutionInSeconds(getNextHour(), 0), TimeUnit.SECONDS),
Duration.create(1, TimeUnit.HOURS),
() -> {
emailService.sendDailyHourlyNotificationsEmails();
},
system.dispatcher()
);
// cancel it on application stop
lifecycle.addStopHook(() -> {
emailScheudler.cancel();
return CompletableFuture.completedFuture(null);
});
// Sets the schedule for cleaning the media temp directory
Cancellable cleanUpScheudler = system.scheduler().schedule(
Duration.create(0, TimeUnit.MILLISECONDS),
Duration.create(2, TimeUnit.HOURS),
() -> {
mediaManager.cleanUpTemp();
},
system.dispatcher()
);
// cancel it on application stop
lifecycle.addStopHook(() -> {
cleanUpScheudler.cancel();
return CompletableFuture.completedFuture(null);
});
}
/**
* Returns the next full hour of the current time
*
* @return Next hour of current time
*/
private int getNextHour() {
return (new DateTime()).plusHours(1).getHourOfDay();
}
/**
* Calculates seconds between now and a time for hour and minute.
*
* @param hour Hour
* @param minute Minute
* @return Seconds
*/
private int nextExecutionInSeconds(int hour, int minute) {
return Seconds.secondsBetween(
new DateTime(),
nextExecution(hour, minute)
).getSeconds();
}
/**
* Returns a DateTime for hour and minute.
*
* @param hour Hour
* @param minute Minute
* @return DateTime
*/
private DateTime nextExecution(int hour, int minute) {
DateTime next = new DateTime()
.withHourOfDay(hour)
.withMinuteOfHour(minute)
.withSecondOfMinute(0)
.withMillisOfSecond(0);
return (next.isBeforeNow())
? next.plusHours(24)
: next;
}
}