{"id":36421268,"url":"https://github.com/dbmdz/flusswerk","last_synced_at":"2026-03-07T03:33:02.777Z","repository":{"id":38461961,"uuid":"111690431","full_name":"dbmdz/flusswerk","owner":"dbmdz","description":"Easily create AMQP/RabbitMQ based workflows.","archived":false,"fork":false,"pushed_at":"2026-02-27T12:31:41.000Z","size":1364,"stargazers_count":8,"open_issues_count":3,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-27T17:38:29.810Z","etag":null,"topics":["amqp","chain","rabbitmq","workers","workflow","workflow-engine"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbmdz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-11-22T13:53:24.000Z","updated_at":"2025-12-05T08:25:15.000Z","dependencies_parsed_at":"2026-01-07T17:04:21.450Z","dependency_job_id":null,"html_url":"https://github.com/dbmdz/flusswerk","commit_stats":null,"previous_names":["dbmdz/workflow"],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/dbmdz/flusswerk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fflusswerk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fflusswerk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fflusswerk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fflusswerk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbmdz","download_url":"https://codeload.github.com/dbmdz/flusswerk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbmdz%2Fflusswerk/sbom","scorecard":{"id":102703,"data":{"date":"2025-08-11","repo":{"name":"github.com/dbmdz/flusswerk","commit":"70e295777f5565201c44aea0ef11b242e87bdb9a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.1,"checks":[{"name":"Code-Review","score":8,"reason":"Found 4/5 approved changesets -- score normalized to 8","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:72: update your workflow using https://app.stepsecurity.io/secureworkflow/dbmdz/flusswerk/ci.yml/main?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yml:36"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"10 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-vmq6-5m68-f53m","Warn: Project is vulnerable to: GHSA-6v67-2wr5-gvf4","Warn: Project is vulnerable to: GHSA-pr98-23f8-jwxv","Warn: Project is vulnerable to: GHSA-rc42-6c7j-7h5r","Warn: Project is vulnerable to: GHSA-4gc7-5j7h-4qph","Warn: Project is vulnerable to: GHSA-4wp7-92pw-q264","Warn: Project is vulnerable to: GHSA-mjmj-j48q-9wg2","Warn: Project is vulnerable to: GHSA-4265-ccf5-phj5","Warn: Project is vulnerable to: GHSA-4g9r-vxhx-9pgx","Warn: Project is vulnerable to: GHSA-cgwf-w82q-5jrr"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-15T10:29:20.812Z","repository_id":38461961,"created_at":"2025-08-15T10:29:20.813Z","updated_at":"2025-08-15T10:29:20.813Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30206585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T03:24:23.086Z","status":"ssl_error","status_checked_at":"2026-03-07T03:23:11.444Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["amqp","chain","rabbitmq","workers","workflow","workflow-engine"],"created_at":"2026-01-11T17:36:53.635Z","updated_at":"2026-03-07T03:33:02.746Z","avatar_url":"https://github.com/dbmdz.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flusswerk - Digital Collections Workflow Engine\n\n[![Javadocs](https://javadoc.io/badge/de.digitalcollections.flusswerk/dc-flusswerk-parent.svg)](https://javadoc.io/doc/de.digitalcollections.flusswerk/dc-flusswerk-parent)\n[![License](https://img.shields.io/github/license/dbmdz/flusswerk.svg)](LICENSE)\n[![Maven Central](https://img.shields.io/maven-central/v/de.digitalcollections.flusswerk/dc-flusswerk-parent.svg)](https://search.maven.org/search?q=a:dc-flusswerk-parent)\n\nFlusswerk makes it easy to create multi threaded workers for\nread/transform/write chains (aka ETL jobs). Workflows are coordinated via\nRabbitMQ, so it's easy to create chains of independent workflow jobs (each a new\nJava application).\n\n**Maven:**\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003edev.mdz\u003c/groupId\u003e\n  \u003cartifactId\u003eflusswerk\u003c/artifactId\u003e\n  \u003cversion\u003e9.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n**Gradle:**\n\n```groovy\ndependencies {\n    compile group: 'dev.mdz', name: 'flusswerk', version: '9.0.0'\n}\n``` \n \n ## Getting started\n\nTo get started, clone or copy the [Flusswerk\nExample](https://github.com/dbmdz/flusswerk-example) application.\n\n \n## What's new in Flusswerk 5\n\n- Flusswerk connections are now shown in RabbitMQ management UI\n- structured logging now automatically contains fields `duration` and `duration_ms` that report the time your app spent on processing a certain message in seconds or milliseconds.\n- The deprecated `tracing_id` has been removed\n- The deprecated `Envelope.timestamp` has been removed in favor of `Envelope.created` which is now of type `Instant`.\n- Constructor of FlusswerkApplication now takes `Optional\u003cEngine\u003e` as an argument (call as `super(Optional.of(engine));`).\n- Options for centralized locking using Redis have been removed\n\n[FlowSpec]:\nframework/src/main/java/com/github/dbmdz/flusswerk/framework/flow/FlowSpec.java\n[IncomingMessageType]:\nframework/src/main/java/com/github/dbmdz/flusswerk/framework/model/IncomingMessageType.java\n\n## The Big Picture\n\nA typical Flusswerk application has three parts:\n\n - Messages\n - the data processing flow (usually a `Reader`, a `Transformer` and a `Writer`)\n - Some Spring Boot glue code\n - Spring Boot `application.yml` to configure all the Flusswerk things\n\nUsually it is also useful to define your own data model classes, although that\nis not strictly required.\n\nOther optional parts are\n\n - Custom metrics collection\n - Custom logging formats (aka `ProcessReport`)\n\n### Messages\n\nMessage classes are for a sending and receiving data from RabbitMQ. All Message\nclasses extend [Message][Message], which automatically forwards tracing ids from\nincoming to outgoing messages (if you set the tracing id by hand, it will not be\noverwritten).\n\n```java\nclass IndexMessage implements Message {\n\n  private String documentId;\n\n  public IndexMessage(String documentId) {\n    this.documentId = requireNonNull(documentId);\n  }\n\n  public String getId() { ... }\n\n  public boolean equals(Object other) { ... }\n\n  public int hashCode() { ... }\n\n}\n```\n\nRegister the type for the incoming message, so it gets automatically\ndeserialized:\n\n```java\n@Bean\npublic IncomingMessageType incomingMessageType() {\n  return new IncomingMessageType(IndexMessage.class);\n}\n```\n\n[Message]: framework/src/main/java/com/github/dbmdz/flusswerk/framework/model/Message.java\n\n\n### Configuration\n\nAll configuration magic happens in Spring's `application.yml`.\n\nA minimal configuration might look like:\n\n```yml\n# Default spring profile is local\nspring:\n  application:\n    name: flusswerk-example\n\nflusswerk:\n  routing:\n    incoming:\n      - search.index\n    outgoing:\n      default: search.publish\n```\n\nThis defaults to connecting to RabbitMQ `localhost:5672`, with user and password\n`guest`, five threads and retrying a message five times. The only outgoing route\ndefined is default, which is used by Flusswerk to automatically send messages.\nFor most applications these are sensible defaults and works out of the box for\nlocal testing.\n\nThe connection information can be overwritten for different environments using\nSpring Boot profiles:\n\n```yml\n---\nspring:\n  profiles: production\nflusswerk:\n  rabbitmq:\n    hosts:\n      - rabbitmq.stg\n    username: secret\n    password: secret\n```\n\nThe sections of the `Flusswerk` configuration\n\n`processing` - control of processing\n\n| property  | default |                                                  |\n| --------- | ------- | ------------------------------------------------ |\n| `threads` | 5       | Number of threads to use for parallel processing |\n\n`rabbitmq` - Connection to RabbitMQ:\n\n| property    | default     |                             |\n| ----------- | ----------- | --------------------------- |\n| `hosts`     | `localhost` | list of hosts to connect to |\n| `username`  | `guest`     | RabbitMQ username           |\n| `passwords` | `guest`     | RabbitMQ password           |\n\n\n`routing` - Messages in and out\n\n| property                | default                 |                                                                  |\n| ----------------------- | ----------------------- | ---------------------------------------------------------------- |\n| `incoming`              | `–`                     | list of queues to read from in order                             |\n| `outgoing`              | `–`                     | routes to send messages to (format 'name: topic')                |\n| `exchange`              | `flusswerk_default`     | default exchange for all queues                                  |\n| `dead letter exchange`  | `\u003cexchange\u003e + \".retry\"` | default dead letter exchange for all queues                      |\n| `exchanges`             | `-`                     | `queue: exchange name` to override default exchanges             |\n| `dead letter exchanges` | `\u003cexchange\u003e + \".retry\"` | `queue: exchange name` to override default dead letter exchanges |\n| `failure policies`      | `default`               | how to handle messages with processing errors                    |\n\n`routing.failure policies` - how to handle messages with processing errors\n\n| property           | default |                                                              |\n| ------------------ | ------- | ------------------------------------------------------------ |\n| `retries`          | `5`     | how many times to retry                                      |\n| `retryRoutingKey`  | `–`     | where to send messages to retry later *(dead lettering)*     |\n| `failedRoutingKey` | `–`     | where to send messages to that should not be processed again |\n| `backoff`          | `–`     | how long to wait until retrying a message                    |\n\nThe queue that should get a custom failure policy is a YAML key here. Please note that the name not\nonly gets processed by YAML, but also by Spring and therefore needs to be quoted and inside square\nbrackets - otherwise Spring Boot will silently ignore it:\n\n```yaml\nflusswerk:\n  routing:\n    failurePolicies:\n      \"[search.index]\":\n        retries: 3\n        backoff: '1s'\n```\n\n`monitoring` - Prometheus settings\n\n| property | default     |                               |\n| -------- | ----------- | ----------------------------- |\n| `prefix` | `flusswerk` | prefix for prometheus metrics |\n\n\n### Data Processing\n\nTo set up your data processing flow, define a Spring bean of type FlowSpec:\n\n```java\n@Bean\npublic FlowSpec flowSpec(Reader reader, Transformer transformer, Writer writer) {\n  return FlowBuilder.flow(IndexMessage.class, Document.class, IndexDocument.class)\n      .reader(reader)\n      .transformer(transformer)\n      .writerSendingMessage(writer)\n      .build();\n}\n```\n\nWith the `Reader`, `Transformer` and `Writer` implementing the `Function` interface:\n\n|               |                                     |                                                                         |\n| ------------- | ----------------------------------- | ----------------------------------------------------------------------- |\n| `Reader`      | `Function\u003cIndexMessage, Document\u003e`  | loads document from storage                                             |\n| `Transformer` | `Function\u003cDocument, IndexDocument\u003e` | uses `Document` to build up the data structure needed for indexing      |\n| `Writer`      | `Function\u003cIndexDocument, Message\u003e`  | sends indexes the data and returns a message for the next workflow step |\n\n\n## Best Practices\n\n### Stateless Processing\n\nAll classes that do data processing (Reader, Transformer, Writer,...) should be\nstateless. This has two reasons:\n\nFirst, it makes your code thread-safe and multiprocessing easy without you\nhaving to even think about it. Just keep it stateless and fly!\n\nSecond, it makes testing a breeze: You throw in data and check the data that\ncomes out. Things can go wrong? Just check if your code throws the right\nexceptions. Wherever you need to interact with external services, mock the\nbehaviour, and your good to go (the Flusswerk tests make heavy use of Mockito,\nbtw.).\n\nIf you absolutely have to introduce state, make sure your code is thread-safe.\n\n\n### Immutable Data\n\nWherever sensible, make your data classes immutable - set everything via the\nconstructor and avoid setters. Implement `equals()` and `hashCode()`. This leads\nusually to more readable code, and makes writing tests much easier. This applies\nto Message classes and to the classes that contain data. \n\nYour particular data processing needs to build your data over time and can't be\nimmutable? Think again if that is the best way, but don't worry too much.\n\n\n\n## Manual Interaction with RabbitMQ\n\nFor manual interaction with RabbitMQ there is a Spring component with the same\nclass:\n\n| `RabbitMQ`       |                                                                         |\n| ---------------- | ----------------------------------------------------------------------- |\n| `ack(Message)`   | acknowledges a `Message` received from a `Queue`                        |\n| `queue(String)`  | returns the `Queue` instance to interact with a queue of the given name |\n| `topic(Message)` | returns the `Topic` instance for the given name to send messages to     |\n| `route(Message)` | returns the `Topic` instance for the given route from `application.yml` |\n\n\n## Error Handling\n\nAny data processing can go wrong. Flusswerk supports two error handling modes:\n\n 1. stop processing for a message completely. This behaviour is triggered by a\n    [StopProcessingException][StopProcessingException].\n 2. retry processing for a message later. This behaviour is triggered by a\n    [RetryProcessingException][RetryProcessingException] or any other\n    [RuntimeException][RuntimeException].\n\nThe default retry behaviour is to wait 30 seconds between retries and try up to\n5 times. If processing a message still keeps failing, it is then treated like as\nif a StopProcessingException had been thrown and will be routed to a failed\nqueue.\n\nFor more fine-grained control, see the configuration parameters for\n`flusswerk.routing.failure policies`.\n\n[StopProcessingException]:\nframework/src/main/java/com/github/dbmdz/flusswerk/framework/exceptions/StopProcessingException.java\n[RetryProcessingException]:\nframework/src/main/java/com/github/dbmdz/flusswerk/framework/exceptions/RetryProcessingException.java\n[RuntimeException]:\nhttps://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/RuntimeException.html\n\n\n### Skip Processing\n\nProcessing can be skipped for a message by throwing a `SkipProcessingException` at any point in your\ncode. Log messages and metrics will have `status=skip` to indicate that processing was skipped. \n\n## Collecting Metrics\n\nEvery Flusswerk application provides base metrics via as a\n[Prometheus][Prometheus] endpoint:\n\n|                              |                                                            |\n|------------------------------|------------------------------------------------------------|\n| `flusswerk.messages`         | total number of processed messages since application start |\n| `flusswerk.messages.seconds` | total amount of time spent on processing these messages    |\n\nTo include custom metrics, get counters via [MeterFactory][MeterFactory]. A bean\nof type [FlowMetrics][FlowMetrics] can also consume execution information of\nsingle flows (best to extend [BaseMetrics][BaseMetrics] for that). \n\n\nThe prometheus endpoint is available at `/actuator/prometheus`.\n\n\n[BaseMetrics]: framework/src/main/java/com/github/dbmdz/flusswerk/framework/monitoring/BaseMetrics.java\n[FlowMetrics]: framework/src/main/java/com/github/dbmdz/flusswerk/framework/monitoring/FlowMetrics.java\n[Prometheus]: https://prometheus.io/\n[MeterFactory]: framework/src/main/java/com/github/dbmdz/flusswerk/framework/monitoring/MeterFactory.java\n\n\n## Customize Logging\n\nTo customize log messages, provide a bean of type [ProcessReport](framework/src/main/java/com/github/dbmdz/flusswerk/framework/reporting/ProcessReport.java).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbmdz%2Fflusswerk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbmdz%2Fflusswerk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbmdz%2Fflusswerk/lists"}