{"id":15678875,"url":"https://github.com/pmlopes/hang-around","last_synced_at":"2025-05-07T09:04:32.822Z","repository":{"id":50587909,"uuid":"494052791","full_name":"pmlopes/hang-around","owner":"pmlopes","description":"Async Await but for Vert.x","archived":false,"fork":false,"pushed_at":"2022-06-03T07:55:53.000Z","size":17,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-05-07T09:04:16.655Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/pmlopes.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":"2022-05-19T12:00:09.000Z","updated_at":"2023-12-12T21:17:36.000Z","dependencies_parsed_at":"2022-09-09T17:20:42.666Z","dependency_job_id":null,"html_url":"https://github.com/pmlopes/hang-around","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmlopes%2Fhang-around","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmlopes%2Fhang-around/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmlopes%2Fhang-around/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmlopes%2Fhang-around/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmlopes","download_url":"https://codeload.github.com/pmlopes/hang-around/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252847489,"owners_count":21813453,"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":[],"created_at":"2024-10-03T16:25:16.324Z","updated_at":"2025-05-07T09:04:32.805Z","avatar_url":"https://github.com/pmlopes.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hang-around\n\n## Async Await but for Vert.x\n\nOne of the main pain points of asynchronous programming is that code flow can be hard to read. With the upcoming Java 19\nwe will see Virtual Threads being added to the JVM. Virtual Threads, unlike regular Threads are not OS Threads and give\nus a way to create large amounts of them without worrying that we will exhaust the OS resource.\n\nThis single source file project gives you a rought idea of what you can do to make your asynchronous code more readable.\n\nThe idea isn't new. In fact if you have programmed in JavaScript this will resemble very similar:\n\nLet's see an example of an HTTP server that will increment a value in REDIS on each call:\n\n```java\npublic class Demo extends AbstractVerticle {\n\n  @Override\n  public void start(Promise\u003cVoid\u003e start) {\n    // wrap this block as a Virtual Thread so we can await (block) at any time\n    // without interfere with the event loop\n    asyncRun(() -\u003e {\n      Redis redis = Redis.createClient(\n        vertx,\n        new RedisOptions().setMaxPoolSize(32).setMaxPoolWaiting(128));\n\n      System.out.println(\"Will count calls to: counter\");\n      // look blocking but not the event loop!\n      await(redis.send(cmd(SET).arg(\"counter\").arg(0)));\n\n      vertx\n        .createHttpServer()\n        // handler's are non blocking by nature, so like in JavaScript we just mark then as\n        // \"async()\" this will start a new virtual thread and ensure we can block at any time\n        .requestHandler(async(req -\u003e {\n          try {\n            // we block by waiting on the redis response\n            var set = await(redis.send(cmd(INCR).arg(key)));\n            // and return the result, no more chains of flatMap(), compose(), onXYZ()...\n            req.response().end(set.toString());\n          } catch (RuntimeException e) {\n            // exceptions are now also handled as simple try-catch\n            req.response()\n              .setStatusCode(500)\n              .end(e.getMessage());\n         }\n      }))\n      .listen(8000, \"0.0.0.0\")\n      .\u003cVoid\u003emapEmpty()\n      .onComplete(start);\n    });\n  }\n}\n```\n\n### But is it fast?\n\nOn my `Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz` I can observe that if I start redis as a test container (which isn't\nthe best idea for performance testing anyway), This application performs as:\n\n```\n~/Projects/tmp $ wrk -t2 -c100 -d10s http://127.0.0.1:8000\nRunning 10s test @ http://127.0.0.1:8000\n  2 threads and 100 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     4.62ms   12.54ms 212.71ms   97.60%\n    Req/Sec    17.23k     5.85k   23.93k    78.79%\n  339750 requests in 10.01s, 14.15MB read\nRequests/sec:  33932.29\nTransfer/sec:      1.41MB\n~/Projects/tmp $ wrk -t2 -c100 -d10s http://127.0.0.1:8000\nRunning 10s test @ http://127.0.0.1:8000\n  2 threads and 100 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     2.48ms    0.98ms  24.25ms   94.57%\n    Req/Sec    20.64k     1.90k   23.65k    94.50%\n  410919 requests in 10.00s, 17.24MB read\nRequests/sec:  41071.70\nTransfer/sec:      1.72MB\n~/Projects/tmp $ \n```\n\nAfter a warm-up cycle of 10s, it can deliver `~41071 req/s`. Not bad, right?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmlopes%2Fhang-around","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmlopes%2Fhang-around","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmlopes%2Fhang-around/lists"}