https://github.com/dinowernli/jproducers
An async computation scheduling library in Java.
https://github.com/dinowernli/jproducers
async futures java producers scheduling
Last synced: 3 months ago
JSON representation
An async computation scheduling library in Java.
- Host: GitHub
- URL: https://github.com/dinowernli/jproducers
- Owner: dinowernli
- License: apache-2.0
- Created: 2018-01-31T20:34:23.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-02-04T12:31:18.000Z (over 7 years ago)
- Last Synced: 2025-01-12T00:48:19.093Z (5 months ago)
- Topics: async, futures, java, producers, scheduling
- Language: Java
- Homepage:
- Size: 52.7 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# jproducers
[](https://travis-ci.org/dinowernli/jproducers)
The `jproducers` library allows specifying asynchronous computations declaratively and letting the library do the scheduling and waiting for you. This is particularly useful to express computations which would otherwise need complex chains of `Futures.transform`.
## Code example
Here is an example class which declares a few producers.
```java
static class Producers {
@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
@interface Foo {}@Produces
@Foo
public static ListenableFuture produceFoo() {
return Futures.immediateFuture("hello!");
}@Produces
public static long produceLength(@Foo Present foo) throws ExecutionException {
return foo.get().length();
}
}
```The code to execute a graph then looks like:
```java
ProducerContext context = ProducerContext.forClasses(Producers.class);
ListenableFuture result = context
.newGraph(Key.get(Long.class))
.run();
```## Producers
In order to orchestrate a computation, `jproducers` constructs a connected graph of producer nodes. Each node is called a `producer`, and is defined by a Java method, e.g.:
```java
@Produces
static String produceSomeString(Present someNumber) throws ExecutionException {
return "hello world: " + someNumber.get();
}
```Producers may have arguments, which `jproducers` uses to determine which other producers need to be run beforehand.
## Return types
The return type of a producer method determines the produced type. If a producer returns a `ListenableFuture`, the library takes care of waiting for the future before invoking downstream producers. The following producers all have produced type `@Bar String`:
```java
@Produces
@Bar
static ListenableFuture produceAsyncBar() {
return Futures.immediateFailedFuture(new RuntimeException("failed!"));
}@Produces
@Bar
static String produceBar() {
return "hello world";
}
```## Error propagation
A producer can indicate failure by throwing an exception (or returning a failed future). If this happens, downstream producers are passed an instance of `Present` containing the error. This allows errors to be propagated throughout a producer graph.
```java
@Produces
static long produceNumUsers(Present response) {
try {
return response.get().getNumUsers();
} catch (ExecutionException e) {
throw new RuntimeException("User info rpc failed", e);
}
}
```## Set producers
It is possible to use `@ProducesIntoSet` to declare that a producer produces and element in a set of values:
```java
@ProducesIntoSet
static UserDetailsRequest produceOwnerDetailsRequest(Present ownerId)
throws ExecutionException {
return new UserDetailsRequest(ownerId.get());
}@ProducesIntoSet
static UserDetailsRequest producerOtherDetailsRequest(Present username)
throws ExecutionException {
return new UserDetailsRequest(username.get());
}
```Downstream producers can then continue their computation of the full set:
```java
@Produces
static ListenableFuture> produceDetails(
Present> requests,
Present client) throws ExecutionException {
return client.makeRequests(requests.get());
}
```## Other features
* Because the graph is constructed based on a desired output type, only the necessary nodes are ever executed.
* Supports backing a `ProducerContext` with direct executors for testing.## Building and running
To run the example, execute:
`bazel run //src/main/java/me/dinowernli/jproducers/example`
To run all tests, execute:
`bazel test //src/...`