{"id":15018079,"url":"https://github.com/davidgregory084/vertices","last_synced_at":"2025-10-23T15:30:26.469Z","repository":{"id":57732940,"uuid":"124723600","full_name":"DavidGregory084/vertices","owner":"DavidGregory084","description":null,"archived":false,"fork":false,"pushed_at":"2020-03-11T23:37:49.000Z","size":356,"stargazers_count":15,"open_issues_count":3,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-30T19:08:08.255Z","etag":null,"topics":["async","asynchronous","concurrency","concurrent","concurrent-programming","functional-programming","monix","scala","vertx"],"latest_commit_sha":null,"homepage":null,"language":"Scala","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/DavidGregory084.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}},"created_at":"2018-03-11T04:39:25.000Z","updated_at":"2025-01-01T10:58:54.000Z","dependencies_parsed_at":"2022-09-13T14:52:27.330Z","dependency_job_id":null,"html_url":"https://github.com/DavidGregory084/vertices","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidGregory084%2Fvertices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidGregory084%2Fvertices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidGregory084%2Fvertices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidGregory084%2Fvertices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidGregory084","download_url":"https://codeload.github.com/DavidGregory084/vertices/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237843819,"owners_count":19375209,"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","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","asynchronous","concurrency","concurrent","concurrent-programming","functional-programming","monix","scala","vertx"],"created_at":"2024-09-24T19:51:24.953Z","updated_at":"2025-10-23T15:30:25.946Z","avatar_url":"https://github.com/DavidGregory084.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Vertices\n\n[![Build Status](https://api.travis-ci.org/DavidGregory084/vertices.svg)](https://travis-ci.org/DavidGregory084/vertices)\n[![License](https://img.shields.io/github/license/DavidGregory084/vertices.svg)](https://opensource.org/licenses/Apache-2.0)\n[![javadoc](https://javadoc.io/badge2/io.github.davidgregory084/vertices-core_2.13/javadoc.svg)](https://javadoc.io/doc/io.github.davidgregory084/vertices-core_2.13) \n\n### Overview\n\nVertices is a Scala library that provides extension methods for the [Eclipse Vert.x](http://vertx.io/) APIs.\n\nThe basic idea of this library is to provide replacements for Vert.x methods which accept callbacks. This makes it easier to use the diverse functionality provided by the Vert.x libraries while writing idiomatic Scala code.\n\nThe new methods make use of the [Task](https://monix.io/api/3.1/monix/eval/Task.html) type from the excellent [Monix](https://monix.io) library.\n\n### Example\n\nThe Vert.x library provides a [SharedData](https://vertx.io/docs/apidocs/io/vertx/core/shareddata/SharedData.html) object which we can use to store and retrieve named [AsyncMap](https://vertx.io/docs/apidocs/io/vertx/core/shareddata/AsyncMap.html) objects.\n\nUsing the original Vert.x APIs we would write code to access this data like so:\n\n```scala\nimport io.vertx.core._\nimport scala.concurrent.{ Await, Promise }\nimport scala.concurrent.duration._\n```\n```scala\nval vertx = Vertx.vertx\n// vertx: io.vertx.core.Vertx = io.vertx.core.impl.VertxImpl@69ffdaa8\n\nval resultPromise = Promise[String]()\n// resultPromise: scala.concurrent.Promise[String] = Future(\u003cnot completed\u003e)\n\nval sharedData = vertx.sharedData\n// sharedData: io.vertx.core.shareddata.SharedData = io.vertx.core.shareddata.impl.SharedDataImpl@70439c3\n\nsharedData.getAsyncMap[String, String](\"example\", getMapResult =\u003e {\n  if (getMapResult.succeeded) {\n    val asyncMap = getMapResult.result\n    asyncMap.put(\"key\", \"value\", putResult =\u003e {\n      if (putResult.succeeded) {\n        asyncMap.get(\"key\", getResult =\u003e {\n          if (getResult.succeeded) {\n            resultPromise.success(getResult.result)\n          } else {\n            resultPromise.failure(getResult.cause)\n          }\n        })\n      } else {\n        resultPromise.failure(putResult.cause)\n      }\n    })\n  } else {\n    resultPromise.failure(getMapResult.cause)\n  }\n})\n\nAwait.result(resultPromise.future, 20.seconds)\n// res1: String = value\n```\n\nAs you can see this is a perfect demonstration of \"callback hell\".\n\nUsing this library we can write the code above as follows:\n\n```scala\nimport monix.execution.Scheduler\nimport vertices._\nimport vertices.core._\n```\n```scala\nimplicit val scheduler: Scheduler = new VertxScheduler(vertx)\n// scheduler: monix.execution.Scheduler = vertices.core.VertxScheduler@4131f6db\n\nval resultTask = for {\n  asyncMap \u003c- sharedData.getAsyncMapL[String, String](\"example\")\n  _        \u003c- asyncMap.putL(\"key\", \"value\")\n  value    \u003c- asyncMap.getL(\"key\")\n} yield value\n// resultTask: monix.eval.Task[String] = Task.FlatMap$482031947\n\nAwait.result(resultTask.runToFuture, 20.seconds)\n// res2: String = value\n```\n\nWe can also convert Vert.x [ReadStream](https://vertx.io/docs/apidocs/io/vertx/core/streams/ReadStream.html) objects to Monix [Observable](https://monix.io/api/3.1/monix/reactive/Observable.html)s.\n\nThe example below uses the Vert.x Event Bus to define an event bus consumer that echoes messages back to the sender in all-caps:\n\n```scala\nimport cats.syntax.apply._\n// import cats.syntax.apply._\n\nval messageStream = vertx.eventBus.consumer[String](\"echo\")\n// messageStream: io.vertx.core.eventbus.MessageConsumer[String] = io.vertx.core.eventbus.impl.HandlerRegistration@32107bba\n\nval echoMessagesExuberantly = for {\n  messageObservable \u003c- messageStream.toObservable(vertx)\n  _                 \u003c- messageObservable.foreachL(msg =\u003e msg.reply(msg.body.toUpperCase))\n} yield ()\n// echoMessagesExuberantly: monix.eval.Task[Unit] = Task.FlatMap$936177086\n\nechoMessagesExuberantly.runToFuture\n// res3: monix.execution.CancelableFuture[Unit] = Async(Future(\u003cnot completed\u003e),monix.eval.internal.TaskConnection$Impl$$anon$1@2b009051)\n\nval sendAMessage = vertx.eventBus.\n  requestL[String](\"echo\", \"hello\").\n  foreachL(msg =\u003e println(msg.body))\n// sendAMessage: monix.eval.Task[Unit] = Task.Map$368375378\n\nval demoTask =\n  sendAMessage *\u003e vertx.closeL\n// demoTask: monix.eval.Task[Unit] = Task.FlatMap$543433178\n\nAwait.result(demoTask.runToFuture(Scheduler.global), 20.seconds)\n// HELLO\n```\n\n### Usage\n\nThe library is published for Scala 2.12 and 2.13.\n\nThe artifact names resemble those of the original Vert.x artifacts.\n\nThey are listed below using the categories defined in the [Vert.x Documentation](https://vertx.io/docs/).\n\nSBT dependency coordinates:\n\n```scala\nval verticesVersion = \"0.1.2\"\n\n// Vert.x core\n\"io.github.davidgregory084\" %% \"vertices-core\" % verticesVersion\n// Vert.x web\n\"io.github.davidgregory084\" %% \"vertices-web\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-web-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-web-api-contract\" % verticesVersion\n// Data access\n\"io.github.davidgregory084\" %% \"vertices-mongo-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-redis-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-cassandra-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-sql-common\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-jdbc-client\" % verticesVersion\n// Microservices\n\"io.github.davidgregory084\" %% \"vertices-service-discovery\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-circuit-breaker\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-config\" % verticesVersion\n// MQTT\n\"io.github.davidgregory084\" %% \"vertices-mqtt\" % verticesVersion\n// Authentication and Authorisation\n\"io.github.davidgregory084\" %% \"vertices-auth-common\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-auth-oauth2\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-auth-mongo\" % verticesVersion\n// Messaging\n\"io.github.davidgregory084\" %% \"vertices-stomp\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-rabbitmq-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-amqp-bridge\" % verticesVersion\n// Integration\n\"io.github.davidgregory084\" %% \"vertices-kafka-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-mail-client\" % verticesVersion\n\"io.github.davidgregory084\" %% \"vertices-consul-client\" % verticesVersion\n// Event Bus Bridge\n\"io.github.davidgregory084\" %% \"vertices-tcp-eventbus-bridge\" % verticesVersion\n// Devops\n\"io.github.davidgregory084\" %% \"vertices-health-check\" % verticesVersion\n```\n\nMill dependency coordinates:\n\n```scala\ndef verticesVersion = T { \"0.1.2\" }\n\n// Vert.x core\nivy\"io.github.davidgregory084::vertices-core:${verticesVersion()}\"\n// Vert.x web\nivy\"io.github.davidgregory084::vertices-web:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-web-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-web-api-contract:${verticesVersion()}\"\n// Data access\nivy\"io.github.davidgregory084::vertices-mongo-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-redis-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-cassandra-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-sql-common:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-jdbc-client:${verticesVersion()}\"\n// Microservices\nivy\"io.github.davidgregory084::vertices-service-discovery:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-circuit-breaker:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-config:${verticesVersion()}\"\n// MQTT\nivy\"io.github.davidgregory084::vertices-mqtt:${verticesVersion()}\"\n// Authentication and Authorisation\nivy\"io.github.davidgregory084::vertices-auth-common:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-auth-oauth2:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-auth-mongo:${verticesVersion()}\"\n// Messaging\nivy\"io.github.davidgregory084::vertices-stomp:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-rabbitmq-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-amqp-bridge:${verticesVersion()}\"\n// Integration\nivy\"io.github.davidgregory084::vertices-kafka-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-mail-client:${verticesVersion()}\"\nivy\"io.github.davidgregory084::vertices-consul-client:${verticesVersion()}\"\n// Event Bus Bridge\nivy\"io.github.davidgregory084::vertices-tcp-eventbus-bridge:${verticesVersion()}\"\n// Devops\nivy\"io.github.davidgregory084::vertices-health-check:${verticesVersion()}\"\n```\n### Cheat Sheet\n\nThe naming strategy for extension methods follows that of [Monix](https://monix.io): the new methods which return [Task](https://monix.io/api/3.1/monix/eval/Task.html) are suffixed with the letter `L` since the underlying task is not executed right away (in other words that it is \"lazy\").\n\n```scala\n// Instead of the io.vertx.core.file.AsyncFile method\ndef write(data: Buffer, handler: Handler[AsyncResult[Void]]): AsyncFile\n// We can use this extension method from vertices.core\ndef writeL(data: Buffer): Task[Unit]\n\n// Instead of the io.vertx.core.dns.DnsClient method\ndef resolveMX(name: String, handler: Handler[AsyncResult[List[MxRecord]]]): DnsClient\n// We can use this extension method from vertices.core\ndef resolveMXL(name: String): Task[List[MxRecord]]\n```\n\nSince it's not possible to decorate a Java class with new static methods, replacements for static methods reside within a companion object named after the original class with `Functions` appended to the end. For example, `io.vertx.core.Vertx.clusteredVertx` has a matching `vertices.core.VertxFunctions.clusteredVertxL` function.\n\n```scala\n// Instead of the io.vertx.ext.auth.oauth2.providers.GoogleAuth static method\ndef create(vertx: Vertx, url: String, handler: Handler[AsyncResult[OAuth2Auth]]): Unit\n// We can use this function from vertices.auth.GoogleAuthFunctions\ndef createL(vertx: Vertx, url: String): Task[OAuth2Auth]\n```\n\n### Import Guide\n\nExtension methods are made available by importing from the package corresponding to each module. The package names are selected to resemble those used by the original APIs.\n\n```scala\n// Vert.x core\nimport vertices.core._\n// Vert.x web modules\nimport vertices.web._\nimport vertices.web.client._\nimport vertices.web.api.contract._\n// Vert.x data access\nimport vertices.mongo._\nimport vertices.redis.client._\nimport vertices.cassandra._\nimport vertices.sql._\nimport vertices.jdbc._\n// Vert.x microservices\nimport vertices.servicediscovery._\nimport vertices.circuitbreaker._\nimport vertices.config._\n// Vert.x MQTT\nimport vertices.mqtt._\n// Vert.x authentication and authorisation\nimport vertices.auth._\nimport vertices.auth.oauth2._\nimport vertices.auth.mongo._\n// Vert.x messaging\nimport vertices.stomp._\nimport vertices.rabbitmq._\nimport vertices.amqpbridge._\n// Vert.x integration\nimport vertices.kafka.client._\nimport vertices.mail._\nimport vertices.consul._\n// Vert.x event bus bridge\nimport vertices.eventbus.bridge.tcp._\n// Vert.x devops\nimport vertices.healthchecks._\n```\n\nThe root package `vertices` also provides some useful extension methods and type class instances for Vert.x types.\n\n### FAQ\n\nQ. Why is `\u003csome module\u003e` missing?\n\nA. The stable modules that have `Handler` operations have been added. If there are new modules that you need please raise a PR.\n\nQ. Why is `\u003csome method\u003e` missing from the generated code?\n\nA. The Vert.x code generation process relies on annotations in the original Java code. Sometimes these annotations are missing for `Handler` methods that could be wrapped by *vertices*. The solution is to raise a PR against the corresponding Vert.x project to add the annotations ([see example](https://github.com/eclipse-vertx/vert.x/pull/2573)).\n\n### Conduct\n\nContributors are expected to follow the [Scala Code of Conduct](https://www.scala-lang.org/conduct/) while participating on Github and any other venues associated with the project. \n\n### Acknowledgements\n\nThanks are due to Alexandru Nedelcu ([@alexandru](https://github.com/alexandru)) for the [Monix](https://github.com/monix/monix) library, which makes writing asynchronous code in Scala an absolute pleasure.\n\n### License\n\nAll code in this repository is licensed under the Apache License, Version 2.0.  See [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidgregory084%2Fvertices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidgregory084%2Fvertices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidgregory084%2Fvertices/lists"}