Skip to content

Commit 8d57ff2

Browse files
committed
fixed #352
fixed #351 fixed #347 fixed #334 fixed #319
1 parent e93ace8 commit 8d57ff2

File tree

128 files changed

+2625
-1582
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+2625
-1582
lines changed

examples/spring-batch/marklogic-config/databases/trace-database.json

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,40 @@
2828
{
2929
"scalar-type": "string",
3030
"namespace-uri": "",
31-
"localname": "traceId",
31+
"localname": "hasError",
3232
"collation": "http://marklogic.com/collation/codepoint",
3333
"range-value-positions": false,
3434
"invalid-values": "reject"
3535
},
3636
{
3737
"scalar-type": "string",
3838
"namespace-uri": "",
39-
"localname": "identifier",
39+
"localname": "flowType",
4040
"collation": "http://marklogic.com/collation/codepoint",
4141
"range-value-positions": false,
4242
"invalid-values": "reject"
4343
},
4444
{
45-
"scalar-type": "unsignedInt",
46-
"namespace-uri": "http://marklogic.com/data-hub/debug",
47-
"localname": "is-debugging-enabled",
48-
"collation": "",
45+
"scalar-type": "string",
46+
"namespace-uri": "",
47+
"localname": "jobId",
48+
"collation": "http://marklogic.com/collation/codepoint",
49+
"range-value-positions": false,
50+
"invalid-values": "reject"
51+
},
52+
{
53+
"scalar-type": "string",
54+
"namespace-uri": "",
55+
"localname": "traceId",
56+
"collation": "http://marklogic.com/collation/codepoint",
57+
"range-value-positions": false,
58+
"invalid-values": "reject"
59+
},
60+
{
61+
"scalar-type": "string",
62+
"namespace-uri": "",
63+
"localname": "identifier",
64+
"collation": "http://marklogic.com/collation/codepoint",
4965
"range-value-positions": false,
5066
"invalid-values": "reject"
5167
},

marklogic-data-hub/build.gradle

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,10 @@ sourceCompatibility = 1.8
1919
targetCompatibility = 1.8
2020

2121
dependencies {
22-
compile 'org.springframework.batch:spring-batch-core:3.0.6.RELEASE'
23-
compile 'org.springframework:spring-jdbc:4.2.6.RELEASE'
24-
compile 'com.marklogic:java-client-api:3.0.5'
22+
compile 'com.marklogic:marklogic-client-api:4.0-SNAPSHOT'
2523
compile 'com.marklogic:ml-javaclient-util:2.10.0'
2624
compile 'com.marklogic:ml-app-deployer:2.4.0'
27-
compile 'com.marklogic:marklogic-spring-batch-core:0.7.0'
2825
compile 'commons-io:commons-io:2.4'
29-
testCompile 'org.springframework.batch:spring-batch-test:3.0.6.RELEASE'
3026
testCompile 'junit:junit:4.12'
3127
testCompile 'xmlunit:xmlunit:1.3'
3228
testCompile 'org.skyscreamer:jsonassert:1.3.0'

marklogic-data-hub/src/main/java/com/marklogic/hub/DataHub.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,15 @@ public void install(HubDeployStatusListener listener) {
516516
deployer.deploy(config);
517517
}
518518

519+
public void updateIndexes() {
520+
AppConfig config = getAppConfig();
521+
HubAppDeployer deployer = new HubAppDeployer(client, adminManager, null);
522+
List<Command> commands = new ArrayList<>();
523+
commands.add(new DeployHubDatabasesCommand(hubConfig));
524+
deployer.setCommands(commands);
525+
deployer.deploy(config);
526+
}
527+
519528
/**
520529
* Uninstalls the data hub configuration and server-side modules from MarkLogic
521530
*/

marklogic-data-hub/src/main/java/com/marklogic/hub/FlowManager.java

Lines changed: 102 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,49 @@
1616
package com.marklogic.hub;
1717

1818
import com.marklogic.client.DatabaseClient;
19-
import com.marklogic.client.DatabaseClientFactory;
19+
import com.marklogic.client.datamovement.DataMovementManager;
20+
import com.marklogic.client.datamovement.JobTicket;
21+
import com.marklogic.client.datamovement.QueryBatcher;
2022
import com.marklogic.client.extensions.ResourceManager;
2123
import com.marklogic.client.extensions.ResourceServices.ServiceResult;
2224
import com.marklogic.client.extensions.ResourceServices.ServiceResultIterator;
2325
import com.marklogic.client.io.DOMHandle;
2426
import com.marklogic.client.util.RequestParameters;
25-
import com.marklogic.hub.flow.Flow;
26-
import com.marklogic.hub.flow.FlowComplexity;
27-
import com.marklogic.hub.flow.FlowType;
28-
import com.marklogic.hub.flow.SimpleFlow;
29-
import com.marklogic.spring.batch.hub.FlowConfig;
30-
import com.marklogic.spring.batch.hub.RunHarmonizeFlowConfig;
31-
import com.marklogic.spring.batch.hub.StagingConfig;
32-
import org.springframework.batch.core.Job;
33-
import org.springframework.batch.core.JobExecution;
34-
import org.springframework.batch.core.JobParameters;
35-
import org.springframework.batch.core.JobParametersBuilder;
36-
import org.springframework.batch.core.launch.JobLauncher;
37-
import org.springframework.context.ConfigurableApplicationContext;
38-
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
27+
import com.marklogic.hub.collector.Collector;
28+
import com.marklogic.hub.collector.ServerCollector;
29+
import com.marklogic.hub.flow.*;
30+
import com.marklogic.hub.job.Job;
31+
import com.marklogic.hub.job.JobManager;
3932
import org.w3c.dom.Document;
4033
import org.w3c.dom.Element;
4134
import org.w3c.dom.Node;
4235
import org.w3c.dom.NodeList;
4336

44-
import java.util.ArrayList;
45-
import java.util.List;
46-
import java.util.UUID;
37+
import java.util.*;
38+
import java.util.concurrent.atomic.AtomicInteger;
39+
import java.util.concurrent.atomic.AtomicLong;
4740

4841
public class FlowManager extends ResourceManager {
4942
private static final String HUB_NS = "http://marklogic.com/data-hub";
5043
private static final String NAME = "flow";
5144

52-
private DatabaseClient client;
45+
private DatabaseClient stagingClient;
46+
private DatabaseClient finalClient;
47+
private DatabaseClient jobClient;
5348
private HubConfig hubConfig;
49+
private JobManager jobManager;
50+
51+
private DataMovementManager dataMovementManager;
5452

5553
public FlowManager(HubConfig hubConfig) {
5654
super();
5755
this.hubConfig = hubConfig;
58-
this.client = hubConfig.newStagingClient();
59-
this.client.init(NAME, this);
56+
this.stagingClient = hubConfig.newStagingClient();
57+
this.finalClient = hubConfig.newFinalClient();
58+
this.jobClient = hubConfig.newJobDbClient();
59+
this.jobManager = new JobManager(this.jobClient);
60+
this.dataMovementManager = this.stagingClient.newDataMovementManager();
61+
this.stagingClient.init(NAME, this);
6062
}
6163

6264
/**
@@ -103,8 +105,7 @@ public List<Flow> getFlows(String entityName) {
103105
* @return the flow
104106
*/
105107
public Flow getFlow(String entityName, String flowName) {
106-
Flow flow = getFlow(entityName, flowName, null);
107-
return flow;
108+
return getFlow(entityName, flowName, null);
108109
}
109110

110111
public Flow getFlow(String entityName, String flowName, FlowType flowType) {
@@ -124,27 +125,8 @@ public Flow getFlow(String entityName, String flowName, FlowType flowType) {
124125
return flowFromXml(parent.getDocumentElement());
125126
}
126127

127-
private ConfigurableApplicationContext buildApplicationContext(Flow flow, JobStatusListener statusListener) {
128-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
129-
ctx.register(StagingConfig.class);
130-
ctx.register(FlowConfig.class);
131-
ctx.register(RunHarmonizeFlowConfig.class);
132-
ctx.getBeanFactory().registerSingleton("hubConfig", hubConfig);
133-
ctx.getBeanFactory().registerSingleton("flow", flow);
134-
ctx.getBeanFactory().registerSingleton("statusListener", statusListener);
135-
ctx.refresh();
136-
return ctx;
137-
}
138-
139-
private JobParameters buildJobParameters(Flow flow, int batchSize, int threadCount) {
140-
JobParametersBuilder jpb = new JobParametersBuilder();
141-
jpb.addLong("batchSize", Integer.toUnsignedLong(batchSize));
142-
jpb.addLong("threadCount", Integer.toUnsignedLong(threadCount));
143-
jpb.addString("uid", UUID.randomUUID().toString());
144-
jpb.addString("flowType", flow.getType().toString());
145-
jpb.addString("entity", flow.getEntityName());
146-
jpb.addString("flow", flow.getName());
147-
return jpb.toJobParameters();
128+
public JobTicket runFlow(Flow flow, int batchSize, int threadCount, JobStatusListener statusListener) {
129+
return runFlow(flow, batchSize, threadCount, HubDatabase.STAGING, HubDatabase.FINAL, null, statusListener);
148130
}
149131

150132
/**
@@ -155,20 +137,83 @@ private JobParameters buildJobParameters(Flow flow, int batchSize, int threadCou
155137
* @param statusListener - the callback to receive job status updates
156138
* @return a JobExecution instance
157139
*/
158-
public JobExecution runFlow(Flow flow, int batchSize, int threadCount, JobStatusListener statusListener) {
159-
JobExecution result = null;
160-
try {
161-
ConfigurableApplicationContext ctx = buildApplicationContext(flow, statusListener);
162-
163-
JobParameters params = buildJobParameters(flow, batchSize, threadCount);
164-
JobLauncher launcher = ctx.getBean(JobLauncher.class);
165-
Job job = ctx.getBean(Job.class);
166-
result = launcher.run(job, params);
167-
} catch (Exception e) {
168-
e.printStackTrace();
140+
public JobTicket runFlow(Flow flow, int batchSize, int threadCount, HubDatabase srcDb, HubDatabase destDb, Map<String, Object> options, JobStatusListener statusListener) {
141+
142+
Collector c = flow.getCollector();
143+
if (c instanceof ServerCollector) {
144+
((ServerCollector)c).setClient(stagingClient);
145+
}
146+
147+
AtomicLong successfulEvents = new AtomicLong(0);
148+
AtomicLong failedEvents = new AtomicLong(0);
149+
AtomicLong successfulBatches = new AtomicLong(0);
150+
AtomicLong failedBatches = new AtomicLong(0);
151+
152+
Vector<String> uris = c.run(options);
153+
154+
DatabaseClient srcClient;
155+
if (srcDb.equals(HubDatabase.STAGING)) {
156+
srcClient = this.stagingClient;
169157
}
158+
else {
159+
srcClient = this.finalClient;
160+
}
161+
String targetDatabase;
162+
if (destDb.equals(HubDatabase.STAGING)) {
163+
targetDatabase = hubConfig.stagingDbName;
164+
}
165+
else {
166+
targetDatabase = hubConfig.finalDbName;
167+
}
168+
169+
FlowRunner flowRunner = new FlowRunner(srcClient, targetDatabase, flow);
170+
AtomicInteger count = new AtomicInteger(0);
171+
ArrayList<String> errorMessages = new ArrayList<>();
172+
QueryBatcher queryBatcher = dataMovementManager.newQueryBatcher(uris.iterator())
173+
.withBatchSize(batchSize)
174+
.withThreadCount(threadCount)
175+
.onUrisReady(batch -> {
176+
try {
177+
RunFlowResponse response = flowRunner.run(batch.getJobTicket().getJobId(), batch.getItems(), options);
178+
failedEvents.addAndGet(response.errorCount);
179+
successfulEvents.addAndGet(response.totalCount - response.errorCount);
180+
successfulBatches.addAndGet(1);
181+
count.addAndGet(1);
182+
}
183+
catch(Exception e) {
184+
errorMessages.add(e.toString());
185+
}
186+
})
187+
.onQueryFailure(failure -> {
188+
failedBatches.addAndGet(1);
189+
failedEvents.addAndGet(batchSize);
190+
});
191+
JobTicket jobTicket = dataMovementManager.startJob(queryBatcher);
192+
jobManager.saveJob(Job.withFlow(flow)
193+
.withJobId(jobTicket.getJobId())
194+
);
195+
196+
new Thread(() -> {
197+
queryBatcher.awaitCompletion();
198+
199+
if (statusListener != null) {
200+
statusListener.onJobFinished();
201+
}
202+
dataMovementManager.stopJob(queryBatcher);
203+
204+
// store the thing in MarkLogic
205+
Job job = Job.withFlow(flow)
206+
.withJobId(jobTicket.getJobId())
207+
.setCounts(successfulEvents.get(), failedEvents.get(), successfulBatches.get(), failedBatches.get())
208+
.withEndTime(new Date());
209+
210+
if (errorMessages.size() > 0) {
211+
job.withJobOutput(String.join("\n", errorMessages));
212+
}
213+
jobManager.saveJob(job);
214+
}).start();
170215

171-
return result;
216+
return jobTicket;
172217
}
173218

174219
/**
@@ -185,7 +230,7 @@ public static Flow flowFromXml(Element doc) {
185230
complexity = elements.item(0).getTextContent();
186231
}
187232

188-
if (complexity.equals(FlowComplexity.SIMPLE.toString())) {
233+
if (complexity != null && complexity.equals(FlowComplexity.SIMPLE.toString())) {
189234
f = new SimpleFlow(doc);
190235
}
191236

marklogic-data-hub/src/main/java/com/marklogic/hub/HubConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class HubConfig extends LoggingObject {
3535
public static final String OLD_HUB_CONFIG_DIR = "marklogic-config";
3636
public static final String HUB_CONFIG_DIR = "hub-internal-config";
3737
public static final String USER_CONFIG_DIR = "user-config";
38+
public static final String SEARCH_OPTIONS_FILE = "all-search-options.xml";
3839

3940
public static final String DEFAULT_HOST = "localhost";
4041

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.marklogic.hub;
2+
3+
public enum HubDatabase {
4+
STAGING("staging"),
5+
FINAL("final");
6+
7+
private String type;
8+
HubDatabase(String type) {
9+
this.type = type;
10+
}
11+
12+
public static HubDatabase getHubDatabase(String status) {
13+
for (HubDatabase hubDatabase : HubDatabase.values()) {
14+
if (hubDatabase.toString().equals(status)) {
15+
return hubDatabase;
16+
}
17+
}
18+
return null;
19+
}
20+
21+
public String toString() {
22+
return this.type;
23+
}
24+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.marklogic.hub;
22

33
public interface JobStatusListener {
4-
void onStatusChange(long jobId, int percentComplete, String message);
4+
void onStatusChange(String jobId, int percentComplete, String message);
55
void onJobFinished();
66
}

marklogic-data-hub/src/main/java/com/marklogic/hub/collector/AbstractCollector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import javax.xml.stream.XMLStreamException;
2121
import javax.xml.stream.XMLStreamWriter;
22+
import java.util.Map;
2223
import java.util.Vector;
2324

2425
public abstract class AbstractCollector implements Collector {
@@ -35,7 +36,7 @@ public PluginType getType() {
3536
}
3637

3738
@Override
38-
public abstract Vector<String> run();
39+
public abstract Vector<String> run(Map<String, Object> options);
3940

4041
@Override
4142
public abstract void serialize(XMLStreamWriter serializer) throws XMLStreamException;

marklogic-data-hub/src/main/java/com/marklogic/hub/collector/Collector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919

2020
import javax.xml.stream.XMLStreamException;
2121
import javax.xml.stream.XMLStreamWriter;
22+
import java.util.Map;
2223
import java.util.Vector;
2324

2425
public interface Collector {
2526

2627
PluginType getType();
27-
Vector<String> run();
28+
Vector<String> run(Map<String, Object> options);
2829
void serialize(XMLStreamWriter serializer) throws XMLStreamException;
2930
}

marklogic-data-hub/src/main/java/com/marklogic/hub/collector/QueryCollector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import com.marklogic.hub.plugin.PluginType;
1919

20+
import java.util.Map;
2021
import java.util.Vector;
2122

2223
public class QueryCollector extends ServerCollector {
@@ -28,7 +29,7 @@ public QueryCollector() {
2829
}
2930

3031
@Override
31-
public Vector<String> run() {
32+
public Vector<String> run(Map<String, Object> options) {
3233
return null;
3334
}
3435

0 commit comments

Comments
 (0)