Skip to content

Commit

Permalink
Introduce Configurable CleanupService delay (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
pivovarit authored May 15, 2020
1 parent 777cf55 commit d96a1d4
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import java.util.Properties;

import static com.hazelcast.hibernate.CacheEnvironment.getCacheCleanupInSeconds;

/**
* Abstract superclass of Hazelcast based {@link RegionFactory} implementations
*/
Expand Down Expand Up @@ -91,7 +93,8 @@ public void start(final SessionFactoryOptions options, final Properties properti
}
instance = instanceLoader.loadInstance();
}
cleanupService = new CleanupService(instance.getName());

cleanupService = new CleanupService(instance.getName(), getCacheCleanupInSeconds(properties));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.time.Duration;
import java.util.Properties;

import static java.lang.String.format;

/**
* This class is used to help in setup the internal caches. It searches for configuration files
* and contains all property names for hibernate based configuration properties.
Expand Down Expand Up @@ -76,6 +78,11 @@ public final class CacheEnvironment {
*/
public static final String LOCK_TIMEOUT = "hibernate.cache.hazelcast.lock_timeout";

/**
* Property to configure the fixed delay in seconds between scheduled cache cleanup jobs
*/
public static final String CLEANUP_DELAY = "hibernate.cache.hazelcast.cleanup_delay";

/**
* Property to configure the Hazelcast instance internal name
*/
Expand Down Expand Up @@ -110,6 +117,10 @@ public final class CacheEnvironment {
// one hour in milliseconds
private static final int DEFAULT_CACHE_TIMEOUT = (3600 * 1000);

// one minute in seconds
private static final int DEFAULT_CACHE_CLEANUP_DELAY = 60;


private CacheEnvironment() {
}

Expand All @@ -133,6 +144,19 @@ public static int getDefaultCacheTimeoutInMillis() {
return DEFAULT_CACHE_TIMEOUT;
}

public static int getCacheCleanupInSeconds(final Properties props) {
int delay = DEFAULT_CACHE_CLEANUP_DELAY;
try {
delay = ConfigurationHelper.getInt(CLEANUP_DELAY, props, DEFAULT_CACHE_CLEANUP_DELAY);
} catch (Exception e) {
Logger.getLogger(CacheEnvironment.class).finest(e);
}
if (delay < 0) {
throw new ConfigurationException(format("[%d] is an illegal value for [%s]", delay, CLEANUP_DELAY));
}
return delay;
}

public static Duration getClusterTimeout(final Properties props) {
int timeoutMillis = ConfigurationHelper.getInt(CLUSTER_TIMEOUT, props, Integer.MAX_VALUE);
if (timeoutMillis <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public boolean put(final Object key, final Object value, final long txTimestamp,
public boolean update(final Object key, final Object newValue, final Object newVersion, final SoftLock lock) {
if (lock instanceof MarkerWrapper) {
final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker();
return (Boolean) map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion,
return map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion,
nextMarkerId(), nextTimestamp(hazelcastInstance)));
} else {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,10 @@
*/
public final class CleanupService {

/**
* Default fixed delay in seconds for scheduled job.
*/
private static final long DEFAULT_FIXED_DELAY = 60L;

private final long fixedDelay;
private final String name;
private final ScheduledExecutorService executor;

public CleanupService(final String name) {
this(name, DEFAULT_FIXED_DELAY);
}

/**
* Visible for testing only.
*/
public CleanupService(final String name, final long fixedDelay) {
this.fixedDelay = fixedDelay;
this.name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@
public class RegionFactoryDefaultSlowTest
extends HibernateSlowTestSupport {

private static final int CLEANUP_DELAY = 4;

protected Properties getCacheProperties() {
Properties props = new Properties();
props.setProperty(Environment.CACHE_REGION_FACTORY, HazelcastCacheRegionFactory.class.getName());
props.setProperty(CacheEnvironment.CLEANUP_DELAY, String.valueOf(CLEANUP_DELAY));
return props;
}

Expand All @@ -52,7 +55,6 @@ public void testQueryCacheCleanup() {
MapConfig mapConfig = getHazelcastInstance(sf).getConfig().getMapConfig("org.hibernate.cache.*");
final float baseEvictionRate = 0.2f;
final int numberOfEntities = 100;
final int defaultCleanupPeriod = 60;
final int maxSize = mapConfig.getEvictionConfig().getSize();
final int evictedItemCount = numberOfEntities - maxSize + (int) (maxSize * baseEvictionRate);
insertDummyEntities(numberOfEntities);
Expand All @@ -64,7 +66,7 @@ public void testQueryCacheCleanup() {
assertEquals(numberOfEntities, queryRegion.getCache().size());

await()
.atMost(defaultCleanupPeriod + 1, TimeUnit.SECONDS)
.atMost(CLEANUP_DELAY + 1, TimeUnit.SECONDS)
.until(() -> (numberOfEntities - evictedItemCount) == queryRegion.getCache().size());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import java.util.Properties;

import static com.hazelcast.hibernate.CacheEnvironment.getCacheCleanupInSeconds;

/**
* Abstract superclass of Hazelcast based {@link RegionFactory} implementations
*/
Expand Down Expand Up @@ -91,7 +93,8 @@ public void start(final SessionFactoryOptions options, final Properties properti
}
instance = instanceLoader.loadInstance();
}
cleanupService = new CleanupService(instance.getName());

cleanupService = new CleanupService(instance.getName(), getCacheCleanupInSeconds(properties));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.time.Duration;
import java.util.Properties;

import static java.lang.String.format;

/**
* This class is used to help in setup the internal caches. It searches for configuration files
* and contains all property names for hibernate based configuration properties.
Expand Down Expand Up @@ -76,6 +78,11 @@ public final class CacheEnvironment {
*/
public static final String LOCK_TIMEOUT = "hibernate.cache.hazelcast.lock_timeout";

/**
* Property to configure the fixed delay in seconds between scheduled cache cleanup jobs
*/
public static final String CLEANUP_DELAY = "hibernate.cache.hazelcast.cleanup_delay";

/**
* Property to configure the Hazelcast instance internal name
*/
Expand Down Expand Up @@ -110,6 +117,9 @@ public final class CacheEnvironment {
// one hour in milliseconds
private static final int DEFAULT_CACHE_TIMEOUT = (3600 * 1000);

// one minute in seconds
private static final int DEFAULT_CACHE_CLEANUP_DELAY = 60;

private CacheEnvironment() {
}

Expand All @@ -133,6 +143,19 @@ public static int getDefaultCacheTimeoutInMillis() {
return DEFAULT_CACHE_TIMEOUT;
}

public static int getCacheCleanupInSeconds(final Properties props) {
int delay = DEFAULT_CACHE_CLEANUP_DELAY;
try {
delay = ConfigurationHelper.getInt(CLEANUP_DELAY, props, DEFAULT_CACHE_CLEANUP_DELAY);
} catch (Exception e) {
Logger.getLogger(CacheEnvironment.class).finest(e);
}
if (delay < 0) {
throw new ConfigurationException(format("[%d] is an illegal value for [%s]", delay, CLEANUP_DELAY));
}
return delay;
}

public static Duration getClusterTimeout(final Properties props) {
int timeoutMillis = ConfigurationHelper.getInt(CLUSTER_TIMEOUT, props, Integer.MAX_VALUE);
if (timeoutMillis <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public boolean put(final Object key, final Object value, final long txTimestamp,
public boolean update(final Object key, final Object newValue, final Object newVersion, final SoftLock lock) {
if (lock instanceof MarkerWrapper) {
final ExpiryMarker unwrappedMarker = ((MarkerWrapper) lock).getMarker();
return (Boolean) map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion,
return map.executeOnKey(key, new UpdateEntryProcessor(unwrappedMarker, newValue, newVersion,
nextMarkerId(), nextTimestamp(hazelcastInstance)));
} else {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,10 @@
*/
public final class CleanupService {

/**
* Default fixed delay in seconds for scheduled job.
*/
private static final long DEFAULT_FIXED_DELAY = 60L;

private final long fixedDelay;
private final String name;
private final ScheduledExecutorService executor;

public CleanupService(final String name) {
this(name, DEFAULT_FIXED_DELAY);
}

/**
* Visible for testing only.
*/
public CleanupService(final String name, final long fixedDelay) {
this.fixedDelay = fixedDelay;
this.name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@
public class RegionFactoryDefaultSlowTest
extends HibernateSlowTestSupport {

private static final int CLEANUP_DELAY = 4;

protected Properties getCacheProperties() {
Properties props = new Properties();
props.setProperty(Environment.CACHE_REGION_FACTORY, HazelcastCacheRegionFactory.class.getName());
props.setProperty(CacheEnvironment.CLEANUP_DELAY, String.valueOf(CLEANUP_DELAY));
return props;
}

Expand All @@ -51,7 +54,6 @@ public void testQueryCacheCleanup() {
MapConfig mapConfig = getHazelcastInstance(sf).getConfig().getMapConfig("org.hibernate.cache.*");
final float baseEvictionRate = 0.2f;
final int numberOfEntities = 100;
final int defaultCleanupPeriod = 60;
final int maxSize = mapConfig.getEvictionConfig().getSize();
final int evictedItemCount = numberOfEntities - maxSize + (int) (maxSize * baseEvictionRate);
insertDummyEntities(numberOfEntities);
Expand All @@ -63,7 +65,7 @@ public void testQueryCacheCleanup() {
assertEquals(numberOfEntities, queryRegion.getCache().size());

await()
.atMost(defaultCleanupPeriod + 1, TimeUnit.SECONDS)
.atMost(CLEANUP_DELAY + 1, TimeUnit.SECONDS)
.until(() -> (numberOfEntities - evictedItemCount) == queryRegion.getCache().size());
}

Expand All @@ -76,14 +78,14 @@ public void testUpdateEntity() {
tx.commit();

tx = session.beginTransaction();
DummyEntity ent = (DummyEntity) session.get(DummyEntity.class, dummyId);
DummyEntity ent = session.get(DummyEntity.class, dummyId);
ent.setName("updatedName");
session.update(ent);
tx.commit();
session.close();

session = sf2.openSession();
DummyEntity entity = (DummyEntity) session.get(DummyEntity.class, dummyId);
DummyEntity entity = session.get(DummyEntity.class, dummyId);
assertEquals("updatedName", entity.getName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import java.util.Map;
import java.util.Properties;

import static com.hazelcast.hibernate.CacheEnvironment.HAZELCAST_FACTORY;
import static com.hazelcast.hibernate.CacheEnvironment.getCacheCleanupInSeconds;

/**
* Simple RegionFactory implementation to return Hazelcast based local Region implementations
*/
Expand Down Expand Up @@ -135,7 +138,7 @@ protected void prepareForUse(final SessionFactoryOptions settings, final Map con
if (instance == null || !instance.getLifecycleService().isRunning()) {
final String defaultFactory = DefaultHazelcastInstanceFactory.class.getName();

String factoryName = (String) configValues.get(CacheEnvironment.HAZELCAST_FACTORY);
String factoryName = (String) configValues.get(HAZELCAST_FACTORY);
if (factoryName == null) {
factoryName = defaultFactory;
}
Expand All @@ -150,7 +153,8 @@ protected void prepareForUse(final SessionFactoryOptions settings, final Map con
}
instance = instanceLoader.loadInstance();
}
cleanupService = new CleanupService(instance.getName());

cleanupService = new CleanupService(instance.getName(), getCacheCleanupInSeconds(toProperties(configValues)));
}

@SuppressWarnings("Duplicates")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.hazelcast.hibernate;

import com.hazelcast.logging.Logger;
import org.hibernate.cfg.Environment;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationException;
Expand All @@ -23,6 +24,8 @@
import java.time.Duration;
import java.util.Properties;

import static java.lang.String.format;

/**
* This class is used to help in setup the internal caches. It searches for configuration files
* and contains all property names for hibernate based configuration properties.
Expand Down Expand Up @@ -70,6 +73,11 @@ public final class CacheEnvironment {
*/
public static final String CLUSTER_TIMEOUT = "hibernate.cache.hazelcast.cluster_timeout";

/**
* Property to configure the fixed delay in seconds between scheduled cache cleanup jobs
*/
public static final String CLEANUP_DELAY = "hibernate.cache.hazelcast.cleanup_delay";

/**
* Property to configure the Hazelcast instance internal name
*/
Expand Down Expand Up @@ -101,6 +109,9 @@ public final class CacheEnvironment {
// one hour in milliseconds
private static final int DEFAULT_CACHE_TIMEOUT = (3600 * 1000);

// one minute in seconds
private static final int DEFAULT_CACHE_CLEANUP_DELAY = 60;

private CacheEnvironment() {
}

Expand Down Expand Up @@ -132,6 +143,20 @@ public static Duration getClusterTimeout(final Properties props) {
return Duration.ofMillis(timeoutMillis);
}

public static int getCacheCleanupInSeconds(final Properties props) {
int delay = DEFAULT_CACHE_CLEANUP_DELAY;
try {
delay = ConfigurationHelper.getInt(CLEANUP_DELAY, props, DEFAULT_CACHE_CLEANUP_DELAY);
} catch (Exception e) {
Logger.getLogger(CacheEnvironment.class).finest(e);
}
if (delay < 0) {
throw new ConfigurationException(format("[%d] is an illegal value for [%s]", delay, CLEANUP_DELAY));
}
return delay;
}


public static boolean shutdownOnStop(final Properties props, final boolean defaultValue) {
return ConfigurationHelper.getBoolean(CacheEnvironment.SHUTDOWN_ON_STOP, props, defaultValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,10 @@
*/
public final class CleanupService {

/**
* Default fixed delay in seconds for scheduled job.
*/
private static final long DEFAULT_FIXED_DELAY = 60L;

private final long fixedDelay;
private final String name;
private final ScheduledExecutorService executor;

public CleanupService(final String name) {
this(name, DEFAULT_FIXED_DELAY);
}

/**
* Visible for testing only.
*/
public CleanupService(final String name, final long fixedDelay) {
this.fixedDelay = fixedDelay;
this.name = name;
Expand Down
Loading

0 comments on commit d96a1d4

Please sign in to comment.