Fix multi-threading, add Query interface, java test

This commit is contained in:
2024-05-04 17:13:34 +02:00
parent 34b620dfa5
commit cc3ac67be6
11 changed files with 488 additions and 80 deletions

View File

@@ -0,0 +1,126 @@
package nl.astraeus.persistence;
import nl.astraeus.nl.astraeus.persistence.AbstractPersistable;
import nl.astraeus.nl.astraeus.persistence.Index;
import nl.astraeus.nl.astraeus.persistence.Persistable;
import nl.astraeus.nl.astraeus.persistence.Persistent;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.List;
public class TestPersistenceJava {
static class Person extends AbstractPersistable {
private static Long serialVersionUID = 1L;
private long id = 0;
private long version = 0;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public long getId() {
return id;
}
@Override
public void setId(long id) {
this.id = id;
}
@Override
public long getVersion() {
return version;
}
@Override
public void setVersion(long version) {
this.version = version;
}
}
@Test
void testPersistence() {
System.out.println("TestPersistenceJava.testPersistence");
Persistent persistent = new Persistent(
new File("data", "java-test"),
new Index[] {
new Index<>(
Person.class,
"name",
(p) -> ((Person)p).getName()
)
}
);
persistent.transaction((t) -> {
Person person = t.find(Person.class, 1L);
if (person != null) {
System.out.println(
"Person: "
+ person.getName() + " is "
+ person.getAge() + " years old."
);
}
return null;
});
persistent.transaction((t) -> {
Person person = new Person("John Doe", 42);
t.store(person);
return null;
});
persistent.transaction((t) -> {
List<Person> persons = t.findByIndex(
Person.class,
"name",
"John Doe"
);
for (Person person : persons) {
System.out.println(
"Person: "
+ person.getName() + " is "
+ person.getAge() + " years old."
);
}
return null;
});
persistent.snapshot();
persistent.getDatastore().printStatus();
persistent.removeOldFiles();
}
}

View File

@@ -1,9 +1,13 @@
package nl.astraeus.persistence
import nl.astraeus.nl.astraeus.persistence.Index
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent
import nl.astraeus.nl.astraeus.persistence.Reference
import nl.astraeus.nl.astraeus.persistence.find
import nl.astraeus.nl.astraeus.persistence.findByIndex
import nl.astraeus.nl.astraeus.persistence.index
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertNull
import java.io.File
import kotlin.test.Test
@@ -39,31 +43,31 @@ class TestPersistence {
println("Test persistence")
val pst = Persistent(
directory = File("data"),
directory = File("data", "test-persistence"),
arrayOf(
Index(Person::class, "name") { p -> (p as? Person)?.name ?: "" },
Index(Person::class, "age") { p -> (p as? Person)?.age ?: -1 },
Index(Person::class, "ageGt20") { p -> ((p as? Person)?.age ?: 0) > 20 },
Index(Person::class, "ageGt23") { p -> ((p as? Person)?.age ?: 0) > 23 },
Index(Person::class, "ageOnlyGt20") { p ->
index<Person>("name") { p -> (p as? Person)?.name ?: "" },
index<Person>("age") { p -> (p as? Person)?.age ?: -1 },
index<Person>("ageGt20") { p -> ((p as? Person)?.age ?: 0) > 20 },
index<Person>("ageGt23") { p -> ((p as? Person)?.age ?: 0) > 23 },
index<Person>("ageOnlyGt20") { p ->
if (((p as? Person)?.age ?: 0) > 20) {
true
} else {
null
}
},
Index(Company::class, "name") { p -> (p as? Company)?.name ?: "" },
index<Company>("name") { p -> (p as? Company)?.name ?: "" },
)
)
pst.transaction {
val person = find(Person::class, 1L) ?: Person(
val person = find<Person>(1L) ?: Person(
id = 1L,
name = "John Doe",
age = 25
)
val company = find(Company::class, 1L) ?: Company(
val company = find<Company>(1L) ?: Company(
id = 1L,
name = "ACME"
)
@@ -83,14 +87,19 @@ class TestPersistence {
age = 18
))
findByIndex(Person::class, "name", "John Doe").forEach { p ->
findByIndex<Person>("name", "John Doe").forEach { p ->
println("Found person by name: ${p.name} - ${p.age}")
}
findByIndex(Person::class, "age", 23).forEach { p ->
val persons: List<Person> = findByIndex("age", 23)
persons.forEach { p ->
println("Found person by age: ${p.name} - ${p.age}")
}
val companies: List<Company> = findByIndex("name", "ACME")
assert(companies.isNotEmpty())
findByIndex(Person::class, "ageGt20", true).forEach { p ->
println("Found person by age > 20: ${p.name} - ${p.age}")
}
@@ -112,6 +121,12 @@ class TestPersistence {
assert(c2 != null)
}
pst.query {
val person = find<Person>(1L)
assertNotNull(person)
}
pst.transaction {
val person = find(Person::class, 1L)
@@ -140,14 +155,19 @@ class TestPersistence {
age = 23
)
)
store(
Person(
id = 11L,
name = "John Clown",
age = 18
)
val person = Person(
id = 11L,
name = "John Clown",
age = 18
)
store(person)
assertNotNull(find(Person::class, person.id))
delete(person)
assertNull(find(Person::class, person.id))
store(person)
assertNotNull(find(Person::class, person.id))
searchIndex(Person::class, "name") {
name -> (name as? String)?.startsWith("John") == true
}.forEach { p ->

View File

@@ -0,0 +1,129 @@
package nl.astraeus.persistence
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent
import nl.astraeus.nl.astraeus.persistence.Reference
import nl.astraeus.nl.astraeus.persistence.count
import nl.astraeus.nl.astraeus.persistence.index
import nl.astraeus.nl.astraeus.persistence.searchIndex
import java.io.File
import kotlin.random.Random
import kotlin.test.Test
class TestThreaded {
class Company(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val adres: String = "Blaat"
) : Persistable, Cloneable {
//var persons: MutableList<Person> by ListReference<Person, Company>(Person::class.java)
companion object {
private const val serialVersionUID: Long = 1L
}
}
class Person(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val age: Int,
) : Persistable, Cloneable {
var company: Company by Reference<Company, Person>(Company::class.java)
companion object {
private const val serialVersionUID: Long = 1L
}
}
@Test
fun testThreaded() {
println("Test threaded")
val pst = Persistent(
directory = File("data", "test-threaded"),
arrayOf(
index<Person>("name") { p -> (p as? Person)?.name ?: "" },
index<Person>("age") { p -> (p as? Person)?.age ?: -1 },
index<Person>("ageGt20") { p -> ((p as? Person)?.age ?: 0) > 20 },
index<Person>("ageGt23") { p -> ((p as? Person)?.age ?: 0) > 23 },
index<Person>("ageOnlyGt20") { p ->
if (((p as? Person)?.age ?: 0) > 20) {
true
} else {
null
}
},
index<Person>("nameAndAge") { p ->
val person = p as? Person
if (person == null) {
null
} else {
person.name to person.age
}
},
index<Company>("name") { p -> (p as? Company)?.name ?: "" },
)
)
val companyNames = arrayOf("Company A", "Company B", "Company C", "Company D", "Company E")
val names = arrayOf("John Doe", "Jane Doe", "John Smith", "Jane Smith", "John Johnson", "Jane Johnson")
val random = Random(System.currentTimeMillis())
val empty = pst.query {
count<Person>() == 0
}
if (empty) {
val runnable = {
repeat(10) {
pst.transaction {
val company = Company(
id = 0L,
name = companyNames[random.nextInt(companyNames.size)]
)
repeat(10) {
val person = Person(
id = 0L,
name = names[random.nextInt(names.size)],
age = random.nextInt(0, 100),
)
person.company = company
store(person)
}
}
}
}
val threads = Array(25) {
Thread(runnable)
}
for (thread in threads) {
thread.start()
}
for (thread in threads) {
thread.join()
}
}
pst.query {
searchIndex<Person>("nameAndAge") { nameAndAge ->
val (name, age) = nameAndAge as Pair<String, Int>
name.contains("mit") && age > 80
}.forEach { p ->
println("Found person by name and age: ${p.id}: ${p.name} - ${p.age}")
}
}
pst.snapshot()
pst.datastore.printStatus()
pst.removeOldFiles()
}
}