{"id":20834944,"url":"https://github.com/dvgica/managerial","last_synced_at":"2025-05-08T02:22:02.068Z","repository":{"id":40328281,"uuid":"371870764","full_name":"dvgica/managerial","owner":"dvgica","description":"A zero-dependency Scala library for managing resources monadically","archived":false,"fork":false,"pushed_at":"2025-04-30T14:48:18.000Z","size":463,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-30T15:57:05.616Z","etag":null,"topics":["resource-management","scala"],"latest_commit_sha":null,"homepage":"","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/dvgica.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,"zenodo":null}},"created_at":"2021-05-29T03:28:20.000Z","updated_at":"2025-04-30T14:48:23.000Z","dependencies_parsed_at":"2023-09-28T17:28:42.667Z","dependency_job_id":"fd3775a9-281c-40ed-91be-728c16f029bc","html_url":"https://github.com/dvgica/managerial","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvgica%2Fmanagerial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvgica%2Fmanagerial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvgica%2Fmanagerial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvgica%2Fmanagerial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvgica","download_url":"https://codeload.github.com/dvgica/managerial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252984741,"owners_count":21835845,"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":["resource-management","scala"],"created_at":"2024-11-18T00:21:58.596Z","updated_at":"2025-05-08T02:22:02.014Z","avatar_url":"https://github.com/dvgica.png","language":"Scala","readme":"# Managerial\n[![Maven](https://img.shields.io/maven-central/v/ca.dvgi/managerial_2.13?color=blue)](https://search.maven.org/search?q=g:ca.dvgi%20managerial) [![CI](https://img.shields.io/github/actions/workflow/status/dvgica/managerial/ci.yml?branch=main)](https://github.com/dvgica/managerial/actions)\n\nManagerial is a small, dependency-free library providing `Managed`, a composable type for setting up and tearing down `Resource`s.\n\n- [Motivation](#motivation)\n- [Installation](#installation)\n- [Usage](#usage)\n  * [Basic Automatic Resource Management Example](#basic-automatic-resource-management-example)\n  * [Composed Resources Example](#composed-resources-example)\n  * [Compatibility with Twitter Util `Managed`](#compatibility-with-twitter-util-managed)\n- [Related Libraries](#related-libraries)\n  * [Twitter Util's `Managed`](#twitter-util-s--managed-)\n  * [Scala ARM](#scala-arm)\n  * [Scala Stdlib `Using`](#scala-stdlib--using-)\n  * [cats-effect `Resource`](#cats-effect--resource-)\n- [Contributing](#contributing)\n\n## Motivation\n\nThis library can aid with basic automatic resource management, that is, automatically closing or tearing down resources once they have been used, regardless of exceptions. In this way, it is similar to Scala's `Using`, Java's `try-with-resources`, etc. This is not very exciting, but perhaps useful in some circumstances.\n\nWhere Managerial really shines is constructing a program in your `main` method. Building a program (especially with manual dependency injection) often requires setup and teardown of various resources which may depend on each other. It's also often useful to have side-effects (e.g. logging) interspersed in this setup and teardown. Doing this construction manually is tedious and error-prone; in particular, developers can easily forget to tear down a resource, or may tear down resources in a different order than they were setup. Any exceptions during setup, usage, or teardown further complicate matters.\n\nManagerial makes these errors impossible by allowing for composition of `Managed` resources in a monadic style (i.e. for comprehensions, `flatMap`, `map`).\n\nNone of the ideas in the lib are particularly novel (see [Related Libraries](#related-libraries)). But, some may find this particular combination of features enticing.\n\n## Installation\n\nManagerial is available on Maven Central for Scala 2.12, 2.13, and 3. There are two artifacts:\n- `managerial`, which provides core functionality\n- `managerial-twitter-util`, which provides [compatibility](#compatibility-with-twitter-util-managed) with Twitter Util's `Managed`\n\nAdd the following dependency description to your build.sbt:\n\n`\"ca.dvgi\" %% \"managerial\" % \"\u003clatest\u003e\"`\n\n## Usage\n\n`Managed[T]` instances are created via `Managed#apply`, `Managed#setup`, or `Managed#from`. Additionally, arbitrary actions can be made into `Managed[Unit]` instances via various `Managed#eval` methods.\n\nMultiple `Managed` instances are composed or stacked via `flatMap`, generally with a for comprehension.\n\nOnce the `Managed` stack is composed, the underlying resources are built and used with `use` or `useUntilShutdown`. Setup occurs in the order of the for comprehension or `flatMap`s, and teardown happens in the reverse order.\n\nNon-fatal exceptions are handled as follows:\n- Exceptions during setup are thrown after already-built resources are torn down\n- Exceptions during usage are thrown after resources are torn down\n- Exceptions during teardown are thrown, but only after teardown is called on every resource.\n- If an exception is thrown during usage, and an additional exception occurs during teardown, the usage exception is thrown with the teardown exception added as a suppressed exception.\n- If an exception is thrown during setup, and an additional exception occurs during teardown, the setup exception is thrown with the teardown exception added as a suppressed exception.\n\nFor more details, see the Scaladocs.\n\n### Basic Automatic Resource Management Example\n\n`file.txt` will be automatically closed after `use`, regardless of exceptions thrown.\n``` scala\nimport ca.dvgi.managerial._\nval fileContents = Managed.from(scala.io.Source.fromFile(\"file.txt\")).use(_.mkString)\n```\n\n### Composed Resources Example\n\nThis is a more full-featured example, showing Managerial's typical use-case.\n\n``` scala\nimport ca.dvgi.managerial._\n\nobject Main extends App {\n\n  val server = for {\n    // create a Managed[Unit] for side effects\n    _ \u003c- Managed.eval(println(\"Starting setup...\"))(println(\"Finished teardown\"))\n\n    // create Managed[Settings] that doesn't require teardown\n    settings \u003c- Managed.setup(Settings(8080, 7070))\n\n    // create Managed[HealthCheckServer], which requires teardown\n    healthCheckServer \u003c- Managed(new HealthCheckServer(settings))(_.stop())\n\n    // Managed#from expects a type class instance for Teardown[T], instead of having teardown specified explicitly.\n    // ca.dvgi.managerial provides Teardown[AutoCloseable].\n    _ \u003c- Managed.from(new ApiServer(settings))\n\n    // once the ApiServer is started, the HealthCheckServer can show it's ready\n    _ \u003c- Managed.eval(healthCheckServer.markReady())(healthCheckServer.markUnready())\n\n    // evalSetup and evalTeardown allow for side-effects during only setup or only teardown\n    _ \u003c- Managed.evalSetup(println(\"Startup is finished!\"))\n  } yield ()\n\n  // builds the Managed stack and registers a JVM shutdown hook to do automatic teardown\n  server.useUntilShutdown()\n}\n\ncase class Settings(healthCheckPort: Int, apiPort: Int)\n\nclass HealthCheckServer(settings: Settings) {\n  println(\"Started HealthCheckServer\")\n  def stop(): Unit = {\n    println(\"Stopped HealthCheckServer\")\n  }\n  def markReady(): Unit = println(\"Marked HealthCheckServer Ready\")\n  def markUnready(): Unit = println(\"Marked HealthCheckServer Unready\")\n}\n\nclass ApiServer(settings: Settings) extends AutoCloseable {\n  import scala.concurrent.ExecutionContext.Implicits.global\n  import scala.concurrent.duration.Duration\n  import scala.concurrent.Await\n  import scala.concurrent.Future\n  val fakeServer = new Thread {\n    override def run: Unit = {\n      Await.ready(Future.never, Duration.Inf)\n    }\n  }\n  fakeServer.start()\n  println(\"Started ApiServer\")\n  def close(): Unit = {\n    println(\"Stopped ApiServer\")\n  }\n}\n\n```\n\nWhen run, this program outputs:\n\n```\nStarting setup...\nStarted HealthCheckServer\nStarted ApiServer\nMarked HealthCheckServer Ready\nStartup is finished!\n^C\nMarked HealthCheckServer Unready\nStopped ApiServer\nStopped HealthCheckServer\nFinished teardown\n```\n\n### Compatibility with Twitter Util `Managed`\n\nThe `managerial-twitter-util` artifact provides `asManagerial` for `com.twitter.util.Managed`, and `asTwitterUtil` for `ca.dvgi.managerial.Managed`.\n\nImport `ca.dvgi.managerial.twitter.util._` to use these methods.\n\n## Related Libraries\n\n### Twitter Util's `Managed`\n\nManagerial is very similar in style to Twitter Util's [`Managed`](https://twitter.github.io/util/docs/com/twitter/util/Managed.html), and borrows a lot of code from it.\n\nUnlike the Twitter Util library, Managerial:\n- does not have any dependencies apart from the Scala stdlib\n- does not allow for asynchronous resource disposal/release\n- attempts to expose a better API for constructing instances of `Managed`\n- works with `AutoCloseable` out-of-the-box\n- handles additional exceptions during teardown by adding them as suppressed exceptions to the original exception\n\n### Scala ARM\n\nManagerial is also quite similar to [Scala ARM](https://github.com/jsuereth/scala-arm).\n\nUnlike Scala ARM, Managerial:\n- is (officially) published for Scala 2.13 and 3\n- lacks some of the \"fancy\" features, like Delimited Continuation style, reflection-based teardown, or JTA transaction support\n\n### Scala Stdlib `Using`\n\nUnlike Scala's [`Using`](https://www.scala-lang.org/api/2.13.3/scala/util/Using$.html), Managerial:\n- is available for Scala 2.12\n- can be used in `for` comprehensions, similar to Twitter Util's `Managed`\n- does not require constructing `Releaseable` type class instances for each resource that is not `AutoCloseable`\n- allows for easily encoding side-effects into teardown (e.g. `adminServer.markUnready()` in the above [example](#composed-resources-example))\n\n### cats-effect `Resource`\n\nUnlike cats-effect's [`Resource`](https://typelevel.org/cats-effect/docs/std/resource), Managerial:\n- does not have any dependencies apart from the Scala stdlib\n- does not abstract over effects (you may actually want that, in which case `cats-effect` is a better choice)\n\n## Contributing\n\nContributions in the form of Issues and PRs are welcome.\n","funding_links":[],"categories":["Table of Contents"],"sub_categories":["Misc"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvgica%2Fmanagerial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvgica%2Fmanagerial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvgica%2Fmanagerial/lists"}