Skip to content

Commit

Permalink
Merge pull request #31902 from Ladicek/fault-tolerance-devui
Browse files Browse the repository at this point in the history
Dev UI: SmallRye Fault Tolerance
  • Loading branch information
phillip-kruger authored Mar 17, 2023
2 parents cb30716 + 8f9ea00 commit bd51374
Show file tree
Hide file tree
Showing 9 changed files with 419 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import io.quarkus.deployment.recording.RecorderContext;
import io.quarkus.gizmo.ClassOutput;
import io.quarkus.runtime.metrics.MetricsFactory;
import io.quarkus.smallrye.faulttolerance.deployment.devui.FaultToleranceInfoBuildItem;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusAsyncExecutorProvider;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusExistingCircuitBreakerNames;
import io.quarkus.smallrye.faulttolerance.runtime.QuarkusFallbackHandlerProvider;
Expand Down Expand Up @@ -107,7 +108,7 @@ public void build(BuildProducer<AnnotationsTransformerBuildItem> annotationsTran
AdditionalBeanBuildItem.Builder fallbackHandlersBeans = AdditionalBeanBuildItem.builder()
.setDefaultScope(BuiltinScope.DEPENDENT.getName());
for (String fallbackHandler : fallbackHandlers) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, fallbackHandler));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(fallbackHandler).methods().build());
fallbackHandlersBeans.addBeanClass(fallbackHandler);
}
beans.produce(fallbackHandlersBeans.build());
Expand Down Expand Up @@ -151,11 +152,11 @@ public void build(BuildProducer<AnnotationsTransformerBuildItem> annotationsTran
}
// Add reflective access to custom backoff strategies
for (ClassInfo strategy : index.getAllKnownImplementors(DotNames.CUSTOM_BACKOFF_STRATEGY)) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, strategy.name().toString()));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(strategy.name().toString()).methods().build());
}

for (DotName annotation : DotNames.FT_ANNOTATIONS) {
reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, annotation.toString()));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(annotation.toString()).methods().build());
// also make them bean defining annotations
additionalBda.produce(new BeanDefiningAnnotationBuildItem(annotation));
}
Expand Down Expand Up @@ -252,7 +253,8 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
AnnotationProxyBuildItem annotationProxy,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<ValidationPhaseBuildItem.ValidationErrorBuildItem> errors) {
BuildProducer<ValidationPhaseBuildItem.ValidationErrorBuildItem> errors,
BuildProducer<FaultToleranceInfoBuildItem> faultToleranceInfo) {

Config config = ConfigProvider.getConfig();

Expand All @@ -262,7 +264,7 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
for (String exceptionConfig : exceptionConfigs) {
Optional<String[]> exceptionNames = config.getOptionalValue(exceptionConfig, String[].class);
if (exceptionNames.isPresent()) {
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, exceptionNames.get()));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(exceptionNames.get()).build());
}
}

Expand All @@ -289,7 +291,7 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
Optional<String[]> exceptionNames = config.getOptionalValue(beanClass.name().toString()
+ "/" + exceptionConfig, String[].class);
if (exceptionNames.isPresent()) {
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, exceptionNames.get()));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(exceptionNames.get()).build());
}
}

Expand All @@ -314,7 +316,7 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
Optional<String[]> exceptionNames = config.getOptionalValue(beanClass.name().toString()
+ "/" + method.name() + "/" + exceptionConfig, String[].class);
if (exceptionNames.isPresent()) {
reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, exceptionNames.get()));
reflectiveClass.produce(ReflectiveClassBuildItem.builder(exceptionNames.get()).build());
}
}
}
Expand Down Expand Up @@ -368,6 +370,9 @@ void processFaultToleranceAnnotations(SmallRyeFaultToleranceRecorder recorder,
}

recorder.initExistingCircuitBreakerNames(existingCircuitBreakerNames.keySet());

// dev UI
faultToleranceInfo.produce(new FaultToleranceInfoBuildItem(ftMethods.size()));
}

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.smallrye.faulttolerance.deployment.devui;

import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
import io.quarkus.devui.spi.page.CardPageBuildItem;
import io.quarkus.devui.spi.page.Page;
import io.quarkus.smallrye.faulttolerance.runtime.devui.FaultToleranceJsonRpcService;

public class FaultToleranceDevUIProcessor {
private static final String NAME = "SmallRye Fault Tolerance";

@BuildStep(onlyIf = IsDevelopment.class)
CardPageBuildItem cardPage(FaultToleranceInfoBuildItem faultToleranceInfo) {
CardPageBuildItem pageBuildItem = new CardPageBuildItem(NAME);

pageBuildItem.addPage(Page.webComponentPageBuilder()
.title("Guarded Methods")
.icon("font-awesome-solid:life-ring")
.componentLink("qwc-fault-tolerance-methods.js")
.staticLabel("" + faultToleranceInfo.getGuardedMethods()));

return pageBuildItem;
}

@BuildStep(onlyIf = IsDevelopment.class)
JsonRPCProvidersBuildItem jsonRPCService() {
return new JsonRPCProvidersBuildItem(NAME, FaultToleranceJsonRpcService.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.quarkus.smallrye.faulttolerance.deployment.devui;

import io.quarkus.builder.item.SimpleBuildItem;

public final class FaultToleranceInfoBuildItem extends SimpleBuildItem {
private final int guardedMethods;

public FaultToleranceInfoBuildItem(int guardedMethods) {
this.guardedMethods = guardedMethods;
}

public int getGuardedMethods() {
return guardedMethods;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
<li>@Asynchronous</li>
{/if}

{#if ftOperation.asynchronousNonBlocking}
<li>@AsynchronousNonBlocking</li>
{/if}

{#if ftOperation.blocking}
<li>@Blocking</li>
{/if}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import {css, html, LitElement} from 'lit';
import {until} from 'lit/directives/until.js';
import {JsonRpc} from 'jsonrpc';
import '@vaadin/grid';
import {columnBodyRenderer} from '@vaadin/grid/lit.js';
import '@vaadin/vertical-layout';

export class QwcFaultToleranceMethods extends LitElement {
jsonRpc = new JsonRpc('SmallRye Fault Tolerance');

static styles = css`
vaadin-grid {
height: 100%;
padding-bottom: 10px;
}
.method {
color: var(--lumo-primary-text-color);
}
`;

static properties = {
_guardedMethods: {state: true},
};

connectedCallback() {
super.connectedCallback();
this._refresh();
}

render() {
return html`${until(this._renderGuardedMethods(), html`<span>Loading guarded methods...</span>`)}`;
}

_renderGuardedMethods() {
if (this._guardedMethods) {
return html`
<vaadin-grid .items="${this._guardedMethods}" theme="no-border">
<vaadin-grid-column header="Bean Class" auto-width flex-grow="0"
${columnBodyRenderer(this._renderBeanClass, [])}
resizable>
</vaadin-grid-column>
<vaadin-grid-column header="Method" auto-width flex-grow="0"
${columnBodyRenderer(this._renderMethodName, [])}
resizable>
</vaadin-grid-column>
<vaadin-grid-column header="Fault Tolerance Strategies" auto-width flex-grow="0"
${columnBodyRenderer(this._renderStrategies, [])}
resizable>
</vaadin-grid-column>
</vaadin-grid>
`;
}
}

_renderBeanClass(guardedMethod) {
return html`
<code>${guardedMethod.beanClass}</code>
`;
}

_renderMethodName(guardedMethod) {
return html`
<code class="method">${guardedMethod.method}()</code>
`;
}

_renderStrategies(guardedMethod) {
return html`
<vaadin-vertical-layout>
${guardedMethod.ApplyFaultTolerance ? this._renderApplyFaultTolerance(guardedMethod.ApplyFaultTolerance) : html``}
${guardedMethod.Asynchronous ? html`<span>@Asynchronous</span>` : html``}
${guardedMethod.AsynchronousNonBlocking ? html`<span>@AsynchronousNonBlocking</span>` : html``}
${guardedMethod.Blocking ? html`<span>@Blocking</span>` : html``}
${guardedMethod.NonBlocking ? html`<span>@NonBlocking</span>` : html``}
${guardedMethod.Bulkhead ? this._renderBulkhead(guardedMethod.Bulkhead) : html``}
${guardedMethod.CircuitBreaker ? this._renderCircuitBreaker(guardedMethod.CircuitBreaker) : html``}
${guardedMethod.CircuitBreakerName ? this._renderCircuitBreakerName(guardedMethod.CircuitBreakerName) : html``}
${guardedMethod.Fallback ? this._renderFallback(guardedMethod.Fallback) : html``}
${guardedMethod.RateLimit ? this._renderRateLimit(guardedMethod.RateLimit) : html``}
${guardedMethod.Retry ? this._renderRetry(guardedMethod.Retry) : html``}
${guardedMethod.ExponentialBackoff ? this._renderExponentialBackoff(guardedMethod.ExponentialBackoff) : html``}
${guardedMethod.FibonacciBackoff ? this._renderFibonacciBackoff(guardedMethod.FibonacciBackoff) : html``}
${guardedMethod.CustomBackoff ? this._renderCustomBackoff(guardedMethod.CustomBackoff) : html``}
${guardedMethod.Timeout ? this._renderTimeout(guardedMethod.Timeout) : html``}
</vaadin-vertical-layout>
`;
}

_renderApplyFaultTolerance(applyFaultTolerance) {
return html`
<span>@ApplyFaultTolerance("${applyFaultTolerance.value}")</span>
`;
}

_renderBulkhead(bulkhead) {
return html`
<span>@Bulkhead(value = ${bulkhead.value}, waitingTaskQueue = ${bulkhead.waitingTaskQueue})</span>
`;
}

_renderCircuitBreaker(circuitBreaker) {
return html`
<span>@CircuitBreaker(delay = ${circuitBreaker.delay} ${circuitBreaker.delayUnit},
requestVolumeThreshold = ${circuitBreaker.requestVolumeThreshold},
failureRatio = ${circuitBreaker.failureRatio},
successThreshold = ${circuitBreaker.successThreshold},
failOn = ${this._renderArray(circuitBreaker.failOn)},
skipOn = ${this._renderArray(circuitBreaker.skipOn)})</span>
`;
}

_renderCircuitBreakerName(circuitBreakerName) {
return html`
<span>
&rarrhk;
@CircuitBreakerName("${circuitBreakerName.value}")
</span>
`;
}

_renderFallback(fallback) {
return html`
<span>@Fallback(value = ${fallback.value},
fallbackMethod = "${fallback.fallbackMethod}",
applyOn = ${this._renderArray(fallback.applyOn)},
skipOn = ${this._renderArray(fallback.skipOn)})</span>
`;
}

_renderRateLimit(rateLimit) {
return html`
<span>@RateLimit(value = ${rateLimit.value},
window = ${rateLimit.window} ${rateLimit.windowUnit},
minSpacing = ${rateLimit.minSpacing} ${rateLimit.minSpacingUnit},
type = ${rateLimit.type})</span>
`;
}

_renderRetry(retry) {
return html`
<span>@Retry(maxRetries = ${retry.maxRetries},
delay = ${retry.delay} ${retry.delayUnit},
maxDuration = ${retry.maxDuration} ${retry.maxDurationUnit},
jitter = ${retry.jitter} ${retry.jitterUnit},
retryOn = ${this._renderArray(retry.retryOn)},
abortOn = ${this._renderArray(retry.abortOn)})</span>
`;
}

_renderExponentialBackoff(exponentialBackoff) {
return html`
<span>
&rarrhk;
@ExponentialBackoff(factor = ${exponentialBackoff.factor},
maxDelay = ${exponentialBackoff.maxDelay} ${exponentialBackoff.maxDelayUnit})
</span>
`;
}

_renderFibonacciBackoff(fibonacciBackoff) {
return html`
<span>
&rarrhk;
@FibonacciBackoff(maxDelay = ${fibonacciBackoff.maxDelay} ${fibonacciBackoff.maxDelayUnit})
</span>
`;
}

_renderCustomBackoff(customBackoff) {
return html`
<span>
&rarrhk;
@CustomBackoff(${customBackoff.value})
</span>
`;
}

_renderTimeout(timeout) {
return html`
<span>@Timeout(${timeout.value} ${timeout.valueUnit})</span>
`;
}

_renderArray(array) {
return array ? html`[${array.join(', ')}]` : html`[]`;
}

_refresh() {
this.jsonRpc.getGuardedMethods().then(guardedMethods => {
this._guardedMethods = guardedMethods.result;
});
}
}

customElements.define('qwc-fault-tolerance-methods', QwcFaultToleranceMethods);
6 changes: 6 additions & 0 deletions extensions/smallrye-fault-tolerance/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
<artifactId>smallrye-fault-tolerance-mutiny</artifactId>
</dependency>

<!-- only for dev UI -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private FaultToleranceOperation createAtRuntime(CacheKey key) {
return FaultToleranceOperation.create(FaultToleranceMethods.create(key.beanClass, key.method));
}

Map<CacheKey, FaultToleranceOperation> getOperationCache() {
public Map<CacheKey, FaultToleranceOperation> getOperationCache() {
return operationCache;
}

Expand Down
Loading

0 comments on commit bd51374

Please sign in to comment.