Fix issue with CachinhModelProvider not caching 'failed' results

Also tweak some timeout values to try to make dynamic CA and reconcile
more responsive.
This commit is contained in:
Kris De Volder
2017-07-21 17:13:41 -07:00
parent 2b0829e1f6
commit 962805f949
7 changed files with 86 additions and 13 deletions

View File

@@ -27,7 +27,7 @@ sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true

View File

@@ -37,7 +37,7 @@ public abstract class BoshCommandBasedModelProvider<T> implements DynamicModelPr
private final YamlParser yamlParser;
protected final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
protected Duration CMD_TIMEOUT = Duration.ofSeconds(10);
protected Duration CMD_TIMEOUT = Duration.ofSeconds(3);
protected BoshCommandBasedModelProvider() {
Representer representer = new Representer();
@@ -76,10 +76,15 @@ public abstract class BoshCommandBasedModelProvider<T> implements DynamicModelPr
protected String executeCommand(ExternalCommand command) throws Exception {
Log.info("executing cmd: "+command);
ExternalProcess process = new ExternalProcess(getWorkingDir(), command, true, CMD_TIMEOUT);
Log.info("executing cmd DONE: "+process);
String out = process.getOut();
return out;
try {
ExternalProcess process = new ExternalProcess(getWorkingDir(), command, true, CMD_TIMEOUT);
Log.info("executing cmd SUCCESS: "+process);
String out = process.getOut();
return out;
} catch (Exception e) {
Log.log("executing cmd FAILED", e);
throw e;
}
}
protected File getWorkingDir() {

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.bosh.models;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@@ -29,9 +30,9 @@ public class CachingModelProvider<T> implements DynamicModelProvider<T> {
*/
private static final Object NULL_KEY = new Object();
private long timeout = 15;
private long timeout = 30;
private TimeUnit timeoutUnit = TimeUnit.SECONDS;
private Cache<Object, T> cache = createCache();
private Cache<Object, CompletableFuture<T>> cache = createCache();
private final DynamicModelProvider<T> delegate;
@@ -48,7 +49,7 @@ public class CachingModelProvider<T> implements DynamicModelProvider<T> {
*/
private Function<DynamicSchemaContext, Object> keyGetter = (dc) -> "WHATEVER";
protected Cache<Object, T> createCache() {
protected Cache<Object, CompletableFuture<T>> createCache() {
return CacheBuilder.newBuilder()
.expireAfterWrite(timeout, timeoutUnit)
.build();
@@ -67,7 +68,19 @@ public class CachingModelProvider<T> implements DynamicModelProvider<T> {
//guava cache doesn't like null key
key = NULL_KEY;
}
return cache.get(key, () -> delegate.getModel(dc));
CompletableFuture<T> cached;
synchronized (this) {
cached = cache.get(key, () -> {
try {
return CompletableFuture.completedFuture(delegate.getModel(dc));
} catch (Throwable e) {
CompletableFuture<T> failed = new CompletableFuture<>();
failed.completeExceptionally(e);
return failed;
}
});
}
return cached.get();
}
}

View File

@@ -12,8 +12,8 @@ package org.springframework.ide.vscode.bosh.mocks;
import java.util.concurrent.Callable;
import org.springframework.ide.vscode.bosh.BoshCommandCloudConfigProviderTest;
import org.springframework.ide.vscode.bosh.models.BoshCommandCloudConfigProvider;
import org.springframework.ide.vscode.bosh.models.BoshCommandCloudConfigProviderTest;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.IOUtil;

View File

@@ -8,7 +8,7 @@
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.bosh;
package org.springframework.ide.vscode.bosh.models;
import static org.junit.Assert.assertEquals;

View File

@@ -15,7 +15,6 @@ import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.ide.vscode.bosh.BoshCommandCloudConfigProviderTest;
import org.springframework.ide.vscode.commons.util.IOUtil;
import org.springframework.ide.vscode.commons.yaml.schema.DynamicSchemaContext;

View File

@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.bosh.models;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.junit.Test;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
@SuppressWarnings("unchecked")
public class CachingModelProviderTest {
@Test public void goodValuesAreCached() throws Exception {
DynamicModelProvider<String> modelProvider = mock(DynamicModelProvider.class);
when(modelProvider.getModel(any())).thenReturn("RESULT");
DynamicModelProvider<String> cached = new CachingModelProvider<>(modelProvider);
assertEquals("RESULT", cached.getModel(null));
assertEquals("RESULT", cached.getModel(null));
assertEquals("RESULT", cached.getModel(null));
verify(modelProvider, times(1)).getModel(any());
}
@Test public void timeoutExceptionsAreCached() throws Exception {
DynamicModelProvider<String> modelProvider = mock(DynamicModelProvider.class);
when(modelProvider.getModel(any())).thenThrow(new TimeoutException("timed out"));
DynamicModelProvider<String> cached = new CachingModelProvider<>(modelProvider);
for (int i = 0; i < 3; i++) {
try {
cached.getModel(null);
fail("Should have thrown");
} catch (Exception _e) {
Throwable e = ExceptionUtil.getDeepestCause(_e);
assertEquals(TimeoutException.class, e.getClass());
}
}
verify(modelProvider, times(1)).getModel(any());
}
}