Commit ffb507ef authored by Evgeni Sladkovskii's avatar Evgeni Sladkovskii

logging and first refactoring

parent 9ea292ad
package nl.trifork.axondbbackupclient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
......@@ -10,10 +11,12 @@ import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableScheduling
@AutoConfigurationPackage
public class AxonDbBackupClientApplication {
@Slf4j
public class AxonDbBackupClient {
public static void main(String[] args) {
SpringApplication.run(AxonDbBackupClientApplication.class, args);
SpringApplication.run(AxonDbBackupClient.class, args);
log.info("Backup client started");
}
@Bean
......
......@@ -2,6 +2,7 @@ package nl.trifork.axondbbackupclient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import nl.trifork.axondbbackupclient.backup.BackupJob;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
......@@ -31,17 +32,4 @@ public class BackupConfig {
jobs.forEach(j -> ensureDir(backupPath + j.getName()));
}
@Data
public static class BackupJob {
private String name;
private String axondbToken;
private String axondbHost;
private String eventsPath;
private String snapshotsPath;
private String controlDbPath;
}
}
package nl.trifork.axondbbackupclient.backup;
import lombok.Data;
@Data
public class BackupJob {
private String name;
private String axondbToken;
private String axondbHost;
private String eventsPath;
private String snapshotsPath;
private String controlDbPath;
}
package nl.trifork.axondbbackupclient.backup;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class BackupService {
private final ControlDBBackupService controlDb;
private final SegmentsBackupService segments;
public void run(BackupJob job) {
controlDb.backup(job);
}
}
package nl.trifork.axondbbackupclient.backup_services;
package nl.trifork.axondbbackupclient.backup;
import com.google.common.base.Stopwatch;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import nl.trifork.axondbbackupclient.BackupConfig;
import nl.trifork.axondbbackupclient.axondb_client.AxonDbRestClient;
import nl.trifork.axondbbackupclient.client.AxonDbRestClient;
import org.springframework.stereotype.Service;
import java.io.File;
import static com.google.common.base.Stopwatch.createStarted;
import static nl.trifork.axondbbackupclient.util.FileIoService.copy;
@Service
@Slf4j
......@@ -18,15 +19,14 @@ public class ControlDBBackupService {
private final BackupConfig config;
private final AxonDbRestClient axonDbClient;
private final FileIoService fileService;
public void backup() {
public void backup(BackupJob job) {
Stopwatch stopwatch = createStarted();
File dbDump = new File(axonDbClient.createControlDbDump());
File dbDump = new File(axonDbClient.createControlDbDump(job.getAxondbHost()));
if (dbDump.exists()) {
try {
fileService.copy(dbDump, config.getJobs().get(0).getControlDbPath());
copy(dbDump, config.getJobs().get(0).getControlDbPath());
log.info("Created and copied db dump in {}", stopwatch);
} finally {
dbDump.delete();
......
package nl.trifork.axondbbackupclient.backup_services;
package nl.trifork.axondbbackupclient.backup;
import com.google.common.base.Stopwatch;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import nl.trifork.axondbbackupclient.BackupConfig;
import nl.trifork.axondbbackupclient.axondb_client.AxonDbRestClient;
import org.springframework.scheduling.annotation.Scheduled;
import nl.trifork.axondbbackupclient.client.AxonDbRestClient;
import org.springframework.stereotype.Service;
import java.io.File;
import static com.google.common.base.Stopwatch.createStarted;
import static java.util.Arrays.stream;
import static nl.trifork.axondbbackupclient.util.FileIoService.copy;
@Service
@RequiredArgsConstructor
......@@ -21,12 +21,11 @@ public class SegmentsBackupService {
private final BackupConfig config;
private final AxonDbRestClient axonDbClient;
private final ControlDBBackupService dbBackupService;
private final FileIoService fileService;
@Scheduled(fixedDelayString = "${backup.fixedDelayMs}", initialDelayString = "${backup.initialDelayMs}")
public void backup() {
// @Scheduled(fixedDelayString = "${backup.fixedDelayMs}", initialDelayString = "${backup.initialDelayMs}")
public void backup(BackupJob job) {
if (hasNewSegments()) {
dbBackupService.backup();
dbBackupService.backup(job);
backupEvents();
backupSnapshots();
} else {
......@@ -57,7 +56,7 @@ public class SegmentsBackupService {
stream(segments)
.map(File::new)
.filter(File::exists)
.forEach(f -> fileService.copy(f, config.getJobs().get(0).getEventsPath()));
.forEach(f -> copy(f, config.getJobs().get(0).getEventsPath()));
log.info("Copied event segments in {}", stopwatch);
}
......@@ -70,7 +69,7 @@ public class SegmentsBackupService {
stream(segments)
.map(File::new)
.filter(File::exists)
.forEach(f -> fileService.copy(f, config.getJobs().get(0).getEventsPath()));
.forEach(f -> copy(f, config.getJobs().get(0).getEventsPath()));
log.info("Copied snapshot segments in {}", stopwatch);
}
......
package nl.trifork.axondbbackupclient.axondb_client;
package nl.trifork.axondbbackupclient.client;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -38,8 +38,8 @@ public class AxonDbRestClient {
}
}
public String createControlDbDump() {
ResponseEntity<String> dbDumpPath = restTemplate.exchange(dbDumpUrl(), POST, reqEntity(), String.class);
public String createControlDbDump(String host) {
ResponseEntity<String> dbDumpPath = restTemplate.exchange(dbDumpUrl(host), POST, reqEntity(), String.class);
return dbDumpPath.getBody();
}
......@@ -51,7 +51,7 @@ public class AxonDbRestClient {
return config.getJobs().get(0).getAxondbHost() + config.getSnapshotsUrl();
}
private String dbDumpUrl() {
private String dbDumpUrl(String host) {
return config.getJobs().get(0).getAxondbHost() + config.getControlDbUrl();
}
......
package nl.trifork.axondbbackupclient.cron;
import com.google.common.base.Stopwatch;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import nl.trifork.axondbbackupclient.backup.BackupJob;
import nl.trifork.axondbbackupclient.backup.BackupService;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static nl.trifork.axondbbackupclient.cron.BackupStatus.DONE;
import static nl.trifork.axondbbackupclient.cron.BackupStatus.ERROR;
import static nl.trifork.axondbbackupclient.cron.BackupStatus.RUNNING;
@Service
@RequiredArgsConstructor
@Slf4j
public class BackupRunner {
private final Executor executor = newFixedThreadPool(8);
private final List<BackupTask> queue = new CopyOnWriteArrayList<>();
private final BackupService backupService;
public void add(BackupTask task) {
task.getJobs().forEach(j -> executor.execute(() -> runJob(j, task)));
queue.add(task);
}
private void runJob(BackupJob job, BackupTask task) {
Stopwatch sw = Stopwatch.createStarted();
MDC.put("traceId", task.getId());
task.getStatus().put(job.getName(), RUNNING);
log.info("Running job {}", job.getName());
try {
backupService.run(job);
task.getStatus().put(job.getName(), DONE);
log.info("Finished job {} in {}", job.getName(), sw);
} catch (RuntimeException e) {
task.getStatus().put(job.getName(), ERROR);
log.error("Failed job {}", job.getName(), e);
} finally {
MDC.remove("traceId");
}
}
}
package nl.trifork.axondbbackupclient.cron;
public enum BackupStatus {
SCHEDULLED,
RUNNING,
DONE,
ERROR
}
package nl.trifork.axondbbackupclient.cron;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import nl.trifork.axondbbackupclient.backup.BackupJob;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static nl.trifork.axondbbackupclient.cron.BackupStatus.SCHEDULLED;
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class BackupTask {
@EqualsAndHashCode.Include
private final String id;
private final Instant timestamp = Instant.now();
private final List<BackupJob> jobs;
private final Map<String, BackupStatus> status;
public static BackupTask task(List<BackupJob> jobs) {
String id = UUID.randomUUID().toString().substring(24);
Map<String, BackupStatus> statuses = new HashMap<>();
jobs.forEach(j -> statuses.put(j.getName(), SCHEDULLED));
return new BackupTask(id, jobs, statuses);
}
}
package nl.trifork.axondbbackupclient.backup_services;
package nl.trifork.axondbbackupclient.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
......@@ -9,10 +8,9 @@ import java.io.IOException;
import static org.apache.commons.io.FileUtils.copyFile;
@Slf4j
@Service
public class FileIoService {
public void copy(File file, String destinationDir) {
public static void copy(File file, String destinationDir) {
try {
String destinationFilePath = destinationDir + file.getName();
File destinationFile = new File(destinationFilePath);
......
package nl.trifork.axondbbackupclient.web;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import nl.trifork.axondbbackupclient.BackupConfig;
import nl.trifork.axondbbackupclient.cron.BackupRunner;
import nl.trifork.axondbbackupclient.cron.BackupTask;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@Slf4j
public class Controller {
private final BackupRunner runner;
private final BackupConfig config;
@PostMapping("/run")
public String runBackup() {
BackupTask task = BackupTask.task(config.getJobs());
log.info("Adding task {}", task);
runner.add(task);
return "Submitted";
}
}
spring:
application:
name: axondb-backup-client
main:
banner-mode: "off"
server:
port: 9080
......@@ -10,7 +12,12 @@ management:
web:
base-path: /manage
exposure:
include: "*"
include: health,loggers,info,metrics
logging:
level:
root: ERROR
nl.trifork: TRACE
backup:
fixedDelayMs: 60000
......@@ -27,4 +34,6 @@ backup:
axondbHost: http://127.0.0.1:8023/axondb
eventsPath: ./axon/axondb1/events/
snapshotsPath: ./axon/axondb1/events/
controlDbPath: ./axon/axondb1/controldb/
\ No newline at end of file
controlDbPath: ./axon/axondb1/controldb/
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %highlight(%-5level) %X{traceId} %-25.25class{0} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
\ No newline at end of file
package nl.trifork.axondbbackupclient;
import nl.trifork.axondbbackupclient.axondb_client.AxonDbRestClient;
import nl.trifork.axondbbackupclient.backup_services.ControlDBBackupService;
import nl.trifork.axondbbackupclient.backup_services.FileIoService;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ControlDBBackupServiceTest {
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
BackupConfig config = new BackupConfig();
AxonDbRestClient client = mock(AxonDbRestClient.class);
FileIoService fileService = mock(FileIoService.class);
ControlDBBackupService subj = new ControlDBBackupService(config, client, fileService);
@Test
public void should_create_and_copy_db_dump() throws IOException {
File dumpFile = tmp.newFile("control1234.db");
File dbBackup = tmp.newFolder("dbBackup");
when(client.createControlDbDump()).thenReturn(dumpFile.getAbsolutePath());
// config.setControlDbPath(dbBackup.getAbsolutePath());
//when
subj.backup();
//then
// verify(fileService).copy(dumpFile, config.getControlDbPath());
assertThat(dumpFile.exists()).isFalse();
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment