Skip to content

Commit

Permalink
feat: feign support
Browse files Browse the repository at this point in the history
  • Loading branch information
Citymonstret committed Oct 12, 2024
1 parent b108d06 commit ada81cd
Show file tree
Hide file tree
Showing 15 changed files with 580 additions and 249 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ library for introducing disruptions to your code to replicate an unstable live e

- **core:** core disruptor API
- ~~**spring:** spring integration~~
- ~~**feign:** feign integration~~
- **openfeign:** feign integration

## Example

Expand Down Expand Up @@ -40,4 +40,20 @@ final Disruptor disruptor = Disruptor.builder()
disruptor.disruptWithoutResult("test", () -> {
System.out.println("test");
});
```

### OpenFeign

```java
final DisruptorCapability capability = DisruptorCapability.of(
disruptor,
"group"
);
Feign.builder()/*...*/.addCapability(capability)/*...*/;

// Or, if using spring-cloud-openfeign:
@Bean
Capability disruptorCapability() {
return DisruptorCapability(disruptor, "group");
}
```
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
1. [x] Create core API
2. [x] Tests :)
3. [ ] Create Spring (AOP) integration
4. [ ] Create Feign integration
4. [x] Create Feign integration
101 changes: 2 additions & 99 deletions core/src/main/java/org/incendo/disruptor/DisruptionConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@
//
package org.incendo.disruptor;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import org.apiguardian.api.API;
import org.incendo.disruptor.disruption.Disruption;
import org.incendo.disruptor.trigger.DisruptionTrigger;
Expand All @@ -41,8 +36,8 @@ public interface DisruptionConfig {
*
* @return the builder
*/
static Builder builder() {
return new Builder();
static DisruptionConfigBuilder builder() {
return new DisruptionConfigBuilder();
}

/**
Expand All @@ -65,96 +60,4 @@ static Builder builder() {
* @return the mode
*/
DisruptionMode mode();

@API(status = API.Status.STABLE, since = "1.0.0")
final class Builder {

private final List<Disruption> disruptions = new ArrayList<>();
private DisruptionTrigger trigger = DisruptionTrigger.never();
private DisruptionMode mode = DisruptionMode.BEFORE;

private Builder() {
}

/**
* Sets the trigger.
*
* @param trigger new trigger
* @return {@code this}
*/
public Builder trigger(final DisruptionTrigger trigger) {
this.trigger = Objects.requireNonNull(trigger, "trigger");
return this;
}

/**
* Adds the given {@code disruptions}.
*
* @param disruptions disruptions to add
* @return {@code this}
*/
public Builder disruptions(final Disruption... disruptions) {
Objects.requireNonNull(disruptions, "disruptions");
for (final Disruption disruption : disruptions) {
Objects.requireNonNull(disruption, "disruption");
}
this.disruptions.addAll(Arrays.asList(disruptions));
return this;
}

/**
* Adds the given {@code disruptions}.
*
* @param disruptions disruptions to add
* @return {@code this}
*/
public Builder disruptions(final List<Disruption> disruptions) {
Objects.requireNonNull(disruptions, "disruptions");
for (final Disruption disruption : disruptions) {
Objects.requireNonNull(disruption, "disruption");
}
this.disruptions.addAll(disruptions);
return this;
}

/**
* Adds a {@link Disruption#delaying(Duration)} disruption.
*
* @param duration duration to delay for
* @return {@code this}
*/
public Builder delay(final Duration duration) {
return this.disruptions(Disruption.delaying(duration));
}

/**
* Adds a {@link Disruption#throwing(Function)} disruption.
*
* @param generator throwable generator
* @return {@code this}
*/
public Builder throwException(final Function<DisruptorContext, Throwable> generator) {
return this.disruptions(Disruption.throwing(generator));
}

/**
* Sets the disruption mode to the given {@code mode}.
*
* @param mode new mode
* @return {@code this}
*/
public Builder mode(final DisruptionMode mode) {
this.mode = Objects.requireNonNull(mode, "mode");
return this;
}

/**
* Build a new {@link DisruptionConfig} instance using {@code this} builder.
*
* @return the config instance
*/
public DisruptionConfig build() {
return new DisruptionConfigImpl(this.trigger, List.copyOf(this.disruptions), this.mode);
}
}
}
126 changes: 126 additions & 0 deletions core/src/main/java/org/incendo/disruptor/DisruptionConfigBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// MIT License
//
// Copyright (c) 2024 Incendo
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package org.incendo.disruptor;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import org.apiguardian.api.API;
import org.incendo.disruptor.disruption.Disruption;
import org.incendo.disruptor.trigger.DisruptionTrigger;

@API(status = API.Status.STABLE, since = "1.0.0")
public final class DisruptionConfigBuilder {

private final List<Disruption> disruptions = new ArrayList<>();
private DisruptionTrigger trigger = DisruptionTrigger.never();
private DisruptionMode mode = DisruptionMode.BEFORE;

DisruptionConfigBuilder() {
}

/**
* Sets the trigger.
*
* @param trigger new trigger
* @return {@code this}
*/
public DisruptionConfigBuilder trigger(final DisruptionTrigger trigger) {
this.trigger = Objects.requireNonNull(trigger, "trigger");
return this;
}

/**
* Adds the given {@code disruptions}.
*
* @param disruptions disruptions to add
* @return {@code this}
*/
public DisruptionConfigBuilder disruptions(final Disruption... disruptions) {
Objects.requireNonNull(disruptions, "disruptions");
for (final Disruption disruption : disruptions) {
Objects.requireNonNull(disruption, "disruption");
}
this.disruptions.addAll(Arrays.asList(disruptions));
return this;
}

/**
* Adds the given {@code disruptions}.
*
* @param disruptions disruptions to add
* @return {@code this}
*/
public DisruptionConfigBuilder disruptions(final List<Disruption> disruptions) {
Objects.requireNonNull(disruptions, "disruptions");
for (final Disruption disruption : disruptions) {
Objects.requireNonNull(disruption, "disruption");
}
this.disruptions.addAll(disruptions);
return this;
}

/**
* Adds a {@link Disruption#delaying(Duration)} disruption.
*
* @param duration duration to delay for
* @return {@code this}
*/
public DisruptionConfigBuilder delay(final Duration duration) {
return this.disruptions(Disruption.delaying(duration));
}

/**
* Adds a {@link Disruption#throwing(Function)} disruption.
*
* @param generator throwable generator
* @return {@code this}
*/
public DisruptionConfigBuilder throwException(final Function<DisruptorContext, Throwable> generator) {
return this.disruptions(Disruption.throwing(generator));
}

/**
* Sets the disruption mode to the given {@code mode}.
*
* @param mode new mode
* @return {@code this}
*/
public DisruptionConfigBuilder mode(final DisruptionMode mode) {
this.mode = Objects.requireNonNull(mode, "mode");
return this;
}

/**
* Build a new {@link DisruptionConfig} instance using {@code this} builder.
*
* @return the config instance
*/
public DisruptionConfig build() {
return new DisruptionConfigImpl(this.trigger, List.copyOf(this.disruptions), this.mode);
}
}
86 changes: 16 additions & 70 deletions core/src/main/java/org/incendo/disruptor/Disruptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@
//
package org.incendo.disruptor;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.apiguardian.api.API;

Expand All @@ -47,8 +43,8 @@ public interface Disruptor {
*
* @return a mutable builder
*/
static Builder builder() {
return new Builder();
static DisruptorBuilder builder() {
return new DisruptorBuilder();
}

/**
Expand Down Expand Up @@ -104,6 +100,20 @@ default void disruptWithoutResult(final String group, Runnable runnable) {
});
}

/**
* Triggers the disruptions for the given {@code group} and {@code mode}.
*
* @param group disruption group to trigger
* @param mode mode to trigger
*/
default void disrupt(final String group, final DisruptionMode mode) {
this.group(group).ifPresent(disruptorGroup -> this.triggerDisruptions(
DisruptorContext.of(group),
disruptorGroup,
mode
));
}

private void triggerDisruptions(
final DisruptorContext context,
final DisruptorGroup group,
Expand All @@ -117,68 +127,4 @@ private void triggerDisruptions(
.forEach(disruption -> disruption.trigger(context));
}

/**
* Builder for {@link Disruptor} instances. The builder should be constructed using {@link #builder()}.
*
* @since 1.0.0
*/
@API(status = API.Status.STABLE, since = "1.0.0")
final class Builder {

private final Map<String, DisruptorGroup> groups = new HashMap<>();

private Builder() {
}

/**
* Adds the given {@code group} with the given {@code name} to the disruptor instance.
*
* @param name group name
* @param group group
* @return {@code this}
*/
public Builder group(
final String name,
final DisruptorGroup group
) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(group, "group");

this.groups.put(name, group);

return this;
}

/**
* Adds the disruptor group with the given {@code name} to the disruptor instance,
* after letting the {@code decorator} decorate the group builder.
*
* @param name group name
* @param decorator group decorator
* @return {@code this}
*/
public Builder group(
final String name,
final Consumer<DisruptorGroup.Builder> decorator
) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(decorator, "decorator");

final DisruptorGroup.Builder builder = DisruptorGroup.builder();
decorator.accept(builder);

return this.group(name, builder.build());
}

/**
* Build a new {@link Disruptor} instance using {@code this} builder.
*
* @return the disruptor instance
*/
public Disruptor build() {
return new DisruptorImpl(
Map.copyOf(this.groups)
);
}
}
}
Loading

0 comments on commit ada81cd

Please sign in to comment.