Skip to content

Commit

Permalink
refactor: 馃挕 new Val constructors, Cons is made private
Browse files Browse the repository at this point in the history
  • Loading branch information
imrafaelmerino committed Feb 8, 2021
1 parent 6aef051 commit 6bb4936
Show file tree
Hide file tree
Showing 85 changed files with 1,475 additions and 1,506 deletions.
138 changes: 80 additions & 58 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,62 +83,84 @@ JacksonVsJsValues.jackson thrpt 5 38816.552 卤 8916.894 ops/s
JacksonVsJsValues.jsonValues thrpt 5 51183.223 卤 10154.660 ops/s
```

## <a name="fewlinesofcode"><a/>vertx-effect in a few lines of code
## <a name="fewlinesofcode"><a/>vertx-effect in a few lines of code

```java
import jsonvalues.JsInt;
import jsonvalues.JsObj;
import jsonvalues.JsStr;
import jsonvalues.spec.JsObjSpec;

import static jsonvalues.JsPath.path;
import static jsonvalues.spec.JsSpecs.*;

import vertx.effect.Val;
import vertx.effect.Validators;
import vertx.effect.VertxModule;
import vertx.effect.exp.Cons;
import vertx.effect.exp.JsArrayExp;
import vertx.effect.exp.JsObjExp;
import vertx.effect.位;

