{"id":19928489,"url":"https://github.com/dinowernli/jproducers","last_synced_at":"2025-08-25T18:44:11.155Z","repository":{"id":74059550,"uuid":"119740103","full_name":"dinowernli/jproducers","owner":"dinowernli","description":"An async computation scheduling library in Java.","archived":false,"fork":false,"pushed_at":"2018-02-04T12:31:18.000Z","size":54,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-01T11:16:33.204Z","etag":null,"topics":["async","futures","java","producers","scheduling"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dinowernli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-31T20:34:23.000Z","updated_at":"2018-02-01T16:45:34.000Z","dependencies_parsed_at":"2023-09-24T13:48:22.319Z","dependency_job_id":null,"html_url":"https://github.com/dinowernli/jproducers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dinowernli/jproducers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinowernli%2Fjproducers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinowernli%2Fjproducers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinowernli%2Fjproducers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinowernli%2Fjproducers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dinowernli","download_url":"https://codeload.github.com/dinowernli/jproducers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dinowernli%2Fjproducers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272116586,"owners_count":24876266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-25T02:00:12.092Z","response_time":1107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","futures","java","producers","scheduling"],"created_at":"2024-11-12T22:37:24.987Z","updated_at":"2025-08-25T18:44:11.119Z","avatar_url":"https://github.com/dinowernli.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jproducers\n\n[![Build Status](https://travis-ci.org/dinowernli/jproducers.svg?branch=master)](https://travis-ci.org/dinowernli/jproducers)\n\nThe `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`.\n\n## Code example\n\nHere is an example class which declares a few producers.\n\n```java\nstatic class Producers {\n  @Retention(RetentionPolicy.RUNTIME)\n  @BindingAnnotation\n  @interface Foo {}\n\n  @Produces\n  @Foo\n  public static ListenableFuture\u003cString\u003e produceFoo() {\n    return Futures.immediateFuture(\"hello!\");\n  }\n\n  @Produces\n  public static long produceLength(@Foo Present\u003cString\u003e foo) throws ExecutionException {\n    return foo.get().length();\n  }\n}\n```\n\nThe code to execute a graph then looks like:\n\n```java\nProducerContext context = ProducerContext.forClasses(Producers.class);\nListenableFuture\u003cLong\u003e result = context\n    .newGraph(Key.get(Long.class))\n    .run();\n```\n\n## Producers\n\nIn 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.:\n\n```java\n@Produces\nstatic String produceSomeString(Present\u003cLong\u003e someNumber) throws ExecutionException {\n  return \"hello world: \" + someNumber.get();\n}\n```\n\nProducers may have arguments, which `jproducers` uses to determine which other producers need to be run beforehand.\n\n## Return types\n\nThe 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`:\n\n```java\n@Produces\n@Bar\nstatic ListenableFuture\u003cString\u003e produceAsyncBar() {\n  return Futures.immediateFailedFuture(new RuntimeException(\"failed!\"));\n}\n\n@Produces\n@Bar\nstatic String produceBar() {\n  return \"hello world\";\n}\n```\n\n## Error propagation\n\nA 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.\n\n```java\n@Produces\nstatic long produceNumUsers(Present\u003cUserInfoResponse\u003e response) {\n  try {\n    return response.get().getNumUsers();\n  } catch (ExecutionException e) {\n    throw new RuntimeException(\"User info rpc failed\", e);\n  }\n}\n```\n\n## Set producers\n\nIt is possible to use `@ProducesIntoSet` to declare that a producer produces and element in a set of values:\n\n```java\n@ProducesIntoSet\nstatic UserDetailsRequest produceOwnerDetailsRequest(Present\u003cLong\u003e ownerId)\n    throws ExecutionException {\n  return new UserDetailsRequest(ownerId.get());\n}\n\n@ProducesIntoSet\nstatic UserDetailsRequest producerOtherDetailsRequest(Present\u003cString\u003e username)\n    throws ExecutionException {\n  return new UserDetailsRequest(username.get());\n}\n```\n\nDownstream producers can then continue their computation of the full set:\n\n```java\n@Produces\nstatic ListenableFuture\u003cImmutableSet\u003cUserDetails\u003e\u003e produceDetails(\n    Present\u003cImmutableSet\u003cUserDetailsRequest\u003e\u003e requests,\n    Present\u003cUserInfoClient\u003e client) throws ExecutionException {\n  return client.makeRequests(requests.get());\n}\n```\n\n## Other features\n\n* Because the graph is constructed based on a desired output type, only the necessary nodes are ever executed.\n* Supports backing a `ProducerContext` with direct executors for testing.\n\n## Building and running\n\nTo run the example, execute:\n\n`bazel run  //src/main/java/me/dinowernli/jproducers/example`\n\nTo run all tests, execute:\n\n`bazel test //src/...`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdinowernli%2Fjproducers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdinowernli%2Fjproducers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdinowernli%2Fjproducers/lists"}