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

Commit a968215

Browse files
committed
#311 Can now deploy and undeploy tasks with the same task-path
1 parent 779aef8 commit a968215

File tree

5 files changed

+162
-15
lines changed

5 files changed

+162
-15
lines changed

src/main/java/com/marklogic/mgmt/api/task/Task.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,63 @@
77
import com.marklogic.mgmt.api.group.Group;
88
import com.marklogic.mgmt.resource.tasks.TaskManager;
99

10+
import javax.xml.bind.annotation.*;
1011
import java.util.List;
1112

13+
@XmlRootElement(name = "task-properties")
14+
@XmlAccessorType(XmlAccessType.FIELD)
1215
public class Task extends Resource {
1316

17+
@XmlElement(name = "group-name")
1418
private String groupName = Group.DEFAULT_GROUP_NAME;
1519

20+
@XmlElement(name = "task-id")
1621
private String taskId;
22+
23+
@XmlElement(name = "task-enabled")
1724
private Boolean taskEnabled;
25+
26+
@XmlElement(name = "task-path")
1827
private String taskPath;
28+
29+
@XmlElement(name = "task-root")
1930
private String taskRoot;
31+
32+
@XmlElement(name = "task-type")
2033
private String taskType;
34+
35+
@XmlElement(name = "task-period")
2136
private Integer taskPeriod;
37+
38+
@XmlElement(name = "task-month-day")
2239
private Integer taskMonthDay;
40+
41+
@XmlElementWrapper(name = "task-days")
42+
@XmlElement(name = "task-day")
2343
private List<String> taskDay;
44+
45+
@XmlElement(name = "task-start-date")
2446
private String taskStartDate;
47+
48+
@XmlElement(name = "task-start-time")
2549
private String taskStartTime;
50+
51+
@XmlElement(name = "task-timestamp")
2652
private String taskTimestamp;
53+
54+
@XmlElement(name = "task-database")
2755
private String taskDatabase;
56+
57+
@XmlElement(name = "task-modules")
2858
private String taskModules;
59+
60+
@XmlElement(name = "task-user")
2961
private String taskUser;
62+
63+
@XmlElement(name = "task-host")
3064
private String taskHost;
65+
66+
@XmlElement(name = "task-priority")
3167
private String taskPriority;
3268

3369
public Task() {

src/main/java/com/marklogic/mgmt/resource/tasks/TaskManager.java

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package com.marklogic.mgmt.resource.tasks;
22

3-
import com.marklogic.mgmt.resource.AbstractResourceManager;
43
import com.marklogic.mgmt.ManageClient;
4+
import com.marklogic.mgmt.SaveReceipt;
5+
import com.marklogic.mgmt.resource.AbstractResourceManager;
56
import com.marklogic.mgmt.resource.requests.RequestManager;
67
import com.marklogic.rest.util.Fragment;
78

89
import java.util.ArrayList;
910
import java.util.List;
1011

1112
/**
12-
* A scheduled task doesn't have a name, and the ID is generated by ML, so this class assumes that task-path will be
13-
* unique and can thus be used as a way to find an existing task.
14-
*
15-
* Note that the "groupName" property of this class corresponds to the "group-id" querystring parameter. It's called
13+
* The "groupName" property of this class corresponds to the "group-id" querystring parameter. It's called
1614
* "groupName" because "group-id" is misleading - it's a name, not an ID.
1715
*/
1816
public class TaskManager extends AbstractResourceManager {
@@ -28,6 +26,32 @@ public TaskManager(ManageClient client, String groupName) {
2826
this.groupName = groupName;
2927
}
3028

29+
/**
30+
* Tasks are tricky because their unique field is "task-id", but that's generated by MarkLogic - it's not expected
31+
* to be in a payload. So this method has to do some extra work to determine what the task-id is for the given
32+
* payload. It does so by looking for an existing task with the same task-path and task-database as what's in the
33+
* given payload. If one exists, then the task-id from the existing task is used. Otherwise, null is returned.
34+
*
35+
* @param payload
36+
* @return
37+
*/
38+
@Override
39+
protected String getResourceId(String payload) {
40+
final String taskId = payloadParser.getPayloadFieldValue(payload, "task-id", false);
41+
if (taskId != null) {
42+
return taskId;
43+
}
44+
45+
final String taskPath = payloadParser.getPayloadFieldValue(payload, "task-path");
46+
final String taskDatabase = payloadParser.getPayloadFieldValue(payload, "task-database", false);
47+
48+
final String xpath = taskDatabase != null ?
49+
format("/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' and t:task-database = '%s']/t:idref", taskPath, taskDatabase) :
50+
format("/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s']/t:idref", taskPath);
51+
52+
return getAsXml().getElementValue(xpath);
53+
}
54+
3155
@Override
3256
public String getResourcesPath() {
3357
return appendGroupId(super.getResourcesPath());
@@ -58,30 +82,60 @@ protected String[] getUpdateResourceParams(String payload) {
5882

5983
@Override
6084
protected String getIdFieldName() {
61-
return "task-path";
62-
}
63-
64-
public String getTaskIdForTaskPath(String taskPath) {
85+
return "task-id";
86+
}
87+
88+
/**
89+
* Previously, this method only accepted a task-path because that was previously used as the unique ID for a task.
90+
* But since two or more tasks can have the same task-path, this class now uses task-id. To preserve backwards
91+
* compatibility then, this method accepts a task-path or a task-id.
92+
*
93+
* @param taskPathOrTaskId
94+
* @return
95+
*/
96+
public String getTaskIdForTaskPath(String taskPathOrTaskId) {
6597
Fragment f = getAsXml();
66-
String xpath = "/node()/*[local-name(.) = 'list-items']/node()"
67-
+ "[*[local-name(.) = 'task-path'] = '%s']/*[local-name(.) = 'idref']";
68-
xpath = String.format(xpath, taskPath);
98+
String xpath = "/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' or t:idref = '%s']/t:idref";
99+
xpath = String.format(xpath, taskPathOrTaskId, taskPathOrTaskId);
69100
String id = f.getElementValue(xpath);
70101
if (id == null) {
71-
throw new RuntimeException("Could not find a scheduled task with a task-path of: " + taskPath);
102+
throw new RuntimeException("Could not find a scheduled task with a task-path or task-id of: " + taskPathOrTaskId);
72103
}
73104
return id;
74105
}
75106

107+
/**
108+
* This accounts for an existing task with either task-path or task-id equal to the given resourceNameOrId.
109+
* This preserves backwards compatibility to when this class used task-path as the ID property.
110+
*
111+
* @param resourceNameOrId
112+
* @param resourceUrlParams
113+
* @return
114+
*/
76115
@Override
77116
public boolean exists(String resourceNameOrId, String... resourceUrlParams) {
78117
if (logger.isInfoEnabled()) {
79118
logger.info("Checking for existence of resource: " + resourceNameOrId);
80119
}
81120
Fragment f = getAsXml();
82121
return f.elementExists(format(
83-
"/node()/*[local-name(.) = 'list-items']/node()[*[local-name(.) = 'task-path'] = '%s']",
84-
resourceNameOrId));
122+
"/t:tasks-default-list/t:list-items/t:list-item[t:task-path = '%s' or t:idref = '%s']",
123+
resourceNameOrId, resourceNameOrId));
124+
}
125+
126+
/**
127+
* When a task is being created, its resourceId - its task-id - will always be null because MarkLogic generates it.
128+
* This method only needs the resourceId for logging purposes. So it's overridden so that the task-path can be used
129+
* as the resourceId so that the logging is more useful.
130+
*
131+
* @param payload
132+
* @param resourceId
133+
* @return
134+
*/
135+
@Override
136+
protected SaveReceipt createNewResource(String payload, String resourceId) {
137+
final String taskPath = payloadParser.getPayloadFieldValue(payload, "task-path", false);
138+
return super.createNewResource(payload, taskPath);
85139
}
86140

87141
public List<String> getTaskPaths() {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.marklogic.appdeployer.command.tasks;
2+
3+
import com.marklogic.appdeployer.AbstractAppDeployerTest;
4+
import com.marklogic.mgmt.resource.tasks.TaskManager;
5+
import org.junit.Test;
6+
7+
import java.io.File;
8+
9+
public class DeployTasksWithSamePathTest extends AbstractAppDeployerTest {
10+
11+
@Test
12+
public void test() {
13+
appConfig.getFirstConfigDir().setBaseDir(new File("src/test/resources/sample-app/tasks-with-same-path"));
14+
initializeAppDeployer(new DeployScheduledTasksCommand());
15+
16+
new TaskManager(manageClient).deleteAllScheduledTasks();
17+
18+
TaskManager taskManager = new TaskManager(manageClient);
19+
final int initialTaskCount = taskManager.getAsXml().getResourceCount();
20+
21+
try {
22+
deploySampleApp();
23+
assertEquals("There should be 2 new tasks", initialTaskCount + 2, taskManager.getAsXml().getResourceCount());
24+
25+
deploySampleApp();
26+
assertEquals("There should still be just 2 new tasks", initialTaskCount + 2, taskManager.getAsXml().getResourceCount());
27+
} finally {
28+
undeploySampleApp();
29+
30+
assertEquals("The 2 new tasks should have been deleted", initialTaskCount, taskManager.getAsXml().getResourceCount());
31+
}
32+
}
33+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"task-enabled":true,
3+
"task-path":"/path/to/query.xqy",
4+
"task-root":"/",
5+
"task-type":"weekly",
6+
"task-period":2,
7+
"task-day":["tuesday"],
8+
"task-start-time":"12:00:00",
9+
"task-database":"Documents",
10+
"task-modules":"",
11+
"task-user":"nobody"
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"task-enabled":true,
3+
"task-path":"/path/to/query.xqy",
4+
"task-root":"/",
5+
"task-type":"weekly",
6+
"task-period":2,
7+
"task-day":["tuesday"],
8+
"task-start-time":"12:00:00",
9+
"task-database":"Modules",
10+
"task-modules":"",
11+
"task-user":"nobody"
12+
}

0 commit comments

Comments
 (0)