public class MyModule extends VertxModule {

public static<String, String> toLowerCase, toUpperCase;
public static<Integer, Integer> inc;
public static<JsObj, JsObj> validate, validateAndMap;
public static<String, String> toLowerCase, toUpperCase;
public static<Integer, Integer> inc;
public static<JsObj, JsObj> validate, validateAndMap;

@Override
protected void deploy() {
@Override
protected void deploy() {

this.deploy("toLowerCase", (String str) -> Cons.success(str.toLowerCase()));
this.deploy("toUpperCase", (String str) -> Cons.success(str.toUpperCase()));
this.deploy("inc", (Integer n) -> Cons.success(n+1));

// json-values uses specs to define the structure of a Json: {a:int,b:[str,str]}
JsObjSpec spec = JsObjSpec.strict("a", integer, "b", tuple(str, str));
this.deploy("validate", Validators.validateJsObj(spec));
this.deploy("toLowerCase",
(String str) -> Val.succeed(str.toLowerCase())
);
this.deploy("toUpperCase",
(String str) -> Val.succeed(str.toUpperCase())
);
this.deploy("inc",
(Integer n) -> Val.succeed(n + 1)
);

<JsObj, JsObj> map = obj->
JsObjExp.parallel("a", inc.apply(obj.getInt("a")).map(JsInt::of),
"b", JsArrayExp.parallel(toLowerCase.apply(obj.getStr(path("/b/0")))
.map(JsStr::of),
toUpperCase.apply(obj.getStr(path("/b/1")))
.map(JsStr::of)
// json-values uses specs to define the structure of a Json: {a:int,b:[str,str]}
JsObjSpec spec = JsObjSpec.strict("a",
integer,
"b",
tuple(str,
str
)
);
this.deploy("validate",
Validators.validateJsObj(spec)
);

<JsObj, JsObj> map = obj ->
JsObjExp.parallel("a",
inc.apply(obj.getInt("a"))
.map(JsInt::of),
"b",
JsArrayExp.parallel(toLowerCase.apply(obj.getStr(path("/b/0")))
.map(JsStr::of),
toUpperCase.apply(obj.getStr(path("/b/1")))
.map(JsStr::of)
)
)
.retry(RetryPolicies.limitRetries(2));
this.deploy("validateAnMap",(JsObj obj) -> validate.apply(obj).flatMap(map));
)
.retry(RetryPolicies.limitRetries(2));
this.deploy("validateAnMap",
(JsObj obj) -> validate.apply(obj)
.flatMap(map)
);

}
}

@Override
protected void initialize() {
@Override
protected void initialize() {

toUpperCase = this.ask("toUpperCase");
toLowerCase = this.ask("toLowerCase");
inc = this.ask("inc");
validate = this.ask("validate");
validateAndMap = this.ask("validateAnMap");
toUpperCase = this.ask("toUpperCase");
toLowerCase = this.ask("toLowerCase");
inc = this.ask("inc");
validate = this.ask("validate");
validateAndMap = this.ask("validateAnMap");

}
}
}
```
**A module is a regular verticle that deploys other verticles and exposes lambdas to communicate with them**.
Expand Down Expand Up @@ -614,41 +636,41 @@ each value of the expression instead of the overall expresion with the methods:
## <a name="modules"><a/> Modules

In vertx-effect, **a module is a special verticle whose purpose is to deploy other verticles and expose lambdas
to communicate with them**. Let's put an example.
to communicate with them**. Let's put an example.

```java
import jsonvalues.JsObj;
import jsonvalues.JsStr;
import vertx.effect.Val;
import vertx.effect.VertxModule;
import vertx.effect.exp.Cons;
import vertx.effect.位;

public class MyModule extends VertxModule {

private static final String REMOVE_NULL_ADDRESS = "removeNull";
private static final String TRIM_ADDRESS = "trim";
public static<JsObj, JsObj> removeNull;
public static<JsObj, JsObj> trim;
@Override
public void deploy() {
this.deploy(REMOVE_NULL_ADDRESS,
(JsObj o) -> Cons.success(o.filterAllValues(pair -> pair.value.isNotNull()))
);
Function<JsValue, JsValue> trim = JsStr.prism.modify.apply(String::trim);
this.deploy(TRIM_ADDRESS,
(JsObj o)-> Cons.success(o.mapAllValues(pair -> trim.apply(pair.value)))
);
}
@Override
protected void initialize() {
removeNull = this.ask(REMOVE_NULL_ADDRESS);
trim = this.ask(TRIM_ADDRESS);
}
private static final String REMOVE_NULL_ADDRESS = "removeNull";
private static final String TRIM_ADDRESS = "trim";

public static<JsObj, JsObj> removeNull;
public static<JsObj, JsObj> trim;

@Override
public void deploy() {

this.deploy(REMOVE_NULL_ADDRESS,
(JsObj o) -> Val.succeed(o.filterAllValues(pair -> pair.value.isNotNull()))
);

Function<JsValue, JsValue> trim = JsStr.prism.modify.apply(String::trim);
this.deploy(TRIM_ADDRESS,
(JsObj o) -> Val.succeed(o.mapAllValues(pair -> trim.apply(pair.value)))
);
}

@Override
protected void initialize() {
removeNull = this.ask(REMOVE_NULL_ADDRESS);
trim = this.ask(TRIM_ADDRESS);
}
}
```

Expand Down
6 changes: 2 additions & 4 deletions src/main/java/vertx/effect/Clock.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package vertx.effect;

import vertx.effect.exp.Cons;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

public final class Clock {

private Clock(){}

public static <Void,Long> monotonic = v -> Cons.success(System.nanoTime());
public static <Void,Long> monotonic = v -> Val.succeed(System.nanoTime());

public static <Void,Long> realTime = v -> Cons.success(System.currentTimeMillis());
public static <Void,Long> realTime = v -> Val.succeed(System.currentTimeMillis());

public static <Void,Long> monotonic(TimeUnit unit){
return v -> monotonic.apply(null).map( time -> unit.convert(Duration.ofNanos(time)));
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/vertx/effect/Cons.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package vertx.effect;

import io.vertx.core.Future;
import vertx.effect.core.AbstractVal;

import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;

final class Cons<O> extends AbstractVal<O> {
private final Supplier<Future<O>> futureSupplier;

Cons(final Supplier<Future<O>> futureSupplier) {
this.futureSupplier = futureSupplier;
}


@Override
public Future<O> get() {
return futureSupplier.get();
}



}
4 changes: 1 addition & 3 deletions src/main/java/vertx/effect/Delay.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package vertx.effect;

import vertx.effect.exp.Cons;

import java.time.Duration;
import java.util.Objects;

Expand All @@ -16,7 +14,7 @@ public class Delay {
delay of zero seconds
*/
public static final Delay ZERO = new Delay(Duration.ofSeconds(0),
Cons.success(0L)
Val.succeed(0L)
);

/**
Expand Down
58 changes: 40 additions & 18 deletions src/main/java/vertx/effect/Val.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,35 @@
import java.util.function.Predicate;
import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;

/**
A Val is just an alias for a lazy Vertx future. Laziness makes your code more functional and pure.
It allows us to describe programs before executing them. The get method triggers the execution
of the val and returns a future.
@param <O> the type of the value produced by the future */
public interface Val<O> extends Supplier<Future<O>> {
public abstract class Val<O> implements Supplier<Future<O>> {

public static final Val<Void> NULL = Val.succeed(null);
public static final Val<Boolean> TRUE = Val.succeed(true);
public static final Val<Boolean> FALSE = Val.succeed(false);

public static <O> Val<O> fail(final Throwable failure) {
if (failure == null)
return fail(new NullPointerException("failure is null"));
return effect(() -> Future.failedFuture(failure));
}

public static <O> Val<O> effect(final Supplier<Future<O>> effect) {
if (effect == null)
return Val.fail(new NullPointerException("effect is null"));
return new Cons<>(requireNonNull(effect));
}

public static <O> Val<O> succeed(final O constant) {
return new Cons<>(() -> Future.succeededFuture(constant));
}

/**
Creates a new value by applying a function to the successful result of this value. If this value
Expand All @@ -25,7 +47,7 @@ public interface Val<O> extends Supplier<Future<O>> {
@param <P> the type of the returned value
@return a new value
*/
<P> Val<P> map(final Function<O, P> fn);
public abstract <P> Val<P> map(final Function<O, P> fn);

/**
Creates a new value by applying a function to the successful result of this value, and returns
Expand All @@ -36,26 +58,26 @@ public interface Val<O> extends Supplier<Future<O>> {
@param <Q> the type of the returned value
@return a new value
*/
<Q> Val<Q> flatMap(final <O, Q> fn);
public abstract <Q> Val<Q> flatMap(final <O, Q> fn);

<Q> Val<Q> flatMap(final <O, Q> successMapper,
final <Throwable, Q> failureMapper);
public abstract <Q> Val<Q> flatMap(final <O, Q> successMapper,
final <Throwable, Q> failureMapper);

/**
returns a new value tha will retry its execution if it fails
@param retryPolicy the policy to retry
@return a new value
*/
Val<O> retry(RetryPolicy retryPolicy);
public abstract Val<O> retry(RetryPolicy retryPolicy);


Val<O> retry(final Predicate<Throwable> predicate,
final RetryPolicy policy);
public abstract Val<O> retry(final Predicate<Throwable> predicate,
final RetryPolicy policy);


Val<O> retryOnFailure(final Predicate<O> predicate,
final RetryPolicy policy);
public abstract Val<O> retryOnFailure(final Predicate<O> predicate,
final RetryPolicy policy);

/**
Creates a new value that will handle any matching throwable that this value might contain.
Expand All @@ -66,7 +88,7 @@ Val<O> retryOnFailure(final Predicate<O> predicate,
@return a new value
*/

Val<O> recover(final Function<Throwable, O> fn);
public abstract Val<O> recover(final Function<Throwable, O> fn);

/**
Creates a new value that will handle any matching throwable that this value might contain
Expand All @@ -76,17 +98,17 @@ Val<O> retryOnFailure(final Predicate<O> predicate,
@return a new value
*/

Val<O> recoverWith(final <Throwable, O> fn);
public abstract Val<O> recoverWith(final <Throwable, O> fn);

Val<O> fallbackTo(final <Throwable, O> fn);
public abstract Val<O> fallbackTo(final <Throwable, O> fn);

/**
Adds a consumer to be notified of the succeeded result of this value.
@param handler the consumer that will be called with the succeeded result
@return a reference to this value, so it can be used fluently
*/
Val<O> onSuccess(final Consumer<O> handler);
public abstract Val<O> onSuccess(final Consumer<O> handler);

/**
Add a handler to be notified of the result.
Expand All @@ -95,16 +117,16 @@ Val<O> retryOnFailure(final Predicate<O> predicate,
@param failureHandler the handler that will be called with the failed result
@return a reference to this, so it can be used fluently
*/
Val<O> onComplete(final Consumer<O> successHandler,
final Consumer<Throwable> failureHandler);
public abstract Val<O> onComplete(final Consumer<O> successHandler,
final Consumer<Throwable> failureHandler);

/**
Add a handler to be notified of the result.
@param handler the handler that will be called with the result
@return a reference to this, so it can be used fluently
*/
Val<O> onComplete(final Handler<AsyncResult<O>> handler);
public abstract Val<O> onComplete(final Handler<AsyncResult<O>> handler);



}

0 comments on commit 6bb4936

Please sign in to comment.