Compare commits
17
Commits
v1.1.1-asie2
...
v1.3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab10938911 | ||
|
|
3212c47967 | ||
|
|
fbf6c17206 | ||
|
|
ff068d8d3f | ||
|
|
354ea3f337 | ||
|
|
ed2251065d | ||
|
|
1aa133876a | ||
|
|
b737bccd1c | ||
|
|
18ca6f09c5 | ||
|
|
ed97efb4ed | ||
|
|
59e745706b | ||
|
|
b6bae65e03 | ||
|
|
52caf9b555 | ||
|
|
fe95ff6239 | ||
|
|
a1144fcad4 | ||
|
|
560e147333 | ||
|
|
299be529ba |
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-platform-module-parent</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.4</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+33
-30
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-platform-module-parent</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.4</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -33,35 +33,6 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to shared -->
|
||||
<dependency>
|
||||
<groupId>com.inteligr8</groupId>
|
||||
<artifactId>common-rest-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to solr-api -->
|
||||
<dependency>
|
||||
<groupId>jakarta.ws.rs</groupId>
|
||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -86,6 +57,38 @@
|
||||
<version>1.3.2-acs-v23.3</version>
|
||||
<type>amp</type>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to shared -->
|
||||
<dependency>
|
||||
<groupId>com.inteligr8</groupId>
|
||||
<artifactId>common-rest-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to solr-api -->
|
||||
<dependency>
|
||||
<groupId>jakarta.ws.rs</groupId>
|
||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>2.17.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
|
||||
<version>2.17.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Including for testing purposes only -->
|
||||
<dependency>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-platform-module-parent</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.4</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>ASIE Platform Module Parent</name>
|
||||
@@ -45,13 +45,24 @@
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Provided by cxf-jaxrs-platform-module, but packaged due to shared -->
|
||||
<dependency>
|
||||
<groupId>com.inteligr8</groupId>
|
||||
<artifactId>common-rest-client</artifactId>
|
||||
<version>3.0.3-cxf</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!-- avoids log4j dependency -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.14.1</version>
|
||||
</plugin>
|
||||
<!-- avoids struts dependency -->
|
||||
<plugin>
|
||||
@@ -61,27 +72,27 @@
|
||||
<!-- Force use of a new maven-dependency-plugin that doesn't download struts dependency -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.4</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<version>5.14.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.4</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<version>5.14.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
@@ -98,7 +109,7 @@
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ossrh-release</id>
|
||||
<id>central-publish</id>
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
@@ -138,20 +149,20 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<groupId>org.sonatype.central</groupId>
|
||||
<artifactId>central-publishing-maven-plugin</artifactId>
|
||||
<version>0.8.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
<publishingServerId>central</publishingServerId>
|
||||
<autoPublish>true</autoPublish>
|
||||
</configuration>
|
||||
<!-- for some reason this is required... -->
|
||||
<executions>
|
||||
<execution>
|
||||
<id>ossrh-deploy</id>
|
||||
<id>deploy</id>
|
||||
<phase>deploy</phase>
|
||||
<goals><goal>deploy</goal></goals>
|
||||
<goals><goal>publish</goal></goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
+2
-3
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-platform-module-parent</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.4</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -36,12 +36,11 @@
|
||||
<dependency>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-api</artifactId>
|
||||
<version>1.1.0-asie2</version>
|
||||
<version>1.1.1-asie2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.inteligr8</groupId>
|
||||
<artifactId>common-rest-client</artifactId>
|
||||
<version>3.0.3-cxf</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Needed by this module, but provided by ACS -->
|
||||
|
||||
+29
-28
@@ -54,6 +54,9 @@ public abstract class AbstractNodeActionService {
|
||||
@Autowired
|
||||
private ExecutorManager executorManager;
|
||||
|
||||
@Autowired
|
||||
private SolrShardHashService shardHashService;
|
||||
|
||||
@Autowired(required = false)
|
||||
@Qualifier(Constants.QUALIFIER_ASIE)
|
||||
private ShardRegistry shardRegistry;
|
||||
@@ -216,42 +219,40 @@ public abstract class AbstractNodeActionService {
|
||||
|
||||
List<com.inteligr8.alfresco.asie.model.ShardInstance> instances = new LinkedList<>();
|
||||
|
||||
List<ShardInstance> slicedInstances = this.shardRegistry.getIndexSlice(searchParams);
|
||||
if (slicedInstances != null) {
|
||||
this.logger.trace("Due to a sharding method, considering only applicable shards and their ASIE nodes: {}: {}", nodeDbId, slicedInstances);
|
||||
|
||||
for (ShardInstance instance : slicedInstances)
|
||||
instances.add(this.toModel(instance));
|
||||
} else {
|
||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : this.shardRegistry.getFlocs().entrySet()) {
|
||||
if (!floc.getKey().getStoreRefs().contains(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
|
||||
continue;
|
||||
for (Entry<Shard, Set<ShardState>> shard : floc.getValue().entrySet()) {
|
||||
for (ShardState shardState : shard.getValue())
|
||||
// we need a ShardRegistry method like getIndexSlice, but
|
||||
// (1) works with shard methods other than explicit
|
||||
// (2) returns all possible instances/nodes, not just one node per instance
|
||||
|
||||
for (Entry<Floc, Map<Shard, Set<ShardState>>> floc : this.shardRegistry.getFlocs().entrySet()) {
|
||||
if (!floc.getKey().getStoreRefs().contains(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE))
|
||||
continue;
|
||||
|
||||
int shardHash = -1;
|
||||
ShardSet shardset = null;
|
||||
for (Entry<Shard, Set<ShardState>> shard : floc.getValue().entrySet()) {
|
||||
for (ShardState shardState : shard.getValue()) {
|
||||
// every shard and instance (state) in the FLOC is the same
|
||||
// but we need one ShardState to determine the full configuration
|
||||
// so we are computing the shardHash once and caching it
|
||||
if (shardset == null) {
|
||||
shardset = ShardSet.from(floc.getKey(), shardState);
|
||||
shardHash = this.shardHashService.computeShardInstanceId(shardset, nodeDbId);
|
||||
}
|
||||
|
||||
if (shardHash >= 0) {
|
||||
if (shard.getKey().getInstance() == shardHash)
|
||||
instances.add(this.toModel(shardState.getShardInstance(), shardState));
|
||||
} else {
|
||||
instances.add(this.toModel(shardState.getShardInstance(), shardState));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.trace("Despite sharding, considering all shards and nodes: {}: {}", nodeDbId, instances);
|
||||
}
|
||||
|
||||
|
||||
return instances;
|
||||
}
|
||||
|
||||
private com.inteligr8.alfresco.asie.model.ShardInstance toModel(ShardInstance instance) {
|
||||
// get any random shardState
|
||||
Floc floc = instance.getShard().getFloc();
|
||||
Map<Shard, Set<ShardState>> shardsStates = this.shardRegistry.getFlocs().get(floc);
|
||||
if (shardsStates == null)
|
||||
throw new IllegalStateException();
|
||||
Set<ShardState> shardStates = shardsStates.get(instance.getShard());
|
||||
if (shardStates == null || shardStates.isEmpty())
|
||||
throw new IllegalStateException();
|
||||
ShardState anyShardState = shardStates.iterator().next();
|
||||
|
||||
return this.toModel(instance, anyShardState);
|
||||
}
|
||||
|
||||
private com.inteligr8.alfresco.asie.model.ShardInstance toModel(ShardInstance instance, ShardState anyShardState) {
|
||||
Floc floc = instance.getShard().getFloc();
|
||||
|
||||
|
||||
@@ -102,7 +102,8 @@ public class AcsReconcileService implements InitializingBean, DisposableBean {
|
||||
*
|
||||
* @param fromDbId A node database ID, inclusive.
|
||||
* @param toDbId A node database ID, exclusive.
|
||||
* @param reindexUnreconciled For nodes not found in Solr, attempt to re-index against all applicable Solr instances.
|
||||
* @param indexUnreconciled For nodes not found in Solr, attempt to index against all applicable Solr instances.
|
||||
* @param reindexReconciled For nodes found in Solr, attempt to re-index against all applicable Solr instances.
|
||||
* @param callback A callback to process multiple returned values from the re-index.
|
||||
* @param queueTimeout A timeout for how long the calling thread should wait for space on the queue.
|
||||
* @param queueUnit The time units for the `queueTimeout`.
|
||||
@@ -288,19 +289,19 @@ public class AcsReconcileService implements InitializingBean, DisposableBean {
|
||||
|
||||
@Override
|
||||
public void success(ShardInstance instance) {
|
||||
reconcileLogger.info("INDEXED: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("INDEXED: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
syncHosts.add(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduled(ShardInstance instance) {
|
||||
reconcileLogger.info("INDEXING: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("INDEXING: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
asyncHosts.add(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(ShardInstance instance, String message) {
|
||||
reconcileLogger.info("FAILED INDEX: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("FAILED INDEX: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
errorHosts.put(instance, message);
|
||||
}
|
||||
};
|
||||
@@ -330,19 +331,19 @@ public class AcsReconcileService implements InitializingBean, DisposableBean {
|
||||
|
||||
@Override
|
||||
public void success(ShardInstance instance) {
|
||||
reconcileLogger.info("REINDEXED: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("REINDEXED: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
syncHosts.add(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduled(ShardInstance instance) {
|
||||
reconcileLogger.info("REINDEXING: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("REINDEXING: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
asyncHosts.add(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(ShardInstance instance, String message) {
|
||||
reconcileLogger.info("FAILED REINDEX: {} <=> {}", nodeDbId, nodeRef);
|
||||
reconcileLogger.info("FAILED REINDEX: {} <=> {} in {}", nodeDbId, nodeRef, instance);
|
||||
errorHosts.put(instance, message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,32 @@
|
||||
package com.inteligr8.alfresco.asie.service;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.codec.digest.MurmurHash3;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.inteligr8.alfresco.asie.model.ShardSet;
|
||||
|
||||
@Component
|
||||
public class SolrShardHashService {
|
||||
|
||||
private final Charset charset = Charset.forName("utf-8");
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
@Autowired
|
||||
private NodeService nodeService;
|
||||
|
||||
public int hash(Object obj, int shardCount) {
|
||||
String str = obj.toString();
|
||||
@@ -23,5 +41,53 @@ public class SolrShardHashService {
|
||||
hash.add(bytes, 0, bytes.length);
|
||||
return Math.abs(hash.end()) % shardCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shardset A ShardSet.
|
||||
* @param nodeDbId The numeric database ID of an ACS node.
|
||||
* @return A shard instance from 0 to 1 less than the number of shards; -1 if unable to hash.
|
||||
*/
|
||||
public int computeShardInstanceId(ShardSet shardset, long nodeDbId) {
|
||||
NodeRef nodeRef = this.nodeService.getNodeRef(nodeDbId);
|
||||
if (nodeRef == null)
|
||||
throw new AlfrescoRuntimeException("The node " + nodeDbId + " does not exist");
|
||||
return this.computeShardInstanceId(shardset, nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shardset A ShardSet.
|
||||
* @param nodeRef A reference to an ACS node.
|
||||
* @return A shard instance from 0 to 1 less than the number of shards; -1 if unable to hash.
|
||||
*/
|
||||
public int computeShardInstanceId(ShardSet shardset, NodeRef nodeRef) {
|
||||
switch (shardset.getMethod()) {
|
||||
case PROPERTY:
|
||||
QName hashableProperty = QName.createQName(shardset.getPrefixedProperty(), this.namespaceService);
|
||||
Object fullPropertyValue = this.nodeService.getProperty(nodeRef, hashableProperty);
|
||||
if (fullPropertyValue == null) {
|
||||
this.logger.debug("Unable to determine shard instance ID because property does not exist on node: {}: {}", nodeRef, hashableProperty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
this.logger.trace("Discovered node property for sharding: {} => {}", nodeRef, fullPropertyValue);
|
||||
String hashableValue = fullPropertyValue.toString();
|
||||
if (shardset.getRegex() != null) {
|
||||
Matcher matcher = shardset.getRegex().matcher(hashableValue);
|
||||
if (!matcher.find()) {
|
||||
this.logger.debug("Unable to determine shard instance ID because regex pattern doesn't match the hashing property value: {}: {}: {}", nodeRef, shardset.getRegex(), hashableValue);
|
||||
return -1;
|
||||
}
|
||||
hashableValue = matcher.group(1);
|
||||
this.logger.trace("Extracted shardable value from node: {}: {} => {}", nodeRef, fullPropertyValue, hashableValue);
|
||||
}
|
||||
|
||||
int shardHash = this.hash(hashableValue, shardset.getShards().intValue());
|
||||
this.logger.debug("Hash shardable value to shard instance ID: {}: {} => {}", nodeRef, hashableValue, shardHash);
|
||||
return shardHash;
|
||||
default:
|
||||
this.logger.trace("Unable to determine shard instance ID due to shard method: {}", shardset.getMethod());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.inteligr8.alfresco</groupId>
|
||||
<artifactId>asie-platform-module-parent</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<version>1.3.4</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user