diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java index 3e42324bfd..694aaedff5 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Configuration.java @@ -183,6 +183,12 @@ import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreBuilde " seconds.") long versionGCTimeLimitInSecs() default DocumentNodeStoreService.DEFAULT_RGC_TIME_LIMIT_SECS; + @AttributeDefinition( + name = "Delay factor for a Version GC run", + description = "A Version GC run has a gap of this delay factor to reduce continuous load on system" + + "The default value is " + DocumentNodeStoreService.DEFAULT_RGC_DELAY_FACTOR) + double versionGCDelayFactor() default DocumentNodeStoreService.DEFAULT_RGC_DELAY_FACTOR; + @AttributeDefinition( name = "Blob GC Max Age (in secs)", description = "Blob Garbage Collector (GC) logic will only consider those blobs for GC which " + diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java index a3115eea78..8d19bb15c6 100644 --- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java +++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreService.java @@ -139,6 +139,7 @@ public class DocumentNodeStoreService { public static final String CONTINUOUS_RGC_EXPR = "*/5 * * * * ?"; public static final String CLASSIC_RGC_EXPR = "0 0 2 * * ?"; public static final long DEFAULT_RGC_TIME_LIMIT_SECS = 3*60*60; // default is 3 hours + public static final double DEFAULT_RGC_DELAY_FACTOR = 0; private static final String DESCRIPTION = "oak.nodestore.description"; static final long DEFAULT_JOURNAL_GC_INTERVAL_MILLIS = 5*60*1000; // default is 5min static final long DEFAULT_JOURNAL_GC_MAX_AGE_MILLIS = 24*60*60*1000; // default is 24hours @@ -758,7 +759,7 @@ public class DocumentNodeStoreService { BlobGCMBean.TYPE, "Document node store blob garbage collection")); } - Runnable startGC = new RevisionGCJob(store, versionGcMaxAgeInSecs, 0); + Runnable startGC = new RevisionGCJob(store, versionGcMaxAgeInSecs, 0, 0); Runnable cancelGC = () -> store.getVersionGarbageCollector().cancel(); Supplier status = () -> store.getVersionGarbageCollector().getStatus(); RevisionGC revisionGC = new RevisionGC(startGC, cancelGC, status, executor); @@ -818,9 +819,10 @@ public class DocumentNodeStoreService { props.put("scheduler.expression", expr); long versionGcMaxAgeInSecs = config.versionGcMaxAgeInSecs(); long versionGCTimeLimitInSecs = config.versionGCTimeLimitInSecs(); + double versionGCDelayFactor = config.versionGCDelayFactor(); addRegistration(scheduleWithFixedDelay(whiteboard, new RevisionGCJob(nodeStore, versionGcMaxAgeInSecs, - versionGCTimeLimitInSecs), + versionGCTimeLimitInSecs, versionGCDelayFactor), props, MODIFIED_IN_SECS_RESOLUTION, true, true)); } @@ -900,23 +902,26 @@ public class DocumentNodeStoreService { private final DocumentNodeStore nodeStore; private final long versionGCMaxAgeInSecs; private final long versionGCTimeLimitInSecs; + private final double versionGCDelayFactor; private volatile Object lastResult = ""; private long lastLogTime; private VersionGCStats stats; RevisionGCJob(DocumentNodeStore ns, long versionGcMaxAgeInSecs, - long versionGCTimeLimitInSecs) { + long versionGCTimeLimitInSecs, + double versionGCDelayFactor) { this.nodeStore = ns; this.versionGCMaxAgeInSecs = versionGcMaxAgeInSecs; this.versionGCTimeLimitInSecs = versionGCTimeLimitInSecs; + this.versionGCDelayFactor = versionGCDelayFactor; resetStats(); } @Override public void run() { VersionGarbageCollector gc = nodeStore.getVersionGarbageCollector(); - gc.setOptions(gc.getOptions().withMaxDuration(TimeUnit.SECONDS, versionGCTimeLimitInSecs)); + gc.setOptions(gc.getOptions().withMaxDuration(TimeUnit.SECONDS, versionGCTimeLimitInSecs).withDelayFactor(versionGCDelayFactor)); try { VersionGCStats s = gc.gc(versionGCMaxAgeInSecs, TimeUnit.SECONDS); stats.addRun(s);