Support backup and recovery of db vars

This commit is contained in:
Abbas Abou Daya 2019-09-16 22:37:16 -07:00
parent 6f0247232f
commit aa3448544e
3 changed files with 70 additions and 9 deletions

View File

@ -0,0 +1,45 @@
package org.telegram.abilitybots.api.db;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import java.util.Objects;
public class BackupVar<T> {
@JsonProperty("var")
private final T var;
private BackupVar(T var) {
this.var = var;
}
@JsonCreator
public static <R> BackupVar<R> createVar(@JsonProperty("var") R var) {
return new BackupVar<>(var);
}
public T var() {
return var;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BackupVar<?> backupVar = (BackupVar<?>) o;
return Objects.equals(var, backupVar.var);
}
@Override
public int hashCode() {
return Objects.hash(var);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("var", var)
.toString();
}
}

View File

@ -12,12 +12,7 @@ import org.mapdb.Serializer;
import org.telegram.abilitybots.api.util.Pair;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
@ -188,15 +183,15 @@ public class MapDBContext implements DBContext {
return Pair.of(entry.getKey(), newArrayList((List) struct));
else if (struct instanceof Map)
return Pair.of(entry.getKey(), new BackupMap((Map) struct));
else
return Pair.of(entry.getKey(), struct);
else if (struct instanceof Atomic.Var)
return Pair.of(entry.getKey(), BackupVar.createVar(((Atomic.Var) struct).get()));
return Pair.of(entry.getKey(), struct);
}).collect(toMap(pair -> (String) pair.a(), Pair::b));
}
private void doRecover(Map<String, Object> backupData) {
clear();
backupData.forEach((name, value) -> {
if (value instanceof Set) {
Set entrySet = (Set) value;
getSet(name).addAll(entrySet);
@ -206,6 +201,8 @@ public class MapDBContext implements DBContext {
} else if (value instanceof List) {
List entryList = (List) value;
getList(name).addAll(entryList);
} else if (value instanceof BackupVar) {
getVar(name).set(((BackupVar) value).var());
} else {
log.error(format("Unable to identify object type during DB recovery, entry name: %s", name));
}

View File

@ -12,6 +12,7 @@ import java.util.Set;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import static java.lang.String.format;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@ -38,6 +39,24 @@ class MapDBContextTest {
db.close();
}
@Test
void canRecoverVar() {
Var<String> test = db.getVar(TEST);
String val = "abilitybot";
test.set(val);
Object backup = db.backup();
db.clear();
// db.clear does not clear atomic variables
// TODO: get clear to remove all non-collection variables in DB
test.set("somevalue");
boolean recovered = db.recover(backup);
String recoveredVal = db.<String>getVar(TEST).get();
assertTrue(recovered, "Could not recover JSON backup file");
assertEquals(val, recoveredVal, "Could not properly recover val from Var in DB");
}
@Test
void canRecoverDB() {
Map<Integer, User> users = db.getMap(USERS);