diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/api/CoreAdminApi.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/api/CoreAdminApi.java index 112c3d1..e4ca52c 100644 --- a/asie-api/src/main/java/com/inteligr8/alfresco/asie/api/CoreAdminApi.java +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/api/CoreAdminApi.java @@ -7,6 +7,7 @@ import com.inteligr8.alfresco.asie.model.core.DisableIndexingRequest; import com.inteligr8.alfresco.asie.model.core.EnableIndexingRequest; import com.inteligr8.alfresco.asie.model.core.FixAction; import com.inteligr8.alfresco.asie.model.core.FixRequest; +import com.inteligr8.alfresco.asie.model.core.IndexRequest; import com.inteligr8.alfresco.asie.model.core.IndexingStatusAction; import com.inteligr8.alfresco.asie.model.core.NewCoreRequest; import com.inteligr8.alfresco.asie.model.core.NewDefaultIndexRequest; @@ -61,6 +62,10 @@ public interface CoreAdminApi extends com.inteligr8.solr.api.CoreAdminApi { @Produces(MediaType.APPLICATION_JSON) ActionCoreResponse purge(@BeanParam PurgeRequest request); + @GET + @Produces(MediaType.APPLICATION_JSON) + ActionCoreResponse index(@BeanParam IndexRequest request); + @GET @Produces(MediaType.APPLICATION_JSON) ActionCoreResponse reindex(@BeanParam ReindexRequest request); diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java new file mode 100644 index 0000000..865a1fb --- /dev/null +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java @@ -0,0 +1,106 @@ +package com.inteligr8.alfresco.asie.model.core; + +import com.inteligr8.solr.model.JsonFormattedResponseRequest; + +import jakarta.annotation.Nonnull; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.QueryParam; + +public class IndexRequest extends JsonFormattedResponseRequest { + + private static final String ACTION = "index"; + + @QueryParam("action") + @DefaultValue(ACTION) + @Nonnull + private String action = ACTION; + + @QueryParam("core") + private String core; + + @QueryParam("txid") + private Long transactionId; + + @QueryParam("acltxid") + private Long aclTransactionId; + + @QueryParam("nodeId") + private Long nodeId; + + @QueryParam("aclid") + private Long aclId; + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getCore() { + return core; + } + + public void setCore(String core) { + this.core = core; + } + + public IndexRequest withCore(String core) { + this.core = core; + return this; + } + + public Long getTransactionId() { + return transactionId; + } + + public void setTransactionId(Long transactionId) { + this.transactionId = transactionId; + } + + public IndexRequest withTransactionId(Long transactionId) { + this.transactionId = transactionId; + return this; + } + + public Long getAclTransactionId() { + return aclTransactionId; + } + + public void setAclTransactionId(Long aclTransactionId) { + this.aclTransactionId = aclTransactionId; + } + + public IndexRequest withAclTransactionId(Long aclTransactionId) { + this.aclTransactionId = aclTransactionId; + return this; + } + + public Long getNodeId() { + return nodeId; + } + + public void setNodeId(Long nodeId) { + this.nodeId = nodeId; + } + + public IndexRequest withNodeId(Long nodeId) { + this.nodeId = nodeId; + return this; + } + + public Long getAclId() { + return aclId; + } + + public void setAclId(Long aclId) { + this.aclId = aclId; + } + + public IndexRequest withAclId(Long aclId) { + this.aclId = aclId; + return this; + } + +} diff --git a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java index 92bf678..cc0bd7e 100644 --- a/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java +++ b/enterprise-module/src/main/java/com/inteligr8/alfresco/asie/enterprise/service/ShardDiscoveryService.java @@ -50,12 +50,15 @@ public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.Sh for (Entry> flocShard : floc.getValue().entrySet()) { for (ShardState shardState : flocShard.getValue()) { ShardSet shardSet = ShardSet.from(floc.getKey(), shardState); - if (shardSet.getCore().equals(core)) + if (shardSet.getCore().equals(core)) { + this.logger.debug("Found matching shard set: {}: {}", core, shardSet); return shardSet; + } } } } - + + this.logger.trace("Did not find matching shard set: {}", core); return null; } @@ -96,7 +99,8 @@ public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.Sh } } } - + + this.logger.trace("Did not find matching node: {}:{}", nodeHostname, nodePort); return null; } @@ -127,6 +131,7 @@ public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.Sh ShardInstance shardInstance = shardState.getShardInstance(); if (node.equals(SolrHost.from(shardInstance))) { + this.logger.trace("Found shard on node: {}: {}", node, shardInstance.getShard().getInstance()); Map shardStates = setShardStates.get(shardSet); if (shardStates == null) setShardStates.put(shardSet, shardStates = new HashMap<>()); @@ -152,7 +157,9 @@ public class ShardDiscoveryService implements com.inteligr8.alfresco.asie.spi.Sh for (Entry>> floc : flocs.entrySet()) { if (shardMethodSet.contains(floc.getKey().getShardMethod())) { + this.logger.trace("Found qualifying shard method: {}", floc.getKey().getShardMethod()); ShardState shardState = this.extractAnyShardState(floc.getValue()); + this.logger.trace("Found single shard state representing shard method: {}: {}", floc.getKey().getShardMethod(), shardState); shardSets.add(ShardSet.from(floc.getKey(), shardState)); } } diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/IndexAcsNodeWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/IndexAcsNodeWebScript.java new file mode 100644 index 0000000..750d931 --- /dev/null +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/IndexAcsNodeWebScript.java @@ -0,0 +1,24 @@ +package com.inteligr8.alfresco.asie.rest; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.inteligr8.alfresco.asie.service.IndexService; +import com.inteligr8.alfresco.asie.spi.ActionCallback; + +@Component(value = "webscript.com.inteligr8.alfresco.asie.indexAcsNode.post") +public class IndexAcsNodeWebScript extends AbstractAcsNodeActionWebScript { + + @Autowired + private IndexService indexSerivce; + + @Override + protected void executeAction(long nodeDbId, ActionCallback callback, long fullQueueTimeout, TimeUnit fullQueueUnit, + long execTimeout, TimeUnit execUnit) throws TimeoutException, InterruptedException { + this.indexSerivce.index(nodeDbId, callback, 10L, TimeUnit.SECONDS, 30L, TimeUnit.SECONDS); + } + +} diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/ReconcileAcsNodesWebScript.java b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/ReconcileAcsNodesWebScript.java index a7e5a46..f2b7c96 100644 --- a/shared/src/main/java/com/inteligr8/alfresco/asie/rest/ReconcileAcsNodesWebScript.java +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/rest/ReconcileAcsNodesWebScript.java @@ -32,6 +32,7 @@ public class ReconcileAcsNodesWebScript extends AbstractAsieWebScript { public void executeAuthorized(WebScriptRequest request, WebScriptResponse response) throws IOException { final int fromDbId = this.getRequestTemplateIntegerVariable(request, "fromDbId"); final int toDbId = this.getRequestTemplateIntegerVariable(request, "toDbId"); + final boolean index = Boolean.TRUE.equals(this.getOptionalQueryParameter(request, "index", Boolean.class)); final boolean reindex = Boolean.TRUE.equals(this.getOptionalQueryParameter(request, "reindex", Boolean.class)); final boolean includeReconciled = Boolean.TRUE.equals(this.getOptionalQueryParameter(request, "includeReconciled", Boolean.class)); @@ -101,7 +102,7 @@ public class ReconcileAcsNodesWebScript extends AbstractAsieWebScript { }; try { - this.reconcileService.reconcile(fromDbId, toDbId, null, reindex, callback, 1L, TimeUnit.HOURS, 2L, TimeUnit.MINUTES); + this.reconcileService.reconcile(fromDbId, toDbId, null, index, reindex, callback, 1L, TimeUnit.HOURS, 2L, TimeUnit.MINUTES); if (responseMap.containsKey("error")) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/service/AcsReconcileService.java b/shared/src/main/java/com/inteligr8/alfresco/asie/service/AcsReconcileService.java index 048f373..fba1e86 100644 --- a/shared/src/main/java/com/inteligr8/alfresco/asie/service/AcsReconcileService.java +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/service/AcsReconcileService.java @@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import com.inteligr8.alfresco.asie.model.ShardInstance; +import com.inteligr8.alfresco.asie.spi.IndexCallback; import com.inteligr8.alfresco.asie.spi.ReconcileCallback; import com.inteligr8.alfresco.asie.spi.ReindexCallback; import com.inteligr8.alfresco.asie.util.CompositeFuture; @@ -55,6 +56,9 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { @Autowired private SearchService searchService; + @Autowired + private IndexService indexService; + @Autowired private ReindexService reindexService; @@ -109,20 +113,21 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { */ public void reconcile( long fromDbId, long toDbId, Integer nodesChunkSize, - boolean reindexUnreconciled, + boolean indexUnreconciled, + boolean reindexReconciled, ReconcileCallback callback, long queueTimeout, TimeUnit queueUnit, long execTimeout, TimeUnit execUnit) throws InterruptedException, TimeoutException { if (nodesChunkSize == null) nodesChunkSize = this.nodesChunkSize; if (this.logger.isTraceEnabled()) - this.logger.trace("reconcile({}, {}, {}, {}, {}, {})", fromDbId, toDbId, nodesChunkSize, reindexUnreconciled, queueUnit.toMillis(queueTimeout), execUnit.toMillis(execTimeout)); + this.logger.trace("reconcile({}, {}, {}, {}, {}, {}, {})", fromDbId, toDbId, nodesChunkSize, indexUnreconciled, reindexReconciled, queueUnit.toMillis(queueTimeout), execUnit.toMillis(execTimeout)); CompositeFuture future = new CompositeFuture<>(); for (long startDbId = fromDbId; startDbId < toDbId; startDbId += nodesChunkSize) { long endDbId = Math.min(toDbId, startDbId + nodesChunkSize); - future.combine(this.reconcileChunk(startDbId, endDbId, reindexUnreconciled, callback, queueTimeout, queueUnit, execTimeout, execUnit)); + future.combine(this.reconcileChunk(startDbId, endDbId, indexUnreconciled, reindexReconciled, callback, queueTimeout, queueUnit, execTimeout, execUnit)); future.purge(true); } @@ -135,18 +140,19 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { public Future reconcile( long fromDbId, long toDbId, Integer nodesChunkSize, - boolean reindexUnreconciled, + boolean indexUnreconciled, + boolean reindexReconciled, ReconcileCallback callback) throws InterruptedException { if (nodesChunkSize == null) nodesChunkSize = this.nodesChunkSize; - this.logger.trace("reconcile({}, {}, {}, {})", fromDbId, toDbId, nodesChunkSize, reindexUnreconciled); + this.logger.trace("reconcile({}, {}, {}, {}, {})", fromDbId, toDbId, nodesChunkSize, indexUnreconciled, reindexReconciled); CompositeFuture future = new CompositeFuture<>(); try { for (long startDbId = fromDbId; startDbId < toDbId; startDbId += nodesChunkSize) { long endDbId = Math.min(toDbId, startDbId + nodesChunkSize); - future.combine(this.reconcileChunk(startDbId, endDbId, reindexUnreconciled, callback, -1L, null, -1L, null)); + future.combine(this.reconcileChunk(startDbId, endDbId, indexUnreconciled, reindexReconciled, callback, -1L, null, -1L, null)); future.purge(true); } } catch (TimeoutException te) { @@ -158,12 +164,13 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { protected Future reconcileChunk( long fromDbId, long toDbId, - boolean reindexUnreconciled, + boolean indexUnreconciled, + boolean reindexReconciled, ReconcileCallback callback, long queueTimeout, TimeUnit queueUnit, long execTimeout, TimeUnit execUnit) throws InterruptedException, TimeoutException { if (this.logger.isTraceEnabled()) - this.logger.trace("reconcileChunk({}, {}, {}, {}, {})", fromDbId, toDbId, reindexUnreconciled, queueUnit.toMillis(queueTimeout), execUnit.toMillis(execTimeout)); + this.logger.trace("reconcileChunk({}, {}, {}, {}, {}, {})", fromDbId, toDbId, indexUnreconciled, reindexReconciled, queueUnit.toMillis(queueTimeout), execUnit.toMillis(execTimeout)); int dbIdCount = (int) (toDbId - fromDbId); @@ -202,22 +209,32 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { final long nodeDbId = _nodeDbId; this.logger.trace("Attempting to reconcile ACS node: {}", nodeDbId); + Callable callable; + final int dbIdIndex = (int) (nodeDbId - fromDbId); if (nodeRefs[dbIdIndex] != null) { - this.logger.trace("A node in the DB is already indexed in Solr: {}: {}", nodeDbId, nodeRefs[dbIdIndex]); - this.reconcileLogger.info("RECONCILED: {} <=> {}", nodeDbId, nodeRefs[dbIdIndex]); - callback.reconciled(nodeDbId); - continue; + callable = new Callable() { + @Override + public Void call() throws InterruptedException, TimeoutException { + logger.trace("A node in the DB is already indexed in Solr: {}: {}", nodeDbId, nodeRefs[dbIdIndex]); + reconcileLogger.info("RECONCILED: {} <=> {}", nodeDbId, nodeRefs[dbIdIndex]); + callback.reconciled(nodeDbId); + + if (reindexReconciled) + reindex(nodeDbId, nodeRefs[dbIdIndex], callback, execTimeout, execUnit); + return null; + } + }; + } else { + callable = new Callable() { + @Override + public Void call() throws InterruptedException, TimeoutException { + reconcile(nodeDbId, indexUnreconciled, callback, execTimeout, execUnit); + return null; + } + }; } - Callable callable = new Callable() { - @Override - public Void call() throws InterruptedException, TimeoutException { - reconcile(nodeDbId, reindexUnreconciled, callback, execTimeout, execUnit); - return null; - } - }; - if (queueTimeout < 0L) { future.combine(this.executor.submit(callable, -1L, null)); } else { @@ -229,7 +246,7 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { } public void reconcile(long nodeDbId, - boolean reindexUnreconciled, + boolean index, ReconcileCallback callback, long execTimeout, TimeUnit execUnit) throws InterruptedException, TimeoutException { NodeRef nodeRef = this.nodeService.getNodeRef(nodeDbId); @@ -250,16 +267,58 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { return; } - if (!reindexUnreconciled) { + if (!index) { this.logger.debug("A node in the DB is not indexed in Solr: {}: {}", nodeDbId, nodeRef); this.reconcileLogger.info("UNRECONCILED: {} <=> {}", nodeDbId, nodeRef); callback.unreconciled(nodeDbId); } else { - logger.debug("A node in the DB is not indexed in Solr; attempt to reindex: {}: {}", nodeDbId, nodeRef); - this.reindex(nodeDbId, nodeRef, callback, execTimeout, execUnit); + logger.debug("A node in the DB is not indexed in Solr; attempt to index: {}: {}", nodeDbId, nodeRef); + this.index(nodeDbId, nodeRef, callback, execTimeout, execUnit); } } + public void index(long nodeDbId, NodeRef nodeRef, + ReconcileCallback callback, + long execTimeout, TimeUnit execUnit) throws InterruptedException, TimeoutException { + Set syncHosts = new HashSet<>(); + Set asyncHosts = new HashSet<>(); + Map errorHosts = new HashMap<>(); + + IndexCallback indexCallback = new IndexCallback() { + + @Override + public void success(ShardInstance instance) { + reconcileLogger.info("INDEXED: {} <=> {}", nodeDbId, nodeRef); + syncHosts.add(instance); + } + + @Override + public void scheduled(ShardInstance instance) { + reconcileLogger.info("INDEXING: {} <=> {}", nodeDbId, nodeRef); + asyncHosts.add(instance); + } + + @Override + public void error(ShardInstance instance, String message) { + reconcileLogger.info("FAILED INDEX: {} <=> {}", nodeDbId, nodeRef); + errorHosts.put(instance, message); + } + }; + + try { + if (execTimeout < 0L) { + this.indexService.index(nodeDbId, indexCallback).get(); + } else { + this.indexService.index(nodeDbId, indexCallback).get(execTimeout, execUnit); + } + } catch (ExecutionException ee) { + throw new RuntimeException("An unexpected exception occurred: " + ee.getMessage(), ee); + } + + if (callback != null) + callback.processed(nodeDbId, syncHosts, asyncHosts, errorHosts); + } + public void reindex(long nodeDbId, NodeRef nodeRef, ReconcileCallback callback, long execTimeout, TimeUnit execUnit) throws InterruptedException, TimeoutException { @@ -283,7 +342,7 @@ public class AcsReconcileService implements InitializingBean, DisposableBean { @Override public void error(ShardInstance instance, String message) { - reconcileLogger.info("UNINDEXED: {} <=> {}", nodeDbId, nodeRef); + reconcileLogger.info("FAILED REINDEX: {} <=> {}", nodeDbId, nodeRef); errorHosts.put(instance, message); } }; diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/service/IndexService.java b/shared/src/main/java/com/inteligr8/alfresco/asie/service/IndexService.java new file mode 100644 index 0000000..354e2d9 --- /dev/null +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/service/IndexService.java @@ -0,0 +1,43 @@ +package com.inteligr8.alfresco.asie.service; + +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.springframework.stereotype.Component; + +import com.inteligr8.alfresco.asie.api.CoreAdminApi; +import com.inteligr8.alfresco.asie.model.ActionCoreResponse; +import com.inteligr8.alfresco.asie.model.core.IndexRequest; +import com.inteligr8.alfresco.asie.spi.ActionCallback; +import com.inteligr8.solr.model.Action; + +@Component +public class IndexService extends AbstractNodeActionService { + + @Override + protected String getActionName() { + return "index"; + } + + @Override + protected String getThreadNamePrefix() { + return "solr-index"; + } + + @Override + protected ActionCoreResponse execute(CoreAdminApi api, String core, long nodeDbId) { + IndexRequest apiRequest = new IndexRequest().withCore(core).withNodeId(nodeDbId); + return api.index(apiRequest); + } + + public Future index(long nodeDbId, ActionCallback callback) throws InterruptedException { + return super.action(nodeDbId, callback); + } + + public void index(long nodeDbId, ActionCallback callback, long fullQueueTimeout, TimeUnit fullQueueUnit, + long execTimeout, TimeUnit execUnit) throws TimeoutException, InterruptedException { + super.action(nodeDbId, callback, fullQueueTimeout, fullQueueUnit, execTimeout, execUnit); + } + +} diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/spi/IndexCallback.java b/shared/src/main/java/com/inteligr8/alfresco/asie/spi/IndexCallback.java new file mode 100644 index 0000000..9a87794 --- /dev/null +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/spi/IndexCallback.java @@ -0,0 +1,12 @@ +package com.inteligr8.alfresco.asie.spi; + +import com.inteligr8.alfresco.asie.model.ShardInstance; + +public interface IndexCallback extends ActionCallback { + + @Override + default void unknownResult(ShardInstance instance) { + throw new IllegalStateException(); + } + +} diff --git a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/indexAcsNode.post.desc.xml b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/indexAcsNode.post.desc.xml new file mode 100644 index 0000000..adff6c3 --- /dev/null +++ b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/indexAcsNode.post.desc.xml @@ -0,0 +1,63 @@ + + + + Index ACS Node in ASIE Indexes + Inteligr8 ASIE + Index the specified ACS node in the ASIE indexes. + This call will attempt to index the ACS node on all applicable Solr nodes. + The index operation could be synchronous or asynchronous and could fail on any Solr node. + If any Solr node failed synchronously in the execution, then expect a status code of 500. + The response body will still be identical to the 200/202 status codes. + If any Solr node is executing the index asynchronously and there are no synchronous failures, then expect a status code of 202.

+

The following path parameters are supported:

+
+
nodeId
+
An ACS node ID.
+
+

The following response body should be expected in most cases (200, 202, and 500 status codes):

+
+			{
+				"nodeDbId": number,
+				"success": [
+					"solrHostSync:8983/solr",
+					...
+				],
+				"scheduled": [
+					"solrHostAsync:8983/solr",
+					...
+				],
+				"error": [
+					"solrHostThatFailed:8983/solr": {
+						"message": "string"
+					},
+					...
+				]
+			}
+		
+

The following status codes should be expected:

+
+
200
+
OK
+
202
+
Accepted
+
400
+
The path or query parameters are invalid
+
+ ]]>
+ + + /inteligr8/asie/acs/node/{nodeId}/index + any + + + user + + + + false + false + + +
\ No newline at end of file diff --git a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/reconcileAcsNodes.post.desc.xml b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/reconcileAcsNodes.post.desc.xml index 82e3963..8f67475 100644 --- a/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/reconcileAcsNodes.post.desc.xml +++ b/shared/src/main/resources/alfresco/extension/templates/webscripts/com/inteligr8/alfresco/asie/reconcileAcsNodes.post.desc.xml @@ -16,6 +16,13 @@
toDbId
A DB ID integer for the ending point of a range, exclusive.
+

The following query parameters are also supported:

+
+
index
+
Schedule an `INDEX` action against all unreconciled nodes.
+
reindex
+
Schedule a `REINDEX` action against all reconciled nodes.
+

The following response body should be expected in most cases (200, 202, and 500 status codes):

 			{
@@ -58,7 +65,7 @@
 	]]>
 	
 	
-	/inteligr8/asie/acs/nodes/{fromDbId}/{toDbId}/reconcile?reindex={reindex?}
+	/inteligr8/asie/acs/nodes/{fromDbId}/{toDbId}/reconcile?index={index?}&reindex={reindex?}
 	any