Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit f61cb3f

Browse files
authored
Merge pull request #306 from marklogic-community/feature/286-billfarber
Adding support for Gradle-style incremental deployments
2 parents 90c4cd5 + c7dba4e commit f61cb3f

File tree

12 files changed

+445
-70
lines changed

12 files changed

+445
-70
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
group=com.marklogic
22
javadocsDir=../gh-pages-marklogic-java/javadocs
3-
version=3.9.0
3+
version=3.10.dev
44
mlJavaclientUtilVersion=3.8.1
55
mlJunitVersion=3.1.0
66

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public class AppConfig {
121121
private String deleteTestModulesPattern = "/test/**";
122122
private int modulesLoaderThreadCount = 4;
123123
private Integer modulesLoaderBatchSize;
124+
private boolean incrementalDeploy = false;
124125

125126
private String schemasPath;
126127

@@ -1184,6 +1185,14 @@ public void setModulesLoaderBatchSize(Integer modulesLoaderBatchSize) {
11841185
this.modulesLoaderBatchSize = modulesLoaderBatchSize;
11851186
}
11861187

1188+
public boolean isIncrementalDeploy() {
1189+
return incrementalDeploy;
1190+
}
1191+
1192+
public void setIncrementalDeploy(boolean incrementalDeploy) {
1193+
this.incrementalDeploy = incrementalDeploy;
1194+
}
1195+
11871196
public String getModelsDatabase() {
11881197
return modelsDatabase;
11891198
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,11 @@ public void initialize() {
626626
config.setIncludeProperties(values);
627627
});
628628

629+
propertyConsumerMap.put("mlIncremental", (config, prop) -> {
630+
logger.info("Supported resources will only be deployed if their resource files are new or have been modified since the last deployment: " + prop);
631+
config.setIncrementalDeploy(Boolean.parseBoolean(prop));
632+
});
633+
629634
propertyConsumerMap.put("mlUpdateMimetypeWhenPropertiesAreEqual", (config, prop) -> {
630635
logger.info("Update mimetype when properties are equal (defaults to false to avoid unnecessary ML restarts): " + prop);
631636
config.setUpdateMimetypeWhenPropertiesAreEqual(Boolean.parseBoolean(prop));

src/main/java/com/marklogic/appdeployer/command/AbstractCommand.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.net.URI;
1717
import java.util.Arrays;
1818
import java.util.HashSet;
19-
import java.util.Map;
2019
import java.util.Set;
2120
import java.util.regex.Pattern;
2221

@@ -282,6 +281,24 @@ protected boolean shouldOptimizeWithCma(CommandContext context) {
282281
return false;
283282
}
284283

284+
protected void ignoreIncrementalCheckForFile(File file) {
285+
if (resourceFilenameFilter instanceof IncrementalFilenameFilter) {
286+
((IncrementalFilenameFilter) resourceFilenameFilter).ignoreIncrementalCheckForFile(file);
287+
} else {
288+
logger.warn("resourceFilenameFilter does not implement " + IncrementalFilenameFilter.class.getName() + ", and thus " +
289+
"ignoreIncrementalCheckForFile for file " + file.getAbsolutePath() + " cannot be invoked");
290+
}
291+
}
292+
293+
protected void setIncrementalMode(boolean incrementalMode) {
294+
if (resourceFilenameFilter instanceof IncrementalFilenameFilter) {
295+
((IncrementalFilenameFilter) resourceFilenameFilter).setIncrementalMode(incrementalMode);
296+
} else {
297+
logger.warn("resourceFilenameFilter does not implement " + IncrementalFilenameFilter.class.getName() + ", and thus " +
298+
"setIncrementalMode cannot be invoked");
299+
}
300+
}
301+
285302
public void setPayloadTokenReplacer(PayloadTokenReplacer payloadTokenReplacer) {
286303
this.payloadTokenReplacer = payloadTokenReplacer;
287304
}
@@ -297,4 +314,8 @@ public void setStoreResourceIdsAsCustomTokens(boolean storeResourceIdsAsCustomTo
297314
public void setResourceFilenameFilter(FilenameFilter resourceFilenameFilter) {
298315
this.resourceFilenameFilter = resourceFilenameFilter;
299316
}
317+
318+
public FilenameFilter getResourceFilenameFilter() {
319+
return resourceFilenameFilter;
320+
}
300321
}

src/main/java/com/marklogic/appdeployer/command/AbstractResourceCommand.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22

33
import com.marklogic.appdeployer.AppConfig;
44
import com.marklogic.appdeployer.ConfigDir;
5-
import com.marklogic.mgmt.admin.AdminManager;
6-
import com.marklogic.mgmt.resource.ResourceManager;
75
import com.marklogic.mgmt.SaveReceipt;
86
import com.marklogic.mgmt.admin.ActionRequiringRestart;
9-
import org.springframework.http.HttpHeaders;
10-
import org.springframework.http.ResponseEntity;
7+
import com.marklogic.mgmt.resource.ResourceManager;
118

129
import java.io.File;
13-
import java.net.URI;
1410
import java.util.ArrayList;
1511
import java.util.List;
1612

@@ -30,6 +26,7 @@ public abstract class AbstractResourceCommand extends AbstractUndoableCommand {
3026

3127
@Override
3228
public void execute(CommandContext context) {
29+
setIncrementalMode(context.getAppConfig().isIncrementalDeploy());
3330
for (File resourceDir : getResourceDirs(context)) {
3431
processExecuteOnResourceDir(context, resourceDir);
3532
}
@@ -100,6 +97,7 @@ protected File[] listFilesInDirectory(File resourceDir, CommandContext context)
10097
@Override
10198
public void undo(CommandContext context) {
10299
if (deleteResourcesOnUndo) {
100+
setIncrementalMode(false);
103101
for (File resourceDir : getResourceDirs(context)) {
104102
processUndoOnResourceDir(context, resourceDir);
105103
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.marklogic.appdeployer.command;
2+
3+
import java.io.File;
4+
import java.io.FilenameFilter;
5+
6+
/**
7+
* Extends FilenameFilter to add support for incremental deployments, where only resources that are new or modified since
8+
* a previous deployment will be deployed.
9+
*/
10+
public interface IncrementalFilenameFilter extends FilenameFilter {
11+
12+
/**
13+
* If the given File is processed during a deployment, do not perform an incremental check on it - i.e. essentially
14+
* act as though incremental mode is disabled.
15+
*
16+
* @param resourceFile
17+
*/
18+
void ignoreIncrementalCheckForFile(File resourceFile);
19+
20+
/**
21+
* Toggle whether this file performs any incremental check.
22+
*
23+
* @param incrementalMode
24+
*/
25+
void setIncrementalMode(boolean incrementalMode);
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.marklogic.appdeployer.command;
2+
3+
import java.io.File;
4+
5+
/**
6+
* Defines operations for whether a resource file should be processed or not during a deployment.
7+
*/
8+
public interface ResourceFileManager {
9+
10+
/**
11+
* Give the implementor a chance to initialize itself - e.g. loading data from a properties file or other resource.
12+
*/
13+
void initialize();
14+
15+
/**
16+
* @param file
17+
* @return
18+
*/
19+
boolean shouldResourceFileBeProcessed(File file);
20+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.marklogic.appdeployer.command;
2+
3+
import com.marklogic.client.ext.modulesloader.impl.PropertiesModuleManager;
4+
5+
import java.io.File;
6+
import java.util.Date;
7+
8+
/**
9+
* Extends the module-specific PropertiesModuleManager, as that class's behavior is exactly what's needed here as well.
10+
* Just uses a different default file path for the properties file that keeps track of timestamps.
11+
*/
12+
public class ResourceFileManagerImpl extends PropertiesModuleManager implements ResourceFileManager {
13+
14+
public static final String DEFAULT_FILE_PATH = "build/com.marklogic.ml-app-deployer/resource-timestamps.properties";
15+
16+
public ResourceFileManagerImpl() {
17+
this(DEFAULT_FILE_PATH);
18+
}
19+
20+
public ResourceFileManagerImpl(String propertiesFilePath) {
21+
super(propertiesFilePath);
22+
}
23+
24+
/**
25+
* One difference between this and the parent class is that if the resource file should be processed, its timestamp
26+
* in the properties file is immediately updated, as opposed to that being done via a separate method.
27+
* <p>
28+
* Note that this doesn't indicate that the resource file was successfully deployed. If an error occurs while
29+
* deploying the resource, it is expected that a developer would then make a change to the resource file. If that
30+
* doesn't occur - e.g. if the failure occurred due to an authentication issue, and thus the resource file doesn't
31+
* have to be changed - the developer would need to turn off incremental support or delete the properties file that
32+
* contains the timestamps.
33+
*
34+
* @param file
35+
* @return
36+
*/
37+
@Override
38+
public boolean shouldResourceFileBeProcessed(File file) {
39+
boolean shouldBeProcessed = hasFileBeenModifiedSinceLastLoaded(file);
40+
if (shouldBeProcessed) {
41+
if (logger.isDebugEnabled()) {
42+
logger.debug("File is new or has been modified: " + file.getAbsolutePath());
43+
}
44+
super.saveLastLoadedTimestamp(file, new Date());
45+
} else if (logger.isInfoEnabled()) {
46+
logger.info("File is neither new nor modified: " + file.getAbsolutePath());
47+
}
48+
return shouldBeProcessed;
49+
}
50+
51+
}

0 commit comments

Comments
 (0)