package com.cosmicpush.app.system;
import com.cosmicpush.app.domain.accounts.*;
import com.cosmicpush.app.domain.clients.ApiClient;
import com.cosmicpush.app.domain.requests.*;
import com.couchace.core.api.CouchDatabase;
import com.couchace.core.api.response.EntityDocument;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PostConstruct;
import org.apache.commons.logging.*;
import org.crazyyak.dev.couchace.support.CouchUtils;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import static java.lang.String.format;
@Service
public class CpJobs {
public static final Log log = LogFactory.getLog(CpJobs.class);
public static final String PDT = "America/Los_Angeles";
@Autowired
private AccountStore accountStore;
@Autowired
private ApiRequestStore apiRequestStore;
@Autowired
private CpCouchServer couchServer;
private static final AtomicBoolean runningCompact = new AtomicBoolean(false);
private static final AtomicBoolean runningPruner = new AtomicBoolean(false);
private static final List<String> designNames = Arrays.asList(
"account",
"api-request"
);
public CpJobs() {
}
@PostConstruct
public void runAtStartup() {
cleanAndCompactDatabase();
}
// Every night at midnight
@Scheduled(cron="0 0 0 * * *", zone=PDT)
public void cleanAndCompactDatabase() {
if (runningCompact.compareAndSet(false, true) == false) {
return;
}
try {
CouchDatabase couchDatabase = couchServer.database();
CouchUtils.compactDatabase(couchDatabase);
CouchUtils.compactDesigns(couchDatabase, designNames);
CouchUtils.cleanupViews(couchDatabase);
} catch (Throwable e) {
e.printStackTrace();
} finally {
runningCompact.set(false);
}
}
@Scheduled(initialDelay = 1000*60, fixedDelay = 1000*60*60, zone=PDT)
public void pruneEvents() {
if (runningPruner.compareAndSet(false, true) == false) {
return;
}
try {
LocalDateTime now = new LocalDateTime();
List<Account> accounts = accountStore.getAll();
for (Account account : accounts) {
pruneEvents(now, account);
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
runningPruner.set(false);
}
}
private void pruneEvents(LocalDateTime now, Account account) {
if (account.getRetentionDays() <= 0) {
return;
}
List<ApiClient> apiClients = account.getApiClients();
for (ApiClient apiClient : apiClients) {
int count = 0;
QueryResult<ApiRequest> queryResult = apiRequestStore.getByClient(apiClient, 100);
do {
List<EntityDocument<ApiRequest>> list = queryResult.getDocumentList();
for (EntityDocument<ApiRequest> document : list) {
pruneEvents(now, account, document);
}
count += queryResult.getSize();
log.info(format("Deleted %s records\n", count));
} while (queryResult.nextPage());
}
}
private void pruneEvents(LocalDateTime now, Account account, EntityDocument<ApiRequest> document) {
int days = account.getRetentionDays();
ApiRequest apiRequest = document.getEntity();
LocalDateTime later = apiRequest.getCreatedAt().plusWeeks(days);
if (now.isAfter(later)) {
apiRequestStore.deleteByDocumentId(
document.getDocumentId(),
document.getDocumentRevision()
);
}
}
}