Skip to content

Commit 5b27a2a

Browse files
Myron Scotthchavdapsl
authored andcommitted
issue-628 Changes to handle failure during clustered write-behind
bump versions Cleanup unused Jackson stuff Use platform-layout instead of platform-kit since platform 5.10.17 Jackson => Gson Switch to gradle nexus publish plugin platform version bump up issue-628 Changes to handle failure during clustered write-behind issue-628 Changed test case to use hamcrest libraries instead of junit issue-628 Minor formatting changes issue-628 Incorporated review comments by Chris issue-628 Incorporated review comments issue-628 Incorporated review comments issue-628 fix for current issue for handling failures of clustered write-behind issue-628 Reverting previous change issue-628 Another approach to handle the failures in clustered write behind issue-628 Reverting previous change issue-628 Increases test case timeout issue-628 Increased test case timeout issue-628 Increased test case timeout issue-628 Increased test case timeout issue-628 Increases test case timeout issue-628 Increases test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout issue-628 Changed test case timeout
1 parent ad2655f commit 5b27a2a

16 files changed

Lines changed: 251 additions & 126 deletions

File tree

build-logic/src/main/java/org/ehcache/build/conventions/DeployConvention.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,6 @@ public void apply(Project project) {
8080
dev.getOrganizationUrl().set("http://ehcache.org");
8181
}));
8282
}));
83-
publishing.repositories(repositories -> repositories.maven(maven -> {
84-
if (IS_RELEASE.test(project)) {
85-
maven.setUrl(project.property("deployUrl"));
86-
maven.credentials(creds -> {
87-
creds.setUsername(project.property("deployUser").toString());
88-
creds.setPassword(project.property("deployPwd").toString());
89-
});
90-
maven.setAllowInsecureProtocol(true);
91-
} else {
92-
maven.setName("sonatype-nexus-snapshot");
93-
maven.setUrl("https://oss.sonatype.org/content/repositories/snapshots");
94-
maven.credentials(creds -> {
95-
creds.setUsername(project.property("sonatypeUser").toString());
96-
creds.setPassword(project.property("sonatypePwd").toString());
97-
});
98-
}
99-
}));
10083
});
10184

10285
project.getExtensions().configure(SigningExtension.class, signing -> {

build.gradle

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
plugins {
1818
// This adds tasks to auto close or release nexus staging repos
19-
// see https://github.com/Codearte/gradle-nexus-staging-plugin/
20-
id 'io.codearte.nexus-staging'
19+
// see https://github.com/gradle-nexus/publish-plugin
20+
id 'io.github.gradle-nexus.publish-plugin'
2121
//OWASP Security Vulnerability Detection
2222
id 'org.owasp.dependencycheck'
2323
}
@@ -30,38 +30,26 @@ allprojects {
3030
version = findProperty('overrideVersion') ?: ehcacheVersion
3131
}
3232

33-
if (deployUrl.contains('nexus')) {
34-
//internal terracotta config, shorten url for this plugin to end at local/
35-
project.nexusStaging {
36-
serverUrl = deployUrl.replaceAll(~/local\/.*$/, "local/")
37-
packageGroup = 'Ehcache OS' //internal staging repository name
33+
nexusPublishing {
34+
repositories {
35+
sonatype {
36+
username = sonatypeUser
37+
password = sonatypePwd
38+
packageGroup = 'org.ehcache' //Sonatype staging repository name
39+
}
40+
nexus {
41+
username = tcDeployUser
42+
password = tcDeployPassword
43+
packageGroup = 'Ehcache OS' //internal staging repository name
44+
nexusUrl.set(uri('https://nexus.terracotta.eur.ad.sag:8443/service/local/'))
45+
snapshotRepositoryUrl.set(uri("https://nexus.terracotta.eur.ad.sag:8443/content/repositories/terracotta-os-snapshots/"))
46+
}
3847
}
39-
ext {
40-
deployUser = tcDeployUser
41-
deployPwd = tcDeployPassword
42-
}
43-
} else {
44-
project.nexusStaging {
45-
packageGroup = 'org.ehcache' //Sonatype staging repository name
46-
}
47-
ext {
48-
deployUser = sonatypeUser
49-
deployPwd = sonatypePwd
50-
}
51-
}
52-
53-
nexusStaging {
54-
username = project.ext.deployUser
55-
password = project.ext.deployPwd
56-
logger.debug("Nexus Staging: Using login ${username} and url ${serverUrl}")
5748
// Sonatype is often very slow in these operations:
58-
delayBetweenRetriesInMillis = (findProperty('delayBetweenRetriesInMillis') ?: '10000') as int
59-
numberOfRetries = (findProperty('numberOfRetries') ?: '100') as int
60-
}
61-
62-
tasks.named('closeAndReleaseRepository') {
63-
// Disable automatic promotion for added safety
64-
enabled = false;
49+
transitionCheckOptions {
50+
delayBetween = Duration.ofSeconds((findProperty('delayBetweenRetriesInSeconds') ?: '10') as int)
51+
maxRetries = (findProperty('numberOfRetries') ?: '100') as int
52+
}
6553
}
6654

6755
assert (JavaVersion.current().isJava8Compatible()) : 'The Ehcache 3 build requires Java 8+ to run'

clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/loaderwriter/writebehind/ClusteredWriteBehind.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,13 @@ private void process(long hash) {
7575
operation);
7676
try {
7777
if (result != null) {
78+
try{
7879
if (result != currentState.get(key) && !(operation instanceof PutOperation)) {
79-
cacheLoaderWriter.write(result.getKey(), result.getValue());
80-
}
80+
cacheLoaderWriter.write(result.getKey(), result.getValue());
81+
}
8182
currentState.put(key, result.asOperationExpiringAt(result.expirationTime()));
83+
}catch (Exception ignored){
84+
}
8285
} else {
8386
if (currentState.get(key) != null && (operation instanceof RemoveOperation
8487
|| operation instanceof ConditionalRemoveOperation)) {
@@ -95,7 +98,6 @@ private void process(long hash) {
9598
for (PutOperation<K, V> operation : currentState.values()) {
9699
builder = builder.add(codec.encode(operation));
97100
}
98-
99101
clusteredWriteBehindStore.replaceAtHead(hash, chain, builder.build());
100102
}
101103
} finally {

clustered/ehcache-clustered/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ dependencies {
9090
serverLibs project(':clustered:server:ehcache-service')
9191

9292
kit "org.terracotta.internal:terracotta-kit:$terracottaCoreVersion@tar.gz"
93-
kit "org.terracotta:platform-kit:$terracottaPlatformVersion@tar.gz"
93+
kit "org.terracotta:platform-layout:$terracottaPlatformVersion@tar.gz"
9494
}
9595

9696
task copyDocs(type: Sync) {
@@ -107,7 +107,7 @@ tasks.named('jar') {
107107
osgi {
108108
instruction Constants.BUNDLE_SYMBOLICNAME, 'org.ehcache.clustered'
109109
instruction Constants.EXPORT_PACKAGE, '!com.tc.*, !com.terracotta.*, !org.terracotta.*, !org.ehcache.*.internal.*, !sun.misc, org.ehcache.clustered.client.*, org.ehcache.clustered.common.*'
110-
instruction Constants.IMPORT_PACKAGE, '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, !com.fasterxml.jackson.*, !org.terracotta.json, javax.xml.bind*;version="[2.2,3)", *'
110+
instruction Constants.IMPORT_PACKAGE, '!sun.misc.*, org.ehcache.xml.*;resolution:=optional, jdk.jfr.*;resolution:=optional, javax.xml.bind*;version="[2.2,3)", *'
111111
}
112112
}
113113

clustered/integration-test/build.gradle

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@ dependencies {
4141
testImplementation project(':ehcache-management')
4242
testImplementation "org.terracotta.management:nms-entity-client:$terracottaPlatformVersion"
4343
testImplementation "org.terracotta.management:nms-agent-entity-client:$terracottaPlatformVersion"
44-
/*
45-
* Jackson BOMs are broken in a bunch of ways. One day we might be able to use the constraints provided through the
46-
* platform dependencies, today is not that day.
47-
*/
48-
testImplementation enforcedPlatform("com.fasterxml.jackson:jackson-bom:$jacksonVersion")
49-
testImplementation 'com.fasterxml.jackson.core:jackson-databind'
5044
testImplementation "org.terracotta:terracotta-utilities-port-chooser:$terracottaUtilitiesVersion"
5145
testImplementation("org.terracotta:galvan-platform-support:$terracottaPlatformVersion") {
5246
exclude group: 'org.terracotta', module: 'terracotta-utilities-port-chooser'

clustered/integration-test/src/test/java/org/ehcache/clustered/management/AbstractClusteringManagementTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.ehcache.clustered.management;
1717

18-
import com.fasterxml.jackson.databind.ObjectMapper;
19-
import com.fasterxml.jackson.databind.SerializationFeature;
2018
import org.ehcache.CacheManager;
2119
import org.ehcache.Status;
2220
import org.ehcache.clustered.util.BeforeAll;
@@ -84,7 +82,6 @@ public abstract class AbstractClusteringManagementTest {
8482
protected static CacheManager cacheManager;
8583
protected static ClientIdentifier ehcacheClientIdentifier;
8684
protected static ServerEntityIdentifier clusterTierManagerEntityIdentifier;
87-
protected static final ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true);
8885

8986
@ClassRule
9087
public static final ClusterWithManagement CLUSTER = new ClusterWithManagement(newCluster(2)

clustered/integration-test/src/test/java/org/ehcache/clustered/management/ClusteringManagementServiceTest.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.ehcache.config.units.MemoryUnit;
2121
import org.hamcrest.MatcherAssert;
2222
import org.junit.FixMethodOrder;
23-
import org.junit.Ignore;
2423
import org.junit.Test;
2524
import org.junit.runners.MethodSorters;
2625
import org.terracotta.management.model.capabilities.Capability;
@@ -133,14 +132,6 @@ public class ClusteringManagementServiceTest extends AbstractClusteringManagemen
133132
new StatisticDescriptor("OffHeapResource:AllocatedMemory", "GAUGE")
134133
);
135134

136-
@Test
137-
@Ignore("This is not a test, but something useful to show a json print of a cluster topology with all management metadata inside")
138-
public void test_A_topology() throws Exception {
139-
Cluster cluster = CLUSTER.getNmsService().readTopology();
140-
String json = mapper.writeValueAsString(cluster.toMap());
141-
//System.out.println(json);
142-
}
143-
144135
@Test
145136
public void test_A_client_tags_exposed() throws Exception {
146137
MatcherAssert.assertThat(() -> {

clustered/integration-test/src/test/java/org/ehcache/clustered/management/ManagementClusterConnectionTest.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.ehcache.clustered.management;
1717

18-
import com.fasterxml.jackson.databind.ObjectMapper;
19-
import com.fasterxml.jackson.databind.SerializationFeature;
2018
import org.ehcache.Cache;
2119
import org.ehcache.CacheManager;
2220
import org.ehcache.Status;
@@ -59,7 +57,6 @@
5957
public class ManagementClusterConnectionTest {
6058

6159
protected static CacheManager cacheManager;
62-
protected static ObjectMapper mapper = new ObjectMapper();
6360

6461
private static TCPProxyManager proxyManager;
6562
private static final Map<String, Long> resources;
@@ -79,9 +76,6 @@ public class ManagementClusterConnectionTest {
7976

8077
@BeforeClass
8178
public static void beforeClass() throws Exception {
82-
83-
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
84-
8579
CLUSTER.get().getCluster().getClusterControl().waitForActive();
8680

8781
proxyManager = TCPProxyManager.create(CLUSTER.get().getCluster().getConnectionURI());

clustered/integration-test/src/test/java/org/ehcache/clustered/writebehind/BasicClusteredWriteBehindTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@
2929
import java.lang.management.ManagementFactory;
3030
import java.lang.management.ThreadInfo;
3131
import java.lang.management.ThreadMXBean;
32+
import java.time.Duration;
3233
import java.util.Arrays;
34+
import java.util.List;
35+
import java.util.Map;
3336
import java.util.concurrent.TimeUnit;
3437

3538
import static org.ehcache.testing.StandardCluster.clusterPath;
3639
import static org.ehcache.testing.StandardCluster.newCluster;
3740
import static org.hamcrest.MatcherAssert.assertThat;
41+
import static org.hamcrest.Matchers.is;
42+
import static org.hamcrest.Matchers.nullValue;
3843
import static org.hamcrest.Matchers.notNullValue;
44+
import static org.terracotta.utilities.test.matchers.Eventually.within;
3945

4046

4147
public class BasicClusteredWriteBehindTest extends WriteBehindTestBase {
@@ -127,4 +133,32 @@ public void testClusteredWriteBehindLoading() throws Exception {
127133

128134
doThreadDump = false;
129135
}
136+
137+
@Test(timeout = 120000)
138+
public void testBasicClusteredWriteBehindWithFailure() {
139+
cacheManager.close();
140+
cacheManager = null;
141+
cacheManager = createCacheManagerWithLoaderWriterWithFailure(CLUSTER.getConnectionURI());
142+
final Cache<Long, String> localCache = cacheManager.getCache(testName.getMethodName(), Long.class, String.class);
143+
localCache.put(1L, String.valueOf(1));
144+
localCache.put(2L, String.valueOf(2));
145+
localCache.put(3L, String.valueOf(3));
146+
localCache.put(4L, String.valueOf(4));
147+
148+
assertThat(() -> localCache.get(1L), within(Duration.ofSeconds(100)).matches(is(nullValue())));
149+
assertThat(() -> localCache.get(3L), within(Duration.ofSeconds(100)).matches(is(nullValue())));
150+
151+
Map<Long, List<String>> records = getEvenNumberLoaderWriter().getRecords();
152+
153+
// Error will be thrown for odd keys, hence only 2 entries are expected here.
154+
assertThat(() -> records.size(), within(Duration.ofSeconds(2)).matches(is(2)));
155+
156+
// Verify that values with only even entries are present in records.
157+
List<String> keyRecords = records.get(2L);
158+
assertThat(keyRecords.get(0), is("2"));
159+
keyRecords = records.get(4L);
160+
assertThat(keyRecords.get(0), is("4"));
161+
162+
doThreadDump = false;
163+
}
130164
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright Terracotta, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.ehcache.clustered.writebehind;
18+
19+
import org.ehcache.spi.loaderwriter.CacheLoaderWriter;
20+
21+
import java.util.ArrayList;
22+
import java.util.Collections;
23+
import java.util.HashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
27+
class EvenNumberLoaderWriter<Long, String> implements CacheLoaderWriter<Long, String> {
28+
29+
private final Map<Long, List<String>> records = new HashMap<>();
30+
31+
@Override
32+
public synchronized String load(Long key) {
33+
List<String> list = records.get(key);
34+
return list == null ? null : list.get(list.size() - 1);
35+
}
36+
37+
@Override
38+
public synchronized void write(Long key, String value) throws Exception {
39+
if (Integer.parseInt(key.toString()) % 2 != 0) {
40+
throw new RuntimeException("Only even keys can be inserted");
41+
}
42+
record(key, value);
43+
}
44+
45+
@Override
46+
public void delete(Long key) {
47+
}
48+
49+
private void record(Long key, String value) {
50+
records.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
51+
}
52+
53+
synchronized Map<Long, List<String>> getRecords() {
54+
return Collections.unmodifiableMap(records);
55+
}
56+
}

0 commit comments

Comments
 (0)