package com.constellio.data.dao.services.sequence;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.junit.Before;
import org.junit.Test;
import com.constellio.data.dao.services.idGenerator.UUIDV1Generator;
import com.constellio.data.utils.ThreadList;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.annotations.SlowTest;
public class SolrSequencesManagerAcceptTest extends ConstellioTest {
private static final String CONFIG_PATH = "/sequence.properties";
SolrSequencesManager sequencesManager;
SolrClient client;
@Before
public void setUp()
throws Exception {
notAUnitItest = true;
//TODO AFTER-TEST-VALIDATION-SEQ
givenDisabledAfterTestValidations();
givenTransactionLogIsEnabled();
sequencesManager = new SolrSequencesManager(getDataLayerFactory().newRecordDao(),
getDataLayerFactory().getSecondTransactionLogManager());
client = getDataLayerFactory().newRecordDao().getBigVaultServer().getNestedSolrServer();
}
@Test
@SlowTest
public void givenMultipleThreadsWitDifferentGeneratorThenAlwaysUniqueIds()
throws Exception {
final Set<Long> concurrentSet = Collections.synchronizedSet(new HashSet<Long>());
final List<Long> concurrentList = Collections.synchronizedList(new ArrayList<Long>());
ThreadList<Thread> threads = new ThreadList<>();
final AtomicInteger total = new AtomicInteger();
for (int i = 0; i < 100; i++) {
threads.add(new Thread() {
@Override
public void run() {
SequencesManager sequencesManager = new SolrSequencesManager(getDataLayerFactory().newRecordDao(), null);
List<Long> ids = new ArrayList<Long>();
for (int j = 0; j < 200; j++) {
try {
ids.add(sequencesManager.next("zeSequence"));
total.incrementAndGet();
} catch (Exception e) {
e.printStackTrace();
}
}
concurrentSet.addAll(ids);
concurrentList.addAll(ids);
}
});
}
threads.startAll();
while (total.get() < 18000) {
System.out.println(total.get() + "/20000");
Thread.sleep(2000);
}
threads.joinAll();
assertThat(concurrentList.size()).isEqualTo(20000);
assertThat(concurrentSet.size()).isEqualTo(20000);
}
@Test
public void givenMultipleThreadsWitSameGeneratorThenAlwaysUniqueIds()
throws Exception {
final Set<Long> concurrentSet = Collections.synchronizedSet(new HashSet<Long>());
ThreadList<Thread> threads = new ThreadList<>();
for (int i = 0; i < 10; i++) {
threads.add(new Thread() {
@Override
public void run() {
Set<Long> ids = new HashSet<Long>();
for (int j = 0; j < 1000; j++) {
concurrentSet.add(sequencesManager.next("zeSequence"));
}
//concurrentSet.addAll(ids);
}
});
}
threads.startAll();
while (concurrentSet.size() < 10000) {
System.out.println(concurrentSet.size());
Thread.sleep(2000);
}
threads.joinAll();
assertThat(concurrentSet).hasSize(10000);
}
@Test
public void whenGetIdsThenZeroPadded()
throws Exception {
assertThat(sequencesManager.next("sequence1")).isEqualTo(1L);
assertThat(sequencesManager.next("sequence1")).isEqualTo(2L);
assertThat(sequencesManager.next("sequence2")).isEqualTo(1L);
}
@Test
public void whenCallNextSetAndLastSequenceValueThenCorrectAnswers()
throws Exception {
SequencesManager sequencesManager1 = new SolrSequencesManager(getDataLayerFactory().newRecordDao(),
getDataLayerFactory().getSecondTransactionLogManager());
SequencesManager sequencesManager2 = new SolrSequencesManager(getDataLayerFactory().newRecordDao(),
getDataLayerFactory().getSecondTransactionLogManager());
assertThat(sequencesManager1.next("seq1")).isEqualTo(1L);
assertThat(sequencesManager1.getLastSequenceValue("seq1")).isEqualTo(1L);
assertThat(sequencesManager2.next("seq1")).isEqualTo(2L);
assertThat(sequencesManager1.next("seq1")).isEqualTo(3L);
assertThat(sequencesManager2.next("seq1")).isEqualTo(4L);
assertThat(sequencesManager1.next("seq1")).isEqualTo(5L);
assertThat(sequencesManager1.getLastSequenceValue("seq1")).isEqualTo(5L);
assertThat(sequencesManager2.next("seq1")).isEqualTo(6L);
assertThat(sequencesManager1.getLastSequenceValue("seq1")).isEqualTo(6L);
assertThat(sequencesManager1.next("seq2")).isEqualTo(1L);
assertThat(sequencesManager2.next("seq2")).isEqualTo(2L);
assertThat(sequencesManager1.getLastSequenceValue("seq2")).isEqualTo(2L);
assertThat(sequencesManager1.next("seq2")).isEqualTo(3L);
assertThat(sequencesManager2.next("seq2")).isEqualTo(4L);
assertThat(sequencesManager1.getLastSequenceValue("seq2")).isEqualTo(4L);
sequencesManager1.set("seq2", 2L);
assertThat(sequencesManager1.next("seq2")).isEqualTo(3L);
assertThat(sequencesManager2.next("seq2")).isEqualTo(4L);
assertThat(getSequenceDocument("seq1").getFieldValues("uuids_ss")).hasSize(1);
assertThat(getSequenceDocument("seq1").getFieldValues("uuids_to_remove_ss")).hasSize(1);
assertThat(getSequenceDocument("seq2").getFieldValues("uuids_ss")).hasSize(1);
assertThat(getSequenceDocument("seq2").getFieldValues("uuids_to_remove_ss")).hasSize(1);
}
@Test
@SlowTest
public void givenASystemHasFallenBetweenTheIncAndTheAddUUIDToRemoveStepThenUUIDRemovedWhenOneThousandAfterHim()
throws Exception {
String previousUUID = UUIDV1Generator.newRandomId();
sequencesManager.createSequenceDocument("seq1", previousUUID);
for (int i = 0; i < 999; i++) {
System.out.println(i);
assertThat(sequencesManager.next("seq1")).isEqualTo(2 + i);
SolrDocument sequenceDocument = getSequenceDocument("seq1");
assertThat(sequenceDocument.getFieldValues("uuids_ss")).hasSize(2 + i);
}
sequencesManager.next("seq1");
SolrDocument sequenceDocument = getSequenceDocument("seq1");
assertThat(sequenceDocument.getFieldValues("uuids_ss")).hasSize(1);
}
SolrDocument getSequenceDocument(String sequenceId)
throws Exception {
client.commit(true, true, true);
ModifiableSolrParams solrParams = new ModifiableSolrParams();
solrParams.set("q", "id:seq_" + sequenceId);
QueryResponse queryResponse = client.query(solrParams);
if (queryResponse.getResults().size() == 0) {
return null;
} else {
return queryResponse.getResults().get(0);
}
}
}