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

Commit c7dba4e

Browse files
committed
#286 Adding tests for incremental support
1 parent 9b60f2a commit c7dba4e

File tree

11 files changed

+360
-209
lines changed

11 files changed

+360
-209
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/DefaultAppConfigFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,9 @@ public void initialize() {
627627
});
628628

629629
propertyConsumerMap.put("mlIncremental", (config, prop) -> {
630-
logger.info("Supported resources will only be deployed if their resource files are now or have been modified since the last deployment: " + 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);
631631
config.setIncrementalDeploy(Boolean.parseBoolean(prop));
632-
});
632+
});
633633

634634
propertyConsumerMap.put("mlUpdateMimetypeWhenPropertiesAreEqual", (config, prop) -> {
635635
logger.info("Update mimetype when properties are equal (defaults to false to avoid unnecessary ML restarts): " + prop);

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.springframework.util.FileCopyUtils;
1212

1313
import java.io.File;
14+
import java.io.FilenameFilter;
1415
import java.io.IOException;
1516
import java.net.URI;
1617
import java.util.Arrays;
@@ -28,7 +29,7 @@ public abstract class AbstractCommand extends LoggingObject implements Command {
2829
private boolean storeResourceIdsAsCustomTokens = false;
2930

3031
protected PayloadTokenReplacer payloadTokenReplacer = new DefaultPayloadTokenReplacer();
31-
private IncrementalFilenameFilter resourceFilenameFilter = new ResourceFilenameFilter();
32+
private FilenameFilter resourceFilenameFilter = new ResourceFilenameFilter();
3233
private PayloadParser payloadParser = new PayloadParser();
3334

3435
/**
@@ -280,6 +281,24 @@ protected boolean shouldOptimizeWithCma(CommandContext context) {
280281
return false;
281282
}
282283

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+
283302
public void setPayloadTokenReplacer(PayloadTokenReplacer payloadTokenReplacer) {
284303
this.payloadTokenReplacer = payloadTokenReplacer;
285304
}
@@ -292,15 +311,11 @@ public void setStoreResourceIdsAsCustomTokens(boolean storeResourceIdsAsCustomTo
292311
this.storeResourceIdsAsCustomTokens = storeResourceIdsAsCustomTokens;
293312
}
294313

295-
public void setResourceFilenameFilter(IncrementalFilenameFilter resourceFilenameFilter) {
314+
public void setResourceFilenameFilter(FilenameFilter resourceFilenameFilter) {
296315
this.resourceFilenameFilter = resourceFilenameFilter;
297316
}
298317

299-
protected void ignoreHashForFilename(String filename) {
300-
((ResourceFilenameFilter) resourceFilenameFilter).addFilenameToIgnoreHash(filename);
301-
}
302-
303-
protected void setIncrementalMode(Boolean incrementalMode) {
304-
resourceFilenameFilter.setIncrementalMode(incrementalMode);
318+
public FilenameFilter getResourceFilenameFilter() {
319+
return resourceFilenameFilter;
305320
}
306321
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import com.marklogic.appdeployer.AppConfig;
44
import com.marklogic.appdeployer.ConfigDir;
5-
import com.marklogic.mgmt.resource.ResourceManager;
65
import com.marklogic.mgmt.SaveReceipt;
76
import com.marklogic.mgmt.admin.ActionRequiringRestart;
7+
import com.marklogic.mgmt.resource.ResourceManager;
88

99
import java.io.File;
1010
import java.util.ArrayList;
@@ -26,7 +26,7 @@ public abstract class AbstractResourceCommand extends AbstractUndoableCommand {
2626

2727
@Override
2828
public void execute(CommandContext context) {
29-
setIncrementalMode(context.getAppConfig().isIncrementalDeploy());
29+
setIncrementalMode(context.getAppConfig().isIncrementalDeploy());
3030
for (File resourceDir : getResourceDirs(context)) {
3131
processExecuteOnResourceDir(context, resourceDir);
3232
}
@@ -96,8 +96,8 @@ protected File[] listFilesInDirectory(File resourceDir, CommandContext context)
9696

9797
@Override
9898
public void undo(CommandContext context) {
99-
setIncrementalMode(false);
100-
if (deleteResourcesOnUndo) {
99+
if (deleteResourcesOnUndo) {
100+
setIncrementalMode(false);
101101
for (File resourceDir : getResourceDirs(context)) {
102102
processUndoOnResourceDir(context, resourceDir);
103103
}
Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
package com.marklogic.appdeployer.command;
22

3+
import java.io.File;
34
import java.io.FilenameFilter;
45

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+
*/
510
public interface IncrementalFilenameFilter extends FilenameFilter {
611

7-
public void addFilenameToIgnoreHash(String filename);
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);
819

9-
public void clearFilenamesToIgnoreHash();
10-
11-
public void setIncrementalMode(boolean incrementalMode);
20+
/**
21+
* Toggle whether this file performs any incremental check.
22+
*
23+
* @param incrementalMode
24+
*/
25+
void setIncrementalMode(boolean incrementalMode);
1226
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
import java.io.File;
44

55
/**
6-
* Defines operations for whether a resource file should be deployed or not.
6+
* Defines operations for whether a resource file should be processed or not during a deployment.
77
*/
88
public interface ResourceFileManager {
99

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();
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();
1414

15-
boolean hasFileBeenModifiedSinceLastDeployed(File file);
16-
17-
void saveLastDeployedHash(File file);
15+
/**
16+
* @param file
17+
* @return
18+
*/
19+
boolean shouldResourceFileBeProcessed(File file);
1820
}
Lines changed: 28 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,51 @@
11
package com.marklogic.appdeployer.command;
22

3-
import com.marklogic.client.ext.helper.LoggingObject;
3+
import com.marklogic.client.ext.modulesloader.impl.PropertiesModuleManager;
44

55
import java.io.File;
6-
import java.io.FileInputStream;
7-
import java.io.FileWriter;
8-
import java.util.Properties;
6+
import java.util.Date;
97

108
/**
11-
* Defines operations for managing whether a module needs to be installed or not.
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.
1211
*/
13-
public class ResourceFileManagerImpl extends LoggingObject implements ResourceFileManager {
12+
public class ResourceFileManagerImpl extends PropertiesModuleManager implements ResourceFileManager {
1413

15-
public static final String DEFAULT_FILE_PATH = "build/ml-gradle/resource-timestamps.properties";
16-
17-
private Properties props;
18-
private String propertiesFilePath;
14+
public static final String DEFAULT_FILE_PATH = "build/com.marklogic.ml-app-deployer/resource-timestamps.properties";
1915

2016
public ResourceFileManagerImpl() {
2117
this(DEFAULT_FILE_PATH);
2218
}
2319

2420
public ResourceFileManagerImpl(String propertiesFilePath) {
25-
props = new Properties();
26-
this.propertiesFilePath = propertiesFilePath;
27-
initialize();
28-
}
29-
30-
@Override
31-
public void initialize() {
32-
File propertiesFile = new File(propertiesFilePath);
33-
logger.info("Loading properties from: " + propertiesFile.getAbsolutePath());
34-
propertiesFile.getParentFile().mkdirs();
35-
if (propertiesFile.exists()) {
36-
FileInputStream fis = null;
37-
try {
38-
fis = new FileInputStream(propertiesFile);
39-
if (logger.isDebugEnabled()) {
40-
logger.debug("Loading properties from: " + propertiesFile.getAbsolutePath());
41-
}
42-
props.load(fis);
43-
} catch (Exception e) {
44-
logger.warn("Unable to load properties, cause: " + e.getMessage());
45-
} finally {
46-
try {
47-
fis.close();
48-
} catch (Exception e) {
49-
logger.warn(e.getMessage());
50-
}
51-
}
52-
}
53-
}
54-
55-
@Override
56-
public boolean hasFileBeenModifiedSinceLastDeployed(File file) {
57-
String key = buildKey(file);
58-
Long lastFileTimestamp = file.lastModified();
59-
String lastDeployedTimestampPropertyValue = props.getProperty(key);
60-
if (lastDeployedTimestampPropertyValue != null) {
61-
Long lastDeployedTimestamp = null;
62-
try {
63-
lastDeployedTimestamp = Long.parseLong(lastDeployedTimestampPropertyValue);
64-
} catch (Exception e) {}
65-
if (lastDeployedTimestamp != null) {
66-
if (logger.isDebugEnabled()) {
67-
logger.debug("lastDeployedTimestamp: " + lastDeployedTimestamp);
68-
logger.debug("key: " + key);
69-
logger.debug("lastFileTimestamp: " + lastFileTimestamp);
70-
}
71-
if (lastFileTimestamp != null) {
72-
return (lastFileTimestamp > lastDeployedTimestamp);
73-
} else {
74-
return true;
75-
}
76-
} else {
77-
return true;
78-
}
79-
} else {
80-
return true;
81-
}
82-
}
83-
84-
@Override
85-
public void saveLastDeployedHash(File file) {
86-
String key = buildKey(file);
87-
props.setProperty(key, file.lastModified() + "");
88-
FileWriter fw = null;
89-
try {
90-
fw = new FileWriter(new File(propertiesFilePath));
91-
props.store(fw, "");
92-
} catch (Exception e) {
93-
logger.warn("Unable to store properties, cause: " + e.getMessage());
94-
} finally {
95-
try {
96-
fw.close();
97-
} catch (Exception e) {
98-
logger.warn(e.getMessage());
99-
}
100-
}
21+
super(propertiesFilePath);
10122
}
10223

10324
/**
104-
* Lower-casing avoids some annoying issues on Windows where sometimes you get "C:" at the start, and other times
105-
* you get "c:". This of course will be a problem if you for some reason have modules with the same names but
106-
* differing in some cases, but I'm not sure why anyone would do that.
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.
10733
*
10834
* @param file
10935
* @return
11036
*/
111-
protected String buildKey(File file) {
112-
return file.getAbsolutePath().toLowerCase();
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;
11349
}
50+
11451
}

0 commit comments

Comments
 (0)