mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-01 19:15:52 +01:00
Add unit tests for micrometer / Wrap data stores with proxies
Squash commits of branch feature/store_metering: - Wrap jaxb stores with proxies to get micrometer insights - Handle exceptions from proxy - User meter for queryable stores, too - Log change - Change name for metrics - Fix imports - Rename invocation handler - Change change log - Replace RuntimeException - Merge branch 'develop' into feature/store_metering - Add store type to description of timer - Fix measuring methods for queryable store - License - Simplify usage of wrapper - Rename class - Remove unnecessary condition
This commit is contained in:
committed by
Till-André Diegeler
parent
57f15f3ac4
commit
ce01cfc602
2
gradle/changelog/meter_stores.yaml
Normal file
2
gradle/changelog/meter_stores.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- type: added
|
||||||
|
description: Performance of stores can be measured with Micrometer metrics
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sonia.scm.store;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
|
import io.micrometer.core.instrument.Timer;
|
||||||
|
import sonia.scm.util.AssertUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.lang.reflect.UndeclaredThrowableException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class StoreInvocationMicrometerWrapper implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Object store;
|
||||||
|
private final MeterRegistry meterRegistry;
|
||||||
|
private final Consumer<Timer.Builder> timerCustomizer;
|
||||||
|
|
||||||
|
private final Supplier<Timer.Builder> timerBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a wrapper for the given store which will record the time taken for each method call.
|
||||||
|
* If the {@link MeterRegistry} is {@code null}, the store will not be wrapped and returned as is.
|
||||||
|
*/
|
||||||
|
public static <T> T create(String storeType,
|
||||||
|
TypedStoreParameters<?> storeParameters,
|
||||||
|
Class<T> storeClass,
|
||||||
|
T store,
|
||||||
|
MeterRegistry meterRegistry) {
|
||||||
|
if (meterRegistry == null) {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
return (T) Proxy.newProxyInstance(
|
||||||
|
storeParameters.getType().getClassLoader(),
|
||||||
|
new Class[]{storeClass},
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
storeType,
|
||||||
|
storeParameters,
|
||||||
|
store,
|
||||||
|
meterRegistry,
|
||||||
|
() -> Timer.builder("scm.persistence")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a wrapper for the given store which will record the time taken for each method call.
|
||||||
|
* If the {@link MeterRegistry} is {@code null}, the store will not be wrapped and returned as is.
|
||||||
|
*/
|
||||||
|
public static <T, Q> Q create(String storeType,
|
||||||
|
Class<T> clazz,
|
||||||
|
String[] parentIds,
|
||||||
|
Class<Q> storeClass,
|
||||||
|
Q store,
|
||||||
|
MeterRegistry meterRegistry) {
|
||||||
|
if (meterRegistry == null) {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
return (Q) Proxy.newProxyInstance(
|
||||||
|
clazz.getClassLoader(),
|
||||||
|
new Class[]{storeClass},
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
storeType,
|
||||||
|
clazz,
|
||||||
|
parentIds,
|
||||||
|
store,
|
||||||
|
meterRegistry,
|
||||||
|
() -> Timer.builder("scm.persistence")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
StoreInvocationMicrometerWrapper(String storeType,
|
||||||
|
TypedStoreParameters<?> storeParameters,
|
||||||
|
Object store,
|
||||||
|
MeterRegistry meterRegistry,
|
||||||
|
Supplier<Timer.Builder> timerBuilder) {
|
||||||
|
this(
|
||||||
|
meterRegistry,
|
||||||
|
store,
|
||||||
|
timer -> timer
|
||||||
|
.description("Time taken for store operation in " + storeType)
|
||||||
|
.tag("type", storeType)
|
||||||
|
.tag("storeName", storeParameters.getName())
|
||||||
|
.tag("repositoryId", storeParameters.getRepositoryId() == null ? "none" : storeParameters.getRepositoryId())
|
||||||
|
.tag("namespace", storeParameters.getNamespace() == null ? "none" : storeParameters.getNamespace()),
|
||||||
|
timerBuilder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
<T, Q> StoreInvocationMicrometerWrapper(String storeType,
|
||||||
|
Class<T> clazz,
|
||||||
|
String[] parentIds,
|
||||||
|
Q store,
|
||||||
|
MeterRegistry meterRegistry,
|
||||||
|
Supplier<Timer.Builder> timerBuilder) {
|
||||||
|
this(
|
||||||
|
meterRegistry,
|
||||||
|
store,
|
||||||
|
timer -> timer
|
||||||
|
.description("Time taken for store operation in " + storeType)
|
||||||
|
.tag("type", storeType)
|
||||||
|
.tag("storeClass", clazz.getName())
|
||||||
|
.tag("parentIds", String.join(",", parentIds)),
|
||||||
|
timerBuilder
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StoreInvocationMicrometerWrapper(MeterRegistry meterRegistry,
|
||||||
|
Object store,
|
||||||
|
Consumer<Timer.Builder> timerCustomizer,
|
||||||
|
Supplier<Timer.Builder> timerBuilder) {
|
||||||
|
AssertUtil.assertIsNotNull(store);
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
|
this.store = store;
|
||||||
|
this.timerCustomizer = timerCustomizer;
|
||||||
|
this.timerBuilder = timerBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
if (meterRegistry == null) {
|
||||||
|
return method.invoke(store, args);
|
||||||
|
}
|
||||||
|
if (QueryableStore.Query.class.isAssignableFrom(method.getReturnType())) {
|
||||||
|
Object delegate = method.invoke(store, args);
|
||||||
|
return Proxy.newProxyInstance(
|
||||||
|
this.getClass().getClassLoader(),
|
||||||
|
delegate.getClass().getInterfaces(),
|
||||||
|
new StoreInvocationMicrometerWrapper(meterRegistry, delegate, timerCustomizer, timerBuilder)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (method.getName().equals("close")) {
|
||||||
|
return method.invoke(store, args);
|
||||||
|
}
|
||||||
|
Timer.Builder timer = timerBuilder.get()
|
||||||
|
.tag("method", method.getName());
|
||||||
|
timerCustomizer.accept(timer);
|
||||||
|
return timer
|
||||||
|
.register(meterRegistry)
|
||||||
|
.record(() -> {
|
||||||
|
try {
|
||||||
|
return method.invoke(store, args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new StoreException("Failed to invoke store method", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (InvocationTargetException | UndeclaredThrowableException e) {
|
||||||
|
throw e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,17 +16,19 @@
|
|||||||
|
|
||||||
package sonia.scm.store.file;
|
package sonia.scm.store.file;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
||||||
import sonia.scm.security.KeyGenerator;
|
import sonia.scm.security.KeyGenerator;
|
||||||
import sonia.scm.store.ConfigurationEntryStore;
|
import sonia.scm.store.ConfigurationEntryStore;
|
||||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||||
|
import sonia.scm.store.StoreInvocationMicrometerWrapper;
|
||||||
import sonia.scm.store.TypedStoreParameters;
|
import sonia.scm.store.TypedStoreParameters;
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
|
public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
|
||||||
implements ConfigurationEntryStoreFactory {
|
implements ConfigurationEntryStoreFactory {
|
||||||
@@ -35,17 +37,39 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
|
|||||||
|
|
||||||
private final StoreCache<ConfigurationEntryStore<?>> storeCache;
|
private final StoreCache<ConfigurationEntryStore<?>> storeCache;
|
||||||
|
|
||||||
@Inject
|
private final MeterRegistry meterRegistry;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
public JAXBConfigurationEntryStoreFactory(
|
public JAXBConfigurationEntryStoreFactory(
|
||||||
SCMContextProvider contextProvider,
|
SCMContextProvider contextProvider,
|
||||||
RepositoryLocationResolver repositoryLocationResolver,
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
KeyGenerator keyGenerator,
|
KeyGenerator keyGenerator,
|
||||||
RepositoryReadOnlyChecker readOnlyChecker,
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
StoreCacheFactory storeCacheFactory
|
StoreCacheFactory storeCacheFactory
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
contextProvider,
|
||||||
|
repositoryLocationResolver,
|
||||||
|
keyGenerator,
|
||||||
|
readOnlyChecker,
|
||||||
|
storeCacheFactory,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public JAXBConfigurationEntryStoreFactory(
|
||||||
|
SCMContextProvider contextProvider,
|
||||||
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
|
KeyGenerator keyGenerator,
|
||||||
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
|
StoreCacheFactory storeCacheFactory,
|
||||||
|
MeterRegistry meterRegistry
|
||||||
) {
|
) {
|
||||||
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
|
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
|
||||||
this.keyGenerator = keyGenerator;
|
this.keyGenerator = keyGenerator;
|
||||||
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,8 +78,8 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
|
|||||||
return (ConfigurationEntryStore<T>) storeCache.getStore(storeParameters);
|
return (ConfigurationEntryStore<T>) storeCache.getStore(storeParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> ConfigurationEntryStore<T> createStore(TypedStoreParameters<T> storeParameters) {
|
private <T> ConfigurationEntryStore<T> createStore(TypedStoreParameters<T> storeParameters) {
|
||||||
return new JAXBConfigurationEntryStore<>(
|
JAXBConfigurationEntryStore<T> store = new JAXBConfigurationEntryStore<>(
|
||||||
getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION),
|
getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION),
|
||||||
storeParameters.getType(),
|
storeParameters.getType(),
|
||||||
storeParameters.getRepositoryId(),
|
storeParameters.getRepositoryId(),
|
||||||
@@ -64,5 +88,13 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
|
|||||||
storeParameters.getType(),
|
storeParameters.getType(),
|
||||||
TypedStoreContext.of(storeParameters)
|
TypedStoreContext.of(storeParameters)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"configuration-entry-store",
|
||||||
|
storeParameters,
|
||||||
|
ConfigurationEntryStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,17 @@
|
|||||||
|
|
||||||
package sonia.scm.store.file;
|
package sonia.scm.store.file;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
||||||
import sonia.scm.store.ConfigurationStore;
|
import sonia.scm.store.ConfigurationStore;
|
||||||
import sonia.scm.store.ConfigurationStoreDecoratorFactory;
|
import sonia.scm.store.ConfigurationStoreDecoratorFactory;
|
||||||
import sonia.scm.store.ConfigurationStoreFactory;
|
import sonia.scm.store.ConfigurationStoreFactory;
|
||||||
|
import sonia.scm.store.StoreInvocationMicrometerWrapper;
|
||||||
import sonia.scm.store.StoreDecoratorFactory;
|
import sonia.scm.store.StoreDecoratorFactory;
|
||||||
import sonia.scm.store.TypedStoreParameters;
|
import sonia.scm.store.TypedStoreParameters;
|
||||||
|
|
||||||
@@ -40,17 +43,39 @@ public class JAXBConfigurationStoreFactory extends FileBasedStoreFactory impleme
|
|||||||
|
|
||||||
private final StoreCache<ConfigurationStore<?>> storeCache;
|
private final StoreCache<ConfigurationStore<?>> storeCache;
|
||||||
|
|
||||||
@Inject
|
private final MeterRegistry meterRegistry;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
public JAXBConfigurationStoreFactory(
|
public JAXBConfigurationStoreFactory(
|
||||||
SCMContextProvider contextProvider,
|
SCMContextProvider contextProvider,
|
||||||
RepositoryLocationResolver repositoryLocationResolver,
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
RepositoryReadOnlyChecker readOnlyChecker,
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
Set<ConfigurationStoreDecoratorFactory> decoratorFactories,
|
Set<ConfigurationStoreDecoratorFactory> decoratorFactories,
|
||||||
StoreCacheFactory storeCacheFactory
|
StoreCacheFactory storeCacheFactory
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
contextProvider,
|
||||||
|
repositoryLocationResolver,
|
||||||
|
readOnlyChecker,
|
||||||
|
decoratorFactories,
|
||||||
|
storeCacheFactory,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public JAXBConfigurationStoreFactory(
|
||||||
|
SCMContextProvider contextProvider,
|
||||||
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
|
Set<ConfigurationStoreDecoratorFactory> decoratorFactories,
|
||||||
|
StoreCacheFactory storeCacheFactory,
|
||||||
|
MeterRegistry meterRegistry
|
||||||
) {
|
) {
|
||||||
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
|
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
|
||||||
this.decoratorFactories = decoratorFactories;
|
this.decoratorFactories = decoratorFactories;
|
||||||
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,6 +101,12 @@ public class JAXBConfigurationStoreFactory extends FileBasedStoreFactory impleme
|
|||||||
store = factory.createDecorator(store, new StoreDecoratorFactory.Context(storeParameters));
|
store = factory.createDecorator(store, new StoreDecoratorFactory.Context(storeParameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
return store;
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"configuration-store",
|
||||||
|
storeParameters,
|
||||||
|
ConfigurationStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,22 @@
|
|||||||
|
|
||||||
package sonia.scm.store.file;
|
package sonia.scm.store.file;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
||||||
import sonia.scm.security.KeyGenerator;
|
import sonia.scm.security.KeyGenerator;
|
||||||
import sonia.scm.store.DataStore;
|
import sonia.scm.store.DataStore;
|
||||||
import sonia.scm.store.DataStoreFactory;
|
import sonia.scm.store.DataStoreFactory;
|
||||||
|
import sonia.scm.store.StoreInvocationMicrometerWrapper;
|
||||||
import sonia.scm.store.TypedStoreParameters;
|
import sonia.scm.store.TypedStoreParameters;
|
||||||
import sonia.scm.util.IOUtil;
|
import sonia.scm.util.IOUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class JAXBDataStoreFactory extends FileBasedStoreFactory
|
public class JAXBDataStoreFactory extends FileBasedStoreFactory
|
||||||
implements DataStoreFactory {
|
implements DataStoreFactory {
|
||||||
@@ -40,7 +42,9 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
|
|||||||
|
|
||||||
private final DataFileCache dataFileCache;
|
private final DataFileCache dataFileCache;
|
||||||
|
|
||||||
@Inject
|
private final MeterRegistry meterRegistry;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
public JAXBDataStoreFactory(
|
public JAXBDataStoreFactory(
|
||||||
SCMContextProvider contextProvider,
|
SCMContextProvider contextProvider,
|
||||||
RepositoryLocationResolver repositoryLocationResolver,
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
@@ -48,11 +52,33 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
|
|||||||
RepositoryReadOnlyChecker readOnlyChecker,
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
DataFileCache dataFileCache,
|
DataFileCache dataFileCache,
|
||||||
StoreCacheFactory storeCacheFactory
|
StoreCacheFactory storeCacheFactory
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
contextProvider,
|
||||||
|
repositoryLocationResolver,
|
||||||
|
keyGenerator,
|
||||||
|
readOnlyChecker,
|
||||||
|
dataFileCache,
|
||||||
|
storeCacheFactory,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public JAXBDataStoreFactory(
|
||||||
|
SCMContextProvider contextProvider,
|
||||||
|
RepositoryLocationResolver repositoryLocationResolver,
|
||||||
|
KeyGenerator keyGenerator,
|
||||||
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
|
DataFileCache dataFileCache,
|
||||||
|
StoreCacheFactory storeCacheFactory,
|
||||||
|
MeterRegistry meterRegistry
|
||||||
) {
|
) {
|
||||||
super(contextProvider, repositoryLocationResolver, Store.DATA, readOnlyChecker);
|
super(contextProvider, repositoryLocationResolver, Store.DATA, readOnlyChecker);
|
||||||
this.keyGenerator = keyGenerator;
|
this.keyGenerator = keyGenerator;
|
||||||
this.dataFileCache = dataFileCache;
|
this.dataFileCache = dataFileCache;
|
||||||
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,15 +87,25 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
|
|||||||
return (DataStore<T>) storeCache.getStore(storeParameters);
|
return (DataStore<T>) storeCache.getStore(storeParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> DataStore<T> createStore(TypedStoreParameters<T> storeParameters) {
|
private <T> DataStore<T> createStore(TypedStoreParameters<T> storeParameters) {
|
||||||
File storeLocation = getStoreLocation(storeParameters);
|
File storeLocation = getStoreLocation(storeParameters);
|
||||||
IOUtil.mkdirs(storeLocation);
|
IOUtil.mkdirs(storeLocation);
|
||||||
return new JAXBDataStore<>(
|
|
||||||
|
// Create a proxy for the created store and use Micrometer to instrument it
|
||||||
|
JAXBDataStore<T> store = new JAXBDataStore<>(
|
||||||
keyGenerator,
|
keyGenerator,
|
||||||
TypedStoreContext.of(storeParameters),
|
TypedStoreContext.of(storeParameters),
|
||||||
storeLocation,
|
storeLocation,
|
||||||
mustBeReadOnly(storeParameters),
|
mustBeReadOnly(storeParameters),
|
||||||
dataFileCache.instanceFor(storeParameters.getType())
|
dataFileCache.instanceFor(storeParameters.getType())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"data-store",
|
||||||
|
storeParameters,
|
||||||
|
DataStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -31,7 +32,10 @@ import sonia.scm.plugin.QueryableTypeDescriptor;
|
|||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
import sonia.scm.repository.RepositoryReadOnlyChecker;
|
||||||
import sonia.scm.security.KeyGenerator;
|
import sonia.scm.security.KeyGenerator;
|
||||||
|
import sonia.scm.store.StoreInvocationMicrometerWrapper;
|
||||||
import sonia.scm.store.QueryableMaintenanceStore;
|
import sonia.scm.store.QueryableMaintenanceStore;
|
||||||
|
import sonia.scm.store.QueryableMutableStore;
|
||||||
|
import sonia.scm.store.QueryableStore;
|
||||||
import sonia.scm.store.QueryableStoreFactory;
|
import sonia.scm.store.QueryableStoreFactory;
|
||||||
import sonia.scm.store.StoreException;
|
import sonia.scm.store.StoreException;
|
||||||
|
|
||||||
@@ -62,6 +66,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
private final KeyGenerator keyGenerator;
|
private final KeyGenerator keyGenerator;
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final RepositoryReadOnlyChecker readOnlyChecker;
|
private final RepositoryReadOnlyChecker readOnlyChecker;
|
||||||
|
private final MeterRegistry meterRegistry;
|
||||||
|
|
||||||
private final Map<String, QueryableTypeDescriptor> queryableTypes = new HashMap<>();
|
private final Map<String, QueryableTypeDescriptor> queryableTypes = new HashMap<>();
|
||||||
|
|
||||||
@@ -73,6 +78,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
ObjectMapper objectMapper,
|
ObjectMapper objectMapper,
|
||||||
KeyGenerator keyGenerator,
|
KeyGenerator keyGenerator,
|
||||||
RepositoryReadOnlyChecker readOnlyChecker,
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
|
MeterRegistry meterRegistry,
|
||||||
@ConfigValue(key = "queryableStore.maxPoolSize", defaultValue = DEFAULT_MAX_POOL_SIZE) int maxPoolSize,
|
@ConfigValue(key = "queryableStore.maxPoolSize", defaultValue = DEFAULT_MAX_POOL_SIZE) int maxPoolSize,
|
||||||
@ConfigValue(key = "queryableStore.connectionTimeout", defaultValue = DEFAULT_CONNECTION_TIMEOUT_IN_SECONDS) int connectionTimeoutInSeconds,
|
@ConfigValue(key = "queryableStore.connectionTimeout", defaultValue = DEFAULT_CONNECTION_TIMEOUT_IN_SECONDS) int connectionTimeoutInSeconds,
|
||||||
@ConfigValue(key = "queryableStore.idleTimeout", defaultValue = DEFAULT_IDLE_TIMEOUT_IN_SECONDS) int idleTimeoutInSeconds,
|
@ConfigValue(key = "queryableStore.idleTimeout", defaultValue = DEFAULT_IDLE_TIMEOUT_IN_SECONDS) int idleTimeoutInSeconds,
|
||||||
@@ -85,6 +91,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
keyGenerator,
|
keyGenerator,
|
||||||
pluginLoader.getExtensionProcessor().getQueryableTypes(),
|
pluginLoader.getExtensionProcessor().getQueryableTypes(),
|
||||||
readOnlyChecker,
|
readOnlyChecker,
|
||||||
|
meterRegistry,
|
||||||
maxPoolSize,
|
maxPoolSize,
|
||||||
connectionTimeoutInSeconds,
|
connectionTimeoutInSeconds,
|
||||||
idleTimeoutInSeconds,
|
idleTimeoutInSeconds,
|
||||||
@@ -99,7 +106,19 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
KeyGenerator keyGenerator,
|
KeyGenerator keyGenerator,
|
||||||
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
|
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
|
||||||
RepositoryReadOnlyChecker readOnlyChecker) {
|
RepositoryReadOnlyChecker readOnlyChecker) {
|
||||||
this(connectionString, objectMapper, keyGenerator, queryableTypeIterable, readOnlyChecker, 10, 30, 600, 1800, 30);
|
this(
|
||||||
|
connectionString,
|
||||||
|
objectMapper,
|
||||||
|
keyGenerator,
|
||||||
|
queryableTypeIterable,
|
||||||
|
readOnlyChecker,
|
||||||
|
null,
|
||||||
|
10,
|
||||||
|
30,
|
||||||
|
600,
|
||||||
|
1800,
|
||||||
|
30
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SQLiteQueryableStoreFactory(String connectionString,
|
private SQLiteQueryableStoreFactory(String connectionString,
|
||||||
@@ -107,6 +126,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
KeyGenerator keyGenerator,
|
KeyGenerator keyGenerator,
|
||||||
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
|
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
|
||||||
RepositoryReadOnlyChecker readOnlyChecker,
|
RepositoryReadOnlyChecker readOnlyChecker,
|
||||||
|
MeterRegistry meterRegistry,
|
||||||
int maxPoolSize,
|
int maxPoolSize,
|
||||||
int connectionTimeoutInSeconds,
|
int connectionTimeoutInSeconds,
|
||||||
int idleTimeoutInSeconds,
|
int idleTimeoutInSeconds,
|
||||||
@@ -120,6 +140,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
maxLifetimeInSeconds,
|
maxLifetimeInSeconds,
|
||||||
leakDetectionThresholdInSeconds);
|
leakDetectionThresholdInSeconds);
|
||||||
this.readOnlyChecker = readOnlyChecker;
|
this.readOnlyChecker = readOnlyChecker;
|
||||||
|
this.meterRegistry = meterRegistry;
|
||||||
this.dataSource = new HikariDataSource(config);
|
this.dataSource = new HikariDataSource(config);
|
||||||
|
|
||||||
this.objectMapper = objectMapper
|
this.objectMapper = objectMapper
|
||||||
@@ -177,9 +198,9 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> SQLiteQueryableStore<T> getReadOnly(Class<T> clazz, String... parentIds) {
|
public <T> QueryableStore<T> getReadOnly(Class<T> clazz, String... parentIds) {
|
||||||
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
||||||
return new SQLiteQueryableStore<>(
|
SQLiteQueryableStore<T> store = new SQLiteQueryableStore<>(
|
||||||
objectMapper,
|
objectMapper,
|
||||||
openDefaultConnection(),
|
openDefaultConnection(),
|
||||||
clazz,
|
clazz,
|
||||||
@@ -188,12 +209,21 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
lock,
|
lock,
|
||||||
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"QueryableStore",
|
||||||
|
clazz,
|
||||||
|
parentIds,
|
||||||
|
QueryableStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> QueryableMaintenanceStore<T> getForMaintenance(Class<T> clazz, String... parentIds) {
|
public <T> QueryableMaintenanceStore<T> getForMaintenance(Class<T> clazz, String... parentIds) {
|
||||||
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
||||||
return new SQLiteQueryableStore<>(
|
SQLiteQueryableStore<T> store = new SQLiteQueryableStore<>(
|
||||||
objectMapper,
|
objectMapper,
|
||||||
openDefaultConnection(),
|
openDefaultConnection(),
|
||||||
clazz,
|
clazz,
|
||||||
@@ -202,12 +232,21 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
lock,
|
lock,
|
||||||
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"QueryableMaintenanceStore",
|
||||||
|
clazz,
|
||||||
|
parentIds,
|
||||||
|
QueryableMaintenanceStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> SQLiteQueryableMutableStore<T> getMutable(Class<T> clazz, String... parentIds) {
|
public <T> QueryableMutableStore<T> getMutable(Class<T> clazz, String... parentIds) {
|
||||||
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
|
||||||
return new SQLiteQueryableMutableStore<>(
|
SQLiteQueryableMutableStore<T> store = new SQLiteQueryableMutableStore<>(
|
||||||
objectMapper,
|
objectMapper,
|
||||||
keyGenerator,
|
keyGenerator,
|
||||||
openDefaultConnection(),
|
openDefaultConnection(),
|
||||||
@@ -217,6 +256,15 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
|
|||||||
lock,
|
lock,
|
||||||
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
mustBeReadOnly(queryableTypeDescriptor, parentIds)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return StoreInvocationMicrometerWrapper.create(
|
||||||
|
"QueryableMutableStore",
|
||||||
|
clazz,
|
||||||
|
parentIds,
|
||||||
|
QueryableMutableStore.class,
|
||||||
|
store,
|
||||||
|
meterRegistry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mustBeReadOnly(QueryableTypeDescriptor queryableTypeDescriptor, String... parentIds) {
|
private boolean mustBeReadOnly(QueryableTypeDescriptor queryableTypeDescriptor, String... parentIds) {
|
||||||
|
|||||||
@@ -0,0 +1,309 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 - present Cloudogu GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sonia.scm.store;
|
||||||
|
|
||||||
|
import io.micrometer.core.instrument.MeterRegistry;
|
||||||
|
import io.micrometer.core.instrument.Timer;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Answers.RETURNS_SELF;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.only;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class StoreInvocationMicrometerWrapperTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private MeterRegistry meterRegistry;
|
||||||
|
@Mock(answer = RETURNS_SELF)
|
||||||
|
private Timer.Builder timerBuilder;
|
||||||
|
@Mock
|
||||||
|
private Timer timer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpTimer() {
|
||||||
|
when(timerBuilder.register(any()))
|
||||||
|
.thenReturn(timer);
|
||||||
|
when(timer.record(any(Supplier.class)))
|
||||||
|
.thenAnswer(i -> i.getArgument(0, Supplier.class).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class ForSimpleStore {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DataStore<User> dataStore;
|
||||||
|
@Mock
|
||||||
|
private TypedStoreParameters<User> storeParameters;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpStore() {
|
||||||
|
when(storeParameters.getName())
|
||||||
|
.thenReturn("users");
|
||||||
|
when(dataStore.get("42")).thenReturn(new User("dent"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureDirectCallForGlobalStore() {
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"data",
|
||||||
|
storeParameters,
|
||||||
|
dataStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
|
||||||
|
User result = store
|
||||||
|
.get("42");
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.isEqualTo("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in data");
|
||||||
|
verify(timerBuilder).tag("method", "get");
|
||||||
|
verify(timerBuilder).tag("type", "data");
|
||||||
|
verify(timerBuilder).tag("storeName", "users");
|
||||||
|
verify(timerBuilder).tag("repositoryId", "none");
|
||||||
|
verify(timerBuilder).tag("namespace", "none");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureDirectCallForRepositoryStore() {
|
||||||
|
when(storeParameters.getRepositoryId())
|
||||||
|
.thenReturn("hog");
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"data",
|
||||||
|
storeParameters,
|
||||||
|
dataStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
|
||||||
|
User result = store
|
||||||
|
.get("42");
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.isEqualTo("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in data");
|
||||||
|
verify(timerBuilder).tag("method", "get");
|
||||||
|
verify(timerBuilder).tag("repositoryId", "hog");
|
||||||
|
verify(timerBuilder).tag("namespace", "none");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureDirectCallForNamespaceStore() {
|
||||||
|
when(storeParameters.getNamespace())
|
||||||
|
.thenReturn("intergalactic");
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"data",
|
||||||
|
storeParameters,
|
||||||
|
dataStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
|
||||||
|
User result = store
|
||||||
|
.get("42");
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.isEqualTo("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in data");
|
||||||
|
verify(timerBuilder).tag("method", "get");
|
||||||
|
verify(timerBuilder).tag("namespace", "intergalactic");
|
||||||
|
verify(timerBuilder).tag("repositoryId", "none");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class ForQueryableStore {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private QueryableStore<User> queryableStore;
|
||||||
|
@Mock
|
||||||
|
private QueryableStore.Query<User, User, ?> query;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpStore() {
|
||||||
|
when(queryableStore.query())
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
when(query.findAll())
|
||||||
|
.thenReturn(List.of(new User("dent")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureDirectCall() {
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"queryable",
|
||||||
|
User.class,
|
||||||
|
new String[]{"intergalactic", "hog"},
|
||||||
|
queryableStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
QueryableStore<User> store = (QueryableStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
|
||||||
|
List<User> result = store
|
||||||
|
.query()
|
||||||
|
.findAll();
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.containsExactly("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in queryable");
|
||||||
|
verify(timerBuilder).tag("method", "findAll");
|
||||||
|
verify(timerBuilder).tag("storeClass", "sonia.scm.user.User");
|
||||||
|
verify(timerBuilder).tag("parentIds", "intergalactic,hog");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureCallAfterOrder() {
|
||||||
|
when(query.orderBy(any(), any(QueryableStore.Order.class)))
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"queryable",
|
||||||
|
User.class,
|
||||||
|
new String[]{"intergalactic", "hog"},
|
||||||
|
queryableStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
QueryableStore store = (QueryableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
|
||||||
|
List<User> result = store
|
||||||
|
.query()
|
||||||
|
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
|
||||||
|
.findAll();
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.containsExactly("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in queryable");
|
||||||
|
verify(timerBuilder).tag("method", "findAll");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureCallAfterMultipleIndirection() {
|
||||||
|
when(query.orderBy(any(), any(QueryableStore.Order.class)))
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
when(query.distinct())
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
when(query.project(any()))
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"queryable",
|
||||||
|
User.class,
|
||||||
|
new String[]{"intergalactic", "hog"},
|
||||||
|
queryableStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
QueryableStore store = (QueryableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
|
||||||
|
List<User> result = store
|
||||||
|
.query()
|
||||||
|
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
|
||||||
|
.distinct()
|
||||||
|
.project(new QueryableStore.IdQueryField())
|
||||||
|
.findAll();
|
||||||
|
|
||||||
|
assertThat(result)
|
||||||
|
.extracting(User::getName)
|
||||||
|
.containsExactly("dent");
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in queryable");
|
||||||
|
verify(timerBuilder).tag("method", "findAll");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class ForQueryableMutableStore {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private QueryableMutableStore<User> queryableMutableStore;
|
||||||
|
@Mock
|
||||||
|
private QueryableMutableStore.MutableQuery<User, ?> query;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpStore() {
|
||||||
|
when(queryableMutableStore.query())
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldMeasureFinalCall() {
|
||||||
|
when(query.orderBy(any(), any(QueryableStore.Order.class)))
|
||||||
|
.thenAnswer(i -> query);
|
||||||
|
|
||||||
|
StoreInvocationMicrometerWrapper handler =
|
||||||
|
new StoreInvocationMicrometerWrapper(
|
||||||
|
"queryable",
|
||||||
|
User.class,
|
||||||
|
new String[]{"intergalactic", "hog"},
|
||||||
|
queryableMutableStore,
|
||||||
|
meterRegistry,
|
||||||
|
() -> timerBuilder
|
||||||
|
);
|
||||||
|
QueryableMutableStore<User> store = (QueryableMutableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableMutableStore.class}, handler);
|
||||||
|
store
|
||||||
|
.query()
|
||||||
|
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
|
||||||
|
.retain(100);
|
||||||
|
|
||||||
|
verify(timerBuilder).description("Time taken for store operation in queryable");
|
||||||
|
verify(timerBuilder).tag("method", "retain");
|
||||||
|
|
||||||
|
verify(timer, only()).record(any(Supplier.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.store.QueryableMaintenanceStore;
|
import sonia.scm.store.QueryableMaintenanceStore;
|
||||||
|
import sonia.scm.store.QueryableMutableStore;
|
||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -56,7 +57,7 @@ class SQLiteParallelizationTest {
|
|||||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
|
|
||||||
for (int i = 0; i < numThreads; i++) {
|
for (int i = 0; i < numThreads; i++) {
|
||||||
final String userId = "user-" + i;
|
final String userId = "user-" + i;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldPutObjectWithAutoIncrementId() {
|
void shouldPutObjectWithAutoIncrementId() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("42"));
|
store.put(new Spaceship("42"));
|
||||||
store.put(new Spaceship("23"));
|
store.put(new Spaceship("23"));
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldPutObjectWithGivenIdsThoughAutoIncrementActivated() {
|
void shouldPutObjectWithGivenIdsThoughAutoIncrementActivated() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
|
||||||
store.put("42", new Spaceship("42", SQLiteQueryableStoreTest.Range.INTER_GALACTIC));
|
store.put("42", new Spaceship("42", SQLiteQueryableStoreTest.Range.INTER_GALACTIC));
|
||||||
store.put("23", new Spaceship("23", SQLiteQueryableStoreTest.Range.SOLAR_SYSTEM));
|
store.put("23", new Spaceship("23", SQLiteQueryableStoreTest.Range.SOLAR_SYSTEM));
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRollback() throws SQLException {
|
void shouldRollback() throws SQLException {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
|
|
||||||
store.transactional(() -> {
|
store.transactional(() -> {
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
@@ -163,7 +163,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldDisableAutoCommit() throws SQLException {
|
void shouldDisableAutoCommit() throws SQLException {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
|
|
||||||
store.transactional(() -> {
|
store.transactional(() -> {
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
@@ -192,7 +192,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldGetObjectWithoutParent() {
|
void shouldGetObjectWithoutParent() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
User tricia = store.get("tricia");
|
User tricia = store.get("tricia");
|
||||||
@@ -205,7 +205,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnForNotExistingValue() {
|
void shouldReturnForNotExistingValue() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User earth = store.get("earth");
|
User earth = store.get("earth");
|
||||||
|
|
||||||
assertThat(earth)
|
assertThat(earth)
|
||||||
@@ -215,7 +215,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldGetObjectWithSingleParent() {
|
void shouldGetObjectWithSingleParent() {
|
||||||
new StoreTestBuilder(connectionString, "sonia.Group").withIds("1337").put("tricia", new User("McMillan"));
|
new StoreTestBuilder(connectionString, "sonia.Group").withIds("1337").put("tricia", new User("McMillan"));
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("42");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
User tricia = store.get("tricia");
|
User tricia = store.get("tricia");
|
||||||
@@ -229,7 +229,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldGetObjectWithMultipleParents() {
|
void shouldGetObjectWithMultipleParents() {
|
||||||
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
|
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
User tricia = store.get("tricia");
|
User tricia = store.get("tricia");
|
||||||
@@ -243,7 +243,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldGetAllForSingleEntry() {
|
void shouldGetAllForSingleEntry() {
|
||||||
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
|
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
Map<String, User> users = store.getAll();
|
Map<String, User> users = store.getAll();
|
||||||
@@ -257,7 +257,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldGetAllForMultipleEntries() {
|
void shouldGetAllForMultipleEntries() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
||||||
store.put("dent", new User("arthur"));
|
store.put("dent", new User("arthur"));
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldUseIdFromItemOnPut() {
|
void shouldUseIdFromItemOnPut() {
|
||||||
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
||||||
|
|
||||||
String id = store.put(new SpaceshipWithId("Heart of Gold", 42));
|
String id = store.put(new SpaceshipWithId("Heart of Gold", 42));
|
||||||
SpaceshipWithId spaceship = store.get("Heart of Gold");
|
SpaceshipWithId spaceship = store.get("Heart of Gold");
|
||||||
@@ -291,7 +291,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldSetNewIdInItemOnPut() {
|
void shouldSetNewIdInItemOnPut() {
|
||||||
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
||||||
|
|
||||||
String id = store.put(new SpaceshipWithId());
|
String id = store.put(new SpaceshipWithId());
|
||||||
SpaceshipWithId spaceship = store.get(id);
|
SpaceshipWithId spaceship = store.get(id);
|
||||||
@@ -302,7 +302,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldStoreWithNewIdAfterManualChange() {
|
void shouldStoreWithNewIdAfterManualChange() {
|
||||||
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
|
||||||
|
|
||||||
store.put(new SpaceshipWithId("Heart of Gold", 42));
|
store.put(new SpaceshipWithId("Heart of Gold", 42));
|
||||||
SpaceshipWithId spaceship = store.get("Heart of Gold");
|
SpaceshipWithId spaceship = store.get("Heart of Gold");
|
||||||
@@ -321,9 +321,9 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
class Clear {
|
class Clear {
|
||||||
@Test
|
@Test
|
||||||
void shouldClear() {
|
void shouldClear() {
|
||||||
SQLiteQueryableMutableStore<User> uneffectedStore = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337");
|
QueryableMutableStore<User> uneffectedStore = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337");
|
||||||
uneffectedStore.put("tricia", new User("McMillan"));
|
uneffectedStore.put("tricia", new User("McMillan"));
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
store.clear();
|
store.clear();
|
||||||
@@ -337,7 +337,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
class Remove {
|
class Remove {
|
||||||
@Test
|
@Test
|
||||||
void shouldRemove() {
|
void shouldRemove() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
|
||||||
store.put("dent", new User("arthur"));
|
store.put("dent", new User("arthur"));
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
class DeleteAll {
|
class DeleteAll {
|
||||||
@Test
|
@Test
|
||||||
void shouldDeleteAllInStoreWithoutSubsequentQuery() {
|
void shouldDeleteAllInStoreWithoutSubsequentQuery() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -365,7 +365,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldOnlyDeleteElementsMatchingTheQuery() {
|
void shouldOnlyDeleteElementsMatchingTheQuery() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -383,9 +383,9 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
|
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
|
||||||
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
|
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
|
||||||
try (
|
try (
|
||||||
SQLiteQueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
|
||||||
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
|
QueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
|
||||||
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
|
QueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
|
||||||
) {
|
) {
|
||||||
Spaceship spaceshipOne = new Spaceship("1");
|
Spaceship spaceshipOne = new Spaceship("1");
|
||||||
Spaceship spaceshipTwo = new Spaceship("2");
|
Spaceship spaceshipTwo = new Spaceship("2");
|
||||||
@@ -408,7 +408,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
class Retain {
|
class Retain {
|
||||||
@Test
|
@Test
|
||||||
void shouldRetainOneWithAscendingOrder() {
|
void shouldRetainOneWithAscendingOrder() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -423,7 +423,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldThrowIllegalArgumentExceptionIfKeptElementsIsNegative() {
|
void shouldThrowIllegalArgumentExceptionIfKeptElementsIsNegative() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -436,7 +436,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRetainOneWithDescendingOrder() {
|
void shouldRetainOneWithDescendingOrder() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -451,7 +451,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldDeleteUnselectedEntitiesAndRetainKeptElementsFromTheSelectedOnes() {
|
void shouldDeleteUnselectedEntitiesAndRetainKeptElementsFromTheSelectedOnes() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
|
|
||||||
Spaceship spaceshipOne = new Spaceship("LazyShip");
|
Spaceship spaceshipOne = new Spaceship("LazyShip");
|
||||||
Spaceship spaceshipTwo = new Spaceship("Biblical Ship");
|
Spaceship spaceshipTwo = new Spaceship("Biblical Ship");
|
||||||
@@ -477,7 +477,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRetainEverythingIfKeptElementsHigherThanContentQuantity() {
|
void shouldRetainEverythingIfKeptElementsHigherThanContentQuantity() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put("1", new Spaceship("1"));
|
store.put("1", new Spaceship("1"));
|
||||||
store.put("2", new Spaceship("2"));
|
store.put("2", new Spaceship("2"));
|
||||||
store.put("3", new Spaceship("3"));
|
store.put("3", new Spaceship("3"));
|
||||||
@@ -494,9 +494,9 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
|
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
|
||||||
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
|
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
|
||||||
try (
|
try (
|
||||||
SQLiteQueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
|
||||||
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
|
QueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
|
||||||
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
|
QueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
|
||||||
) {
|
) {
|
||||||
Spaceship spaceshipOne = new Spaceship("1");
|
Spaceship spaceshipOne = new Spaceship("1");
|
||||||
Spaceship spaceshipTwo = new Spaceship("2");
|
Spaceship spaceshipTwo = new Spaceship("2");
|
||||||
@@ -567,7 +567,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
Repository.class.getName() + ".class"
|
Repository.class.getName() + ".class"
|
||||||
).readOnly("42");
|
).readOnly("42");
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> store = storeTestBuilder.withIds("23");
|
QueryableMutableStore<User> store = storeTestBuilder.withIds("23");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
assertThat(store.get("tricia")).isNotNull();
|
assertThat(store.get("tricia")).isNotNull();
|
||||||
@@ -580,7 +580,7 @@ class SQLiteQueryableMutableStoreTest {
|
|||||||
Group.class.getName() + ".class"
|
Group.class.getName() + ".class"
|
||||||
).readOnly("42");
|
).readOnly("42");
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> store = storeTestBuilder.withIds("42");
|
QueryableMutableStore<User> store = storeTestBuilder.withIds("42");
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
assertThat(store.get("tricia")).isNotNull();
|
assertThat(store.get("tricia")).isNotNull();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import sonia.scm.store.Operator;
|
|||||||
import sonia.scm.store.QueryableMaintenanceStore;
|
import sonia.scm.store.QueryableMaintenanceStore;
|
||||||
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceIterator;
|
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceIterator;
|
||||||
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceStoreEntry;
|
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceStoreEntry;
|
||||||
|
import sonia.scm.store.QueryableMutableStore;
|
||||||
import sonia.scm.store.QueryableStore;
|
import sonia.scm.store.QueryableStore;
|
||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = {"*Of*", "Heart*Gold", "H*", "*d", "*Heart Of Gold*", "Heart Of Gold", "Heart Of *Gold"})
|
@ValueSource(strings = {"*Of*", "Heart*Gold", "H*", "*d", "*Heart Of Gold*", "Heart Of Gold", "Heart Of *Gold"})
|
||||||
void shouldWorkWithLikes(String searchString) {
|
void shouldWorkWithLikes(String searchString) {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
||||||
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = {"Of", "*of*", "heart of gold"})
|
@ValueSource(strings = {"Of", "*of*", "heart of gold"})
|
||||||
void shouldNotFindNotMatchingValuesWithLike() {
|
void shouldNotFindNotMatchingValuesWithLike() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
||||||
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldWorkWithEnums() {
|
void shouldWorkWithEnums() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
|
||||||
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldWorkWithLongs() {
|
void shouldWorkWithLongs() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
||||||
trillian.setCreationDate(10000000000L);
|
trillian.setCreationDate(10000000000L);
|
||||||
store.put(trillian);
|
store.put(trillian);
|
||||||
@@ -134,7 +135,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldWorkWithIntegers() {
|
void shouldWorkWithIntegers() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
||||||
trillian.setCreationDate(42L);
|
trillian.setCreationDate(42L);
|
||||||
store.put(trillian);
|
store.put(trillian);
|
||||||
@@ -154,7 +155,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldWorkWithNumberCollection() {
|
void shouldWorkWithNumberCollection() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
||||||
trillian.setActive(true);
|
trillian.setActive(true);
|
||||||
store.put(trillian);
|
store.put(trillian);
|
||||||
@@ -174,7 +175,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCountAndWorkWithNumberCollection() {
|
void shouldCountAndWorkWithNumberCollection() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
|
||||||
trillian.setActive(true);
|
trillian.setActive(true);
|
||||||
store.put(trillian);
|
store.put(trillian);
|
||||||
@@ -197,7 +198,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleCollections() {
|
void shouldHandleCollections() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
||||||
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
||||||
|
|
||||||
@@ -210,7 +211,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCountAndHandleCollections() {
|
void shouldCountAndHandleCollections() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
||||||
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCountWithoutConditions() {
|
void shouldCountWithoutConditions() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
||||||
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleEmptyCollectionWithMaxString() {
|
void shouldHandleEmptyCollectionWithMaxString() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
Integer result = store.query().max(
|
Integer result = store.query().max(
|
||||||
SPACESHIP_FLIGHT_COUNT
|
SPACESHIP_FLIGHT_COUNT
|
||||||
);
|
);
|
||||||
@@ -245,7 +246,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
@Nested
|
@Nested
|
||||||
class ForAggregations {
|
class ForAggregations {
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<Spaceship> store;
|
QueryableMutableStore<Spaceship> store;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void createData() {
|
void createData() {
|
||||||
@@ -318,7 +319,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleCollectionSize() {
|
void shouldHandleCollectionSize() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
|
||||||
store.put(new Spaceship("Heart of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
store.put(new Spaceship("Heart of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
|
||||||
store.put(new Spaceship("MillenniumFalcon"));
|
store.put(new Spaceship("MillenniumFalcon"));
|
||||||
@@ -345,7 +346,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleMap() {
|
void shouldHandleMap() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
||||||
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
|
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
|
||||||
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
|
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
|
||||||
@@ -365,7 +366,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCountAndHandleMap() {
|
void shouldCountAndHandleMap() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
||||||
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
|
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
|
||||||
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
|
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
|
||||||
@@ -386,7 +387,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleMapSize() {
|
void shouldHandleMapSize() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
|
||||||
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true, "dagobah", true)));
|
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true, "dagobah", true)));
|
||||||
store.put(new Spaceship("MillenniumFalcon", Map.of()));
|
store.put(new Spaceship("MillenniumFalcon", Map.of()));
|
||||||
@@ -413,7 +414,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRetrieveTime() {
|
void shouldRetrieveTime() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
Spaceship spaceshuttle = new Spaceship("Spaceshuttle", Range.SOLAR_SYSTEM);
|
Spaceship spaceshuttle = new Spaceship("Spaceshuttle", Range.SOLAR_SYSTEM);
|
||||||
spaceshuttle.setInServiceSince(Instant.parse("1981-04-12T10:00:00Z"));
|
spaceshuttle.setInServiceSince(Instant.parse("1981-04-12T10:00:00Z"));
|
||||||
store.put(spaceshuttle);
|
store.put(spaceshuttle);
|
||||||
@@ -445,7 +446,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldLimitQuery() {
|
void shouldLimitQuery() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
||||||
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
||||||
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
|
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
|
||||||
@@ -461,7 +462,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldOrderResults() {
|
void shouldOrderResults() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
||||||
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
||||||
store.put(new User("zaphod", "Beeblebrox Head 1", "zaphod1@hog.org"));
|
store.put(new User("zaphod", "Beeblebrox Head 1", "zaphod1@hog.org"));
|
||||||
@@ -480,7 +481,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldOrderResultsAsNumbers() {
|
void shouldOrderResultsAsNumbers() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("1"));
|
store.put(new User("1"));
|
||||||
store.put(new User("2"));
|
store.put(new User("2"));
|
||||||
store.put(new User("10"));
|
store.put(new User("10"));
|
||||||
@@ -498,7 +499,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldOrderResultsAsStrings() {
|
void shouldOrderResultsAsStrings() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("1"));
|
store.put(new User("1"));
|
||||||
store.put(new User("2"));
|
store.put(new User("2"));
|
||||||
store.put(new User("10"));
|
store.put(new User("10"));
|
||||||
@@ -519,7 +520,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
class QueryLogicalHandling {
|
class QueryLogicalHandling {
|
||||||
@Test
|
@Test
|
||||||
void shouldQueryForId() {
|
void shouldQueryForId() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -536,7 +537,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldQueryForIdAndOrderByDESC() {
|
void shouldQueryForIdAndOrderByDESC() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
|
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
|
||||||
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -551,7 +552,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldOrderIdsAndPayload() {
|
void shouldOrderIdsAndPayload() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
|
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
|
||||||
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("3", new User("trillian", "Arthur Dent", "arthur@hog.org"));
|
store.put("3", new User("trillian", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -576,7 +577,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
.withIds("1337")
|
.withIds("1337")
|
||||||
.put("tricia", new User("trillian", "Trillian McMillan", "tricia@hog.org"));
|
.put("tricia", new User("trillian", "Trillian McMillan", "tricia@hog.org"));
|
||||||
|
|
||||||
SQLiteQueryableStore<User> store = new StoreTestBuilder(connectionString, Group.class.getName()).withIds();
|
QueryableStore<User> store = new StoreTestBuilder(connectionString, Group.class.getName()).withIds();
|
||||||
|
|
||||||
List<User> all = store.query(
|
List<User> all = store.query(
|
||||||
GROUP.eq("42")
|
GROUP.eq("42")
|
||||||
@@ -590,7 +591,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleContainsCondition() {
|
void shouldHandleContainsCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -605,7 +606,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleIsNullCondition() {
|
void shouldHandleIsNullCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
|
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
|
||||||
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
|
|
||||||
@@ -621,7 +622,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleNotNullCondition() {
|
void shouldHandleNotNullCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
|
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
|
||||||
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
|
|
||||||
@@ -637,7 +638,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleOr() {
|
void shouldHandleOr() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -658,7 +659,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleOrWithMultipleStores() {
|
void shouldHandleOrWithMultipleStores() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
|
||||||
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
|
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
|
||||||
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
||||||
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
|
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
|
||||||
@@ -666,7 +667,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
store.put("McMillan", mcmillan);
|
store.put("McMillan", mcmillan);
|
||||||
store.put("dent", dent);
|
store.put("dent", dent);
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> parallelStore = new StoreTestBuilder(connectionString, "sonia.Group").withIds("LameGroup");
|
QueryableMutableStore<User> parallelStore = new StoreTestBuilder(connectionString, "sonia.Group").withIds("LameGroup");
|
||||||
parallelStore.put("tricia", new User("trillian", "Trillian IAMINAPARALLELSTORE McMillan", "mcmillan@gmail.com"));
|
parallelStore.put("tricia", new User("trillian", "Trillian IAMINAPARALLELSTORE McMillan", "mcmillan@gmail.com"));
|
||||||
|
|
||||||
List<User> result = store.query(
|
List<User> result = store.query(
|
||||||
@@ -680,7 +681,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleGroup() {
|
void shouldHandleGroup() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
.withIds("42");
|
.withIds("42");
|
||||||
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
new StoreTestBuilder(connectionString, "sonia.Group")
|
new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
@@ -696,7 +697,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleGroupWithCondition() {
|
void shouldHandleGroupWithCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
.withIds("42");
|
.withIds("42");
|
||||||
store
|
store
|
||||||
.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
@@ -713,7 +714,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldHandleInArrayCondition() {
|
void shouldHandleInArrayCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
|
||||||
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
store.put(new User("arthur", "Dent", "arthur@hog.org"));
|
||||||
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
|
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
|
||||||
@@ -731,7 +732,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindAllObjectsWithoutParentWithoutConditions() {
|
void shouldFindAllObjectsWithoutParentWithoutConditions() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
|
|
||||||
List<User> all = store.query().findAll();
|
List<User> all = store.query().findAll();
|
||||||
@@ -741,7 +742,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindAllObjectsWithoutParentWithCondition() {
|
void shouldFindAllObjectsWithoutParentWithCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian"));
|
store.put("tricia", new User("trillian"));
|
||||||
store.put("dent", new User("arthur"));
|
store.put("dent", new User("arthur"));
|
||||||
|
|
||||||
@@ -751,7 +752,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindAllObjectsWithOneParentAndMultipleConditions() {
|
void shouldFindAllObjectsWithOneParentAndMultipleConditions() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
|
||||||
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
|
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
|
||||||
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
||||||
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
|
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
|
||||||
@@ -770,7 +771,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindAllObjectsWithoutParentWithMultipleConditions() {
|
void shouldFindAllObjectsWithoutParentWithMultipleConditions() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
|
||||||
@@ -786,7 +787,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnIds() {
|
void shouldReturnIds() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, Spaceship.class.getName())
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, Spaceship.class.getName())
|
||||||
.withIds("hog");
|
.withIds("hog");
|
||||||
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
|
|
||||||
@@ -807,13 +808,13 @@ class SQLiteQueryableStoreTest {
|
|||||||
class FindOne {
|
class FindOne {
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnEmptyOptionalIfNoResultFound() {
|
void shouldReturnEmptyOptionalIfNoResultFound() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
assertThat(store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne()).isEmpty();
|
assertThat(store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnOneResultIfOneIsGiven() {
|
void shouldReturnOneResultIfOneIsGiven() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
|
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
|
||||||
store.put(expectedShip);
|
store.put(expectedShip);
|
||||||
Spaceship ship = store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne().get();
|
Spaceship ship = store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne().get();
|
||||||
@@ -823,7 +824,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldThrowErrorIfMoreThanOneResultIsSaved() {
|
void shouldThrowErrorIfMoreThanOneResultIsSaved() {
|
||||||
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
|
||||||
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
|
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
|
||||||
Spaceship localShip = new Spaceship("Heart Of Gold", Range.SOLAR_SYSTEM);
|
Spaceship localShip = new Spaceship("Heart Of Gold", Range.SOLAR_SYSTEM);
|
||||||
store.put(expectedShip);
|
store.put(expectedShip);
|
||||||
@@ -837,7 +838,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
class FindFirst {
|
class FindFirst {
|
||||||
@Test
|
@Test
|
||||||
void shouldFindFirst() {
|
void shouldFindFirst() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User expectedUser = new User("trillian", "Tricia", "tricia@hog.org");
|
User expectedUser = new User("trillian", "Tricia", "tricia@hog.org");
|
||||||
|
|
||||||
store.put("1", expectedUser);
|
store.put("1", expectedUser);
|
||||||
@@ -854,7 +855,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindFirstWithMatchingCondition() {
|
void shouldFindFirstWithMatchingCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan-alternate@gmail.com");
|
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan-alternate@gmail.com");
|
||||||
|
|
||||||
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
|
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
|
||||||
@@ -874,7 +875,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindFirstWithMatchingLogicalCondition() {
|
void shouldFindFirstWithMatchingLogicalCondition() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
||||||
|
|
||||||
store.put("1", new User("trillian-old", "Tricia", "tricia@hog.org"));
|
store.put("1", new User("trillian-old", "Tricia", "tricia@hog.org"));
|
||||||
@@ -900,7 +901,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnEmptyOptionalIfNoResultFound() {
|
void shouldReturnEmptyOptionalIfNoResultFound() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
Optional<User> user = store.query(
|
Optional<User> user = store.query(
|
||||||
USER_NAME.eq("dave")
|
USER_NAME.eq("dave")
|
||||||
)
|
)
|
||||||
@@ -933,7 +934,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnDistinctValuesFromObject() {
|
void shouldReturnDistinctValuesFromObject() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
.withIds();
|
.withIds();
|
||||||
|
|
||||||
List<Object[]> result = store.query().project(USER_NAME).distinct().findAll();
|
List<Object[]> result = store.query().project(USER_NAME).distinct().findAll();
|
||||||
@@ -949,7 +950,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnDistinctParentIds() {
|
void shouldReturnDistinctParentIds() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
.withIds();
|
.withIds();
|
||||||
|
|
||||||
List<Object[]> result = store.query().project(GROUP).distinct().findAll();
|
List<Object[]> result = store.query().project(GROUP).distinct().findAll();
|
||||||
@@ -963,7 +964,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReturnDistinctCount() {
|
void shouldReturnDistinctCount() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
|
||||||
.withIds();
|
.withIds();
|
||||||
|
|
||||||
long count = store.query().project(GROUP).distinct().count();
|
long count = store.query().project(GROUP).distinct().count();
|
||||||
@@ -976,11 +977,12 @@ class SQLiteQueryableStoreTest {
|
|||||||
class ForMaintenance {
|
class ForMaintenance {
|
||||||
@Test
|
@Test
|
||||||
void shouldUpdateRawJson() throws Exception {
|
void shouldUpdateRawJson() throws Exception {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
||||||
store.put("1", user);
|
store.put("1", user);
|
||||||
|
|
||||||
try (MaintenanceIterator<User> iterator = store.iterateAll()) {
|
QueryableMaintenanceStore<User> maintenanceStore = new StoreTestBuilder(connectionString).forMaintenanceWithSubIds();
|
||||||
|
try (MaintenanceIterator<User> iterator = maintenanceStore.iterateAll()) {
|
||||||
assertThat(iterator.hasNext()).isTrue();
|
assertThat(iterator.hasNext()).isTrue();
|
||||||
MaintenanceStoreEntry<User> entry = iterator.next();
|
MaintenanceStoreEntry<User> entry = iterator.next();
|
||||||
assertThat(entry.getId()).isEqualTo("1");
|
assertThat(entry.getId()).isEqualTo("1");
|
||||||
@@ -997,7 +999,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldUpdateRawJsonForItemWithParent() throws Exception {
|
void shouldUpdateRawJsonForItemWithParent() throws Exception {
|
||||||
SQLiteQueryableMutableStore<User> subStore = new StoreTestBuilder(connectionString, Group.class.getName()).withIds("hitchhiker");
|
QueryableMutableStore<User> subStore = new StoreTestBuilder(connectionString, Group.class.getName()).withIds("hitchhiker");
|
||||||
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
|
||||||
subStore.put("1", user);
|
subStore.put("1", user);
|
||||||
|
|
||||||
@@ -1019,11 +1021,12 @@ class SQLiteQueryableStoreTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRemoveFromIteratorWithoutParent() {
|
void shouldRemoveFromIteratorWithoutParent() {
|
||||||
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
|
||||||
store.put(new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
store.put(new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
|
||||||
store.put(new User("dent", "Arthur Dent", "dent@gmail.com"));
|
store.put(new User("dent", "Arthur Dent", "dent@gmail.com"));
|
||||||
|
|
||||||
for (MaintenanceIterator<User> iter = store.iterateAll(); iter.hasNext(); ) {
|
QueryableMaintenanceStore<User> maintenanceStore = new StoreTestBuilder(connectionString).forMaintenanceWithSubIds();
|
||||||
|
for (MaintenanceIterator<User> iter = maintenanceStore.iterateAll(); iter.hasNext(); ) {
|
||||||
MaintenanceStoreEntry<User> next = iter.next();
|
MaintenanceStoreEntry<User> next = iter.next();
|
||||||
if (next.get().getName().equals("dent")) {
|
if (next.get().getName().equals("dent")) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
@@ -1039,11 +1042,11 @@ class SQLiteQueryableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldRemoveFromIteratorWithParents() {
|
void shouldRemoveFromIteratorWithParents() {
|
||||||
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
|
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
|
||||||
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42", "hog");
|
QueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42", "hog");
|
||||||
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
||||||
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> earthStore = testStoreBuilder.withIds("42", "earth");
|
QueryableMutableStore<User> earthStore = testStoreBuilder.withIds("42", "earth");
|
||||||
earthStore.put("dent", new User("dent", "Arthur Dent", "dent@gmail.com"));
|
earthStore.put("dent", new User("dent", "Arthur Dent", "dent@gmail.com"));
|
||||||
|
|
||||||
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
|
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
|
||||||
@@ -1068,7 +1071,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldReadAll() {
|
void shouldReadAll() {
|
||||||
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName());
|
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName());
|
||||||
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
|
QueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
|
||||||
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
||||||
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
||||||
|
|
||||||
@@ -1091,9 +1094,9 @@ class SQLiteQueryableStoreTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldReadAllWithMultipleIds() {
|
void shouldReadAllWithMultipleIds() {
|
||||||
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
|
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
|
||||||
SQLiteQueryableMutableStore<User> store1 = testStoreBuilder.withIds("42", "astronauts");
|
QueryableMutableStore<User> store1 = testStoreBuilder.withIds("42", "astronauts");
|
||||||
store1.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
store1.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
|
||||||
SQLiteQueryableMutableStore<User> store2 = testStoreBuilder.withIds("42", "earthlings");
|
QueryableMutableStore<User> store2 = testStoreBuilder.withIds("42", "earthlings");
|
||||||
store2.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
store2.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
|
||||||
|
|
||||||
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
|
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
|
||||||
@@ -1128,7 +1131,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
|
QueryableMaintenanceStore<User> hogStore = testStoreBuilder.forMaintenanceWithSubIds("42");
|
||||||
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
|
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
|
||||||
assertThat(allValues)
|
assertThat(allValues)
|
||||||
.extracting("value")
|
.extracting("value")
|
||||||
@@ -1147,7 +1150,7 @@ class SQLiteQueryableStoreTest {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
|
QueryableMaintenanceStore<User> hogStore = testStoreBuilder.forMaintenanceWithSubIds("42");
|
||||||
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
|
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
|
||||||
assertThat(allValues)
|
assertThat(allValues)
|
||||||
.extracting("value")
|
.extracting("value")
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import sonia.scm.repository.RepositoryReadOnlyChecker;
|
|||||||
import sonia.scm.security.UUIDKeyGenerator;
|
import sonia.scm.security.UUIDKeyGenerator;
|
||||||
import sonia.scm.store.IdGenerator;
|
import sonia.scm.store.IdGenerator;
|
||||||
import sonia.scm.store.QueryableMaintenanceStore;
|
import sonia.scm.store.QueryableMaintenanceStore;
|
||||||
|
import sonia.scm.store.QueryableMutableStore;
|
||||||
import sonia.scm.store.QueryableStore;
|
import sonia.scm.store.QueryableStore;
|
||||||
import sonia.scm.user.User;
|
import sonia.scm.user.User;
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ class StoreTestBuilder {
|
|||||||
this.parentClasses = parentClasses;
|
this.parentClasses = parentClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteQueryableMutableStore<User> withIds(String... ids) {
|
QueryableMutableStore<User> withIds(String... ids) {
|
||||||
return forClassWithIds(User.class, ids);
|
return forClassWithIds(User.class, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ class StoreTestBuilder {
|
|||||||
return createStoreFactory(User.class).getForMaintenance(User.class, ids);
|
return createStoreFactory(User.class).getForMaintenance(User.class, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
<T> SQLiteQueryableMutableStore<T> forClassWithIds(Class<T> clazz, String... ids) {
|
<T> QueryableMutableStore<T> forClassWithIds(Class<T> clazz, String... ids) {
|
||||||
return createStoreFactory(clazz).getMutable(clazz, ids);
|
return createStoreFactory(clazz).getMutable(clazz, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user