/**
* Copyright (c) 2016, All Contributors (see CONTRIBUTORS file)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.eventsourcing.queries;
import com.eventsourcing.*;
import com.eventsourcing.hlc.HybridTimestamp;
import com.eventsourcing.index.Index;
import com.eventsourcing.index.SimpleIndex;
import com.google.common.collect.Iterators;
import com.googlecode.concurrenttrees.common.Iterables;
import com.googlecode.cqengine.IndexedCollection;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.resultset.ResultSet;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.Value;
import lombok.experimental.Accessors;
import org.testng.annotations.Test;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static com.eventsourcing.index.IndexEngine.IndexFeature.*;
import static com.eventsourcing.queries.QueryFactory.equal;
import static com.eventsourcing.queries.QueryFactory.isLatestEntity;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class IsLatestEntityTest extends RepositoryUsingTest {
public IsLatestEntityTest() {
super(IsLatestEntityTest.class.getPackage());
}
@Value
@EqualsAndHashCode(callSuper = false)
@Accessors(fluent = true)
public static class TestEvent extends StandardEvent {
private String test;
private UUID reference;
public final static SimpleIndex<TestEvent, UUID> REFERENCE_ID = SimpleIndex.as(TestEvent::reference);
@Index({EQ, LT, GT})
public final static SimpleIndex<TestEvent, HybridTimestamp> TIMESTAMP = SimpleIndex.as(StandardEntity::timestamp);
}
@Value
@EqualsAndHashCode(callSuper = false)
@Accessors(fluent = true)
public static class TestCommand extends StandardCommand<Void, UUID> {
private String test;
private UUID reference;
@Override public EventStream<Void> events() throws Exception {
TestEvent event = new TestEvent(test, reference);
return EventStream.of(event);
}
@Override public UUID result() {
return reference;
}
}
@Test @SneakyThrows
public void test() {
UUID uuid = UUID.randomUUID();
repository.publish(new TestCommand("test1", uuid)).get();
Query<EntityHandle<TestEvent>> query = isLatestEntity(equal(TestEvent.REFERENCE_ID, uuid),
TestEvent.TIMESTAMP);
try (ResultSet<EntityHandle<TestEvent>> resultSet = repository.query(TestEvent.class, query)) {
assertEquals(resultSet.size(), 1);
assertEquals(resultSet.uniqueResult().get().test(), "test1");
}
repository.publish(new TestCommand("test2", uuid)).get();
try (ResultSet<EntityHandle<TestEvent>> resultSet = repository.query(TestEvent.class, query)) {
assertEquals(resultSet.size(), 1);
assertEquals(resultSet.uniqueResult().get().test(), "test2");
}
}
@Test @SneakyThrows
public void testMassive() {
UUID uuid = UUID.randomUUID();
for (int i = 0; i < 10000; i++ ) {
repository.publish(new TestCommand("test" + (i + 1), uuid)).get();
}
Query<EntityHandle<TestEvent>> query = isLatestEntity(equal(TestEvent.REFERENCE_ID, uuid),
TestEvent.TIMESTAMP);
long t1 = System.nanoTime();
try (ResultSet<EntityHandle<TestEvent>> resultSet = repository.query(TestEvent.class, query)) {
assertEquals(resultSet.size(), 1);
assertEquals(resultSet.uniqueResult().get().test(), "test10000");
long t2 = System.nanoTime();
long time = TimeUnit.SECONDS.convert(t2 - t1, TimeUnit.NANOSECONDS);
if (time > 1) {
System.err.println("Warning: [IsLatestEntityTest.testMassive] isLatestEntity is slow, took " + time +
" seconds");
}
}
}
@Test @SneakyThrows
public void testFunction() {
UUID uuid = UUID.randomUUID();
repository.publish(new TestCommand("test1", uuid)).get();
repository.publish(new TestCommand("test2", uuid)).get();
UUID uuidN = UUID.randomUUID();
repository.publish(new TestCommand("testN1", uuidN)).get();
repository.publish(new TestCommand("testN2", uuidN)).get();
Query<EntityHandle<TestEvent>> query = isLatestEntity((h) -> equal(TestEvent.REFERENCE_ID, h.get().reference()),
TestEvent.TIMESTAMP);
try (ResultSet<EntityHandle<TestEvent>> resultSet = repository.query(TestEvent.class, query)) {
assertEquals(resultSet.size(), 2);
List<EntityHandle<TestEvent>> result = Iterables.toList(resultSet);
assertTrue(Iterators.any(result.iterator(), e -> e.get().test().contentEquals("test2")));
assertTrue(Iterators.any(result.iterator(), e -> e.get().test().contentEquals("testN2")));
}
}
}