Skip to content

Commit 4179bcc

Browse files
Merge pull request #4847 from microsoft/miller/devops-1803723
Bug 1803723: [Bug][AzureToolkit][Test] Error box begin with failed to load/refresh items of combo box
2 parents 1a07063 + 04d432a commit 4179bcc

File tree

5 files changed

+81
-56
lines changed

5 files changed

+81
-56
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/azure/toolkit/intellij/common/handler/IntelliJAzureExceptionHandler.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import com.intellij.openapi.actionSystem.AnActionEvent;
3030
import com.intellij.openapi.application.ApplicationManager;
3131
import com.intellij.openapi.application.ModalityState;
32+
import com.intellij.openapi.progress.ProgressIndicator;
33+
import com.intellij.openapi.progress.ProgressManager;
3234
import com.intellij.openapi.project.Project;
3335
import com.intellij.util.ui.UIUtil;
3436
import com.microsoft.azure.toolkit.intellij.common.AzureToolkitErrorDialog;
@@ -46,10 +48,8 @@
4648
import org.apache.commons.lang3.StringUtils;
4749

4850
import java.awt.*;
49-
import java.util.HashMap;
5051
import java.util.List;
51-
import java.util.ListIterator;
52-
import java.util.Map;
52+
import java.util.*;
5353
import java.util.stream.Collectors;
5454
import java.util.stream.Stream;
5555

@@ -70,8 +70,9 @@ public void handleException(Project object, Throwable throwable, boolean isBackG
7070

7171
@Override
7272
protected void onHandleException(final Throwable throwable, final @Nullable AzureExceptionAction[] actions) {
73-
// todo: detect foreground/background from call stack
74-
onHandleException(throwable, false, actions);
73+
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
74+
final boolean background = Objects.isNull(indicator) || !indicator.isModal();
75+
onHandleException(throwable, background, actions);
7576
}
7677

7778
@Override

Utils/azuretools-core/src/com/microsoft/azure/toolkit/lib/common/handler/AzureExceptionHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
package com.microsoft.azure.toolkit.lib.common.handler;
2323

2424
import com.microsoft.azuretools.azurecommons.helpers.Nullable;
25+
import lombok.extern.java.Log;
2526
import org.apache.commons.lang3.exception.ExceptionUtils;
2627

2728
import java.io.InterruptedIOException;
29+
import java.util.logging.Level;
2830

31+
@Log
2932
public abstract class AzureExceptionHandler {
3033
private static AzureExceptionHandler handler;
3134

@@ -53,11 +56,13 @@ public static void onRxException(final Throwable e) {
5356
}
5457

5558
public void handleException(Throwable throwable, @Nullable AzureExceptionAction... action) {
59+
log.log(Level.WARNING, "caught an error in AzureExceptionHandler", throwable);
5660
onHandleException(throwable, action);
5761
}
5862

5963
public void handleException(Throwable throwable, boolean isBackGround, @Nullable AzureExceptionAction... action) {
60-
onHandleException(throwable, isBackGround, action);
64+
log.log(Level.WARNING, "caught an error in AzureExceptionHandler", throwable);
65+
this.onHandleException(throwable, isBackGround, action);
6166
}
6267

6368
protected abstract void onHandleException(Throwable throwable, @Nullable AzureExceptionAction[] action);

Utils/azuretools-core/src/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationEnhancer.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@
2323
package com.microsoft.azure.toolkit.lib.common.operation;
2424

2525
import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitOperationException;
26+
import lombok.extern.java.Log;
2627
import org.apache.commons.collections4.CollectionUtils;
2728
import org.aspectj.lang.JoinPoint;
2829
import org.aspectj.lang.annotation.*;
2930
import org.aspectj.lang.reflect.MethodSignature;
3031

32+
import java.util.Objects;
33+
import java.util.logging.Level;
34+
3135
@Aspect
36+
@Log
3237
public final class AzureOperationEnhancer {
3338

3439
@Pointcut("execution(@AzureOperation * *..*.*(..))")
@@ -40,15 +45,19 @@ public void enterOperation(JoinPoint point) {
4045
final AzureOperationRef operation = toOperationRef(point);
4146
final AzureOperation.Type type = AzureOperationUtils.getAnnotation(operation).type();
4247
if (type == AzureOperation.Type.ACTION) {
43-
AzureOperationsContext.operations.get().clear();
48+
AzureOperationsContext.clear();
4449
}
4550
AzureOperationsContext.push(operation);
4651
}
4752

4853
@AfterReturning("operation()")
4954
public void exitOperation(JoinPoint point) {
50-
if (CollectionUtils.isNotEmpty(AzureOperationsContext.operations.get())) {
51-
AzureOperationsContext.pop();
55+
final AzureOperationRef operation = toOperationRef(point);
56+
if (CollectionUtils.isNotEmpty(AzureOperationsContext.getOperations())) {
57+
final AzureOperationRef popped = AzureOperationsContext.pop();
58+
if (!Objects.equals(popped, operation)) {
59+
log.log(Level.SEVERE, "!!!operation stack is wrongly managed!!!");
60+
}
5261
}
5362
}
5463

Utils/azuretools-core/src/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationRef.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,26 @@
2323
package com.microsoft.azure.toolkit.lib.common.operation;
2424

2525
import lombok.Builder;
26-
import lombok.Data;
26+
import lombok.Getter;
27+
import lombok.Setter;
2728

2829
import java.lang.reflect.Method;
2930

30-
@Data
31+
@Getter
32+
@Setter
3133
@Builder
3234
public class AzureOperationRef {
3335
private Method method;
3436
private String[] paramNames;
3537
private Object[] paramValues;
3638
private Object instance;
39+
40+
@Override
41+
public boolean equals(final Object obj) {
42+
if (!(obj instanceof AzureOperationRef)) {
43+
return false;
44+
}
45+
final AzureOperationRef operation = (AzureOperationRef) obj;
46+
return operation.getMethod() == this.method || operation.getMethod().equals(this.method);
47+
}
3748
}

Utils/azuretools-core/src/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationsContext.java

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,85 +23,84 @@
2323
package com.microsoft.azure.toolkit.lib.common.operation;
2424

2525
import com.microsoft.azure.toolkit.lib.common.handler.AzureExceptionHandler;
26+
import com.microsoft.azuretools.azurecommons.helpers.Nullable;
2627
import rx.Completable;
2728
import rx.Observable;
2829
import rx.Single;
30+
import rx.functions.Action1;
2931

3032
import java.lang.Thread.UncaughtExceptionHandler;
3133
import java.util.*;
3234

3335
public class AzureOperationsContext {
34-
static final ThreadLocal<Deque<AzureOperationRef>> operations = ThreadLocal.withInitial(ArrayDeque::new);
35-
static final UncaughtExceptionHandler rxExceptionHandler = (t, e) -> AzureExceptionHandler.onRxException(e);
36-
static final UncaughtExceptionHandler exceptionHandler = (t, e) -> AzureExceptionHandler.onUncaughtException(e);
36+
private static final ThreadLocal<Deque<AzureOperationRef>> operations = ThreadLocal.withInitial(ArrayDeque::new);
37+
private static final UncaughtExceptionHandler rxExceptionHandler = (t, e) -> AzureExceptionHandler.onRxException(e);
38+
private static final UncaughtExceptionHandler exceptionHandler = (t, e) -> AzureExceptionHandler.onUncaughtException(e);
3739

3840
public static List<AzureOperationRef> getOperations() {
39-
final ArrayList<AzureOperationRef> ops = new ArrayList<>(operations.get());
41+
final ArrayList<AzureOperationRef> ops = new ArrayList<>(AzureOperationsContext.operations.get());
4042
Collections.reverse(ops);
4143
return Collections.unmodifiableList(ops);
4244
}
4345

46+
static void init(Deque<AzureOperationRef> closure) {
47+
AzureOperationsContext.operations.set(closure);
48+
}
49+
4450
static void push(final AzureOperationRef operation) {
45-
operations.get().push(operation);
51+
AzureOperationsContext.operations.get().push(operation);
52+
}
53+
54+
static AzureOperationRef pop() {
55+
return AzureOperationsContext.operations.get().pop();
4656
}
4757

48-
static void pop() {
49-
operations.get().pop();
58+
static void clear() {
59+
AzureOperationsContext.operations.get().clear();
60+
}
61+
62+
static void dispose() {
63+
AzureOperationsContext.operations.remove();
5064
}
5165

5266
public static Runnable deriveClosure(final Runnable runnable) {
5367
final Deque<AzureOperationRef> closure = new ArrayDeque<>(AzureOperationsContext.getOperations());
54-
return () -> {
55-
operations.set(closure);
56-
try {
57-
runnable.run();
58-
} catch (final Throwable throwable) {
59-
AzureExceptionHandler.onUncaughtException(throwable);
60-
}
61-
};
68+
final long parentThread = Thread.currentThread().getId();
69+
return () -> act((none) -> runnable.run(), closure, parentThread, null);
6270
}
6371

6472
public static Single.OnSubscribe<?> deriveClosure(final Single.OnSubscribe<?> action) {
6573
final Deque<AzureOperationRef> closure = new ArrayDeque<>(AzureOperationsContext.getOperations());
66-
return (o) -> {
67-
Thread.currentThread().setUncaughtExceptionHandler(rxExceptionHandler);
68-
operations.set(closure);
69-
try {
70-
action.call(o);
71-
} catch (final Throwable throwable) {
72-
AzureExceptionHandler.onRxException(throwable);
73-
}
74-
};
74+
final long parentThread = Thread.currentThread().getId();
75+
return (o) -> act(action, closure, parentThread, o);
7576
}
7677

7778
public static Observable.OnSubscribe<?> deriveClosure(final Observable.OnSubscribe<?> action) {
7879
final Deque<AzureOperationRef> closure = new ArrayDeque<>(AzureOperationsContext.getOperations());
79-
return (o) -> {
80-
Thread.currentThread().setUncaughtExceptionHandler(rxExceptionHandler);
81-
operations.set(closure);
82-
try {
83-
action.call(o);
84-
} catch (final Throwable throwable) {
85-
AzureExceptionHandler.onRxException(throwable);
86-
}
87-
};
80+
final long parentThread = Thread.currentThread().getId();
81+
return (o) -> act(action, closure, parentThread, o);
8882
}
8983

9084
public static Completable.OnSubscribe deriveClosure(final Completable.OnSubscribe action) {
9185
final Deque<AzureOperationRef> closure = new ArrayDeque<>(AzureOperationsContext.getOperations());
92-
return (o) -> {
93-
Thread.currentThread().setUncaughtExceptionHandler(rxExceptionHandler);
94-
operations.set(closure);
95-
try {
96-
action.call(o);
97-
} catch (final Throwable throwable) {
98-
AzureExceptionHandler.onRxException(throwable);
99-
}
100-
};
86+
final long parentThread = Thread.currentThread().getId();
87+
return (o) -> act(action, closure, parentThread, o);
10188
}
10289

103-
@FunctionalInterface
104-
public interface OperationProceedable {
105-
Object proceed() throws Throwable;
90+
private static void act(final Action1 action, final Deque<AzureOperationRef> closure, final long parentThread, @Nullable final Object subscriber) {
91+
final long currentThread = Thread.currentThread().getId();
92+
if (!Objects.equals(currentThread, parentThread)) {
93+
Thread.currentThread().setUncaughtExceptionHandler(rxExceptionHandler);
94+
AzureOperationsContext.init(closure);
95+
}
96+
try {
97+
action.call(subscriber);
98+
} catch (final Throwable throwable) {
99+
AzureExceptionHandler.onRxException(throwable);
100+
} finally {
101+
if (!Objects.equals(currentThread, parentThread)) {
102+
AzureOperationsContext.dispose();
103+
}
104+
}
106105
}
107106
}

0 commit comments

Comments
 (0)