{"id":16697267,"url":"https://github.com/iravid/managedt","last_synced_at":"2025-03-21T19:32:04.918Z","repository":{"id":57725383,"uuid":"123479184","full_name":"iravid/managedt","owner":"iravid","description":"A monad for resource acquisition and cleanup","archived":false,"fork":false,"pushed_at":"2018-09-12T18:18:08.000Z","size":28,"stargazers_count":53,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-18T04:18:47.466Z","etag":null,"topics":[],"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/iravid.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-01T18:58:16.000Z","updated_at":"2025-02-14T23:11:33.000Z","dependencies_parsed_at":"2022-09-11T20:30:32.276Z","dependency_job_id":null,"html_url":"https://github.com/iravid/managedt","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iravid%2Fmanagedt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iravid%2Fmanagedt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iravid%2Fmanagedt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iravid%2Fmanagedt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iravid","download_url":"https://codeload.github.com/iravid/managedt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244855557,"owners_count":20521659,"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-12T17:46:50.883Z","updated_at":"2025-03-21T19:32:04.535Z","avatar_url":"https://github.com/iravid.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deprecated\n\nWith cats-effect 1.0.0 out, this library is now redundant. The [`Resource`](https://typelevel.org/cats-effect/datatypes/resource.html) data type provides equivalent functionality.\n\n[![Build Status](https://travis-ci.org/iravid/managedt.svg?branch=master)](https://travis-ci.org/iravid/managedt)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.iravid/managedt_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.iravid/managedt_2.12)\n\n# ManagedT: a monad for resource management\n\n`ManagedT[F[_], A]` is a monad for constructing computations that acquire and\nrelease resources. It is a translation of Gabriel Gonzalez'\n[managed](https://hackage.haskell.org/package/managed) library, with the\ndifference that this library abstracts over the effect type.\n\nThis library only contains typeclass instances for\n[cats](github.com/typelevel/cats). Scalaz already contains the `Codensity` data\ntype which can serve the same functionality (with, albeit, some additional\nplumbing for cleanup handlers).\n\n## IMPORTANT CAVEATS\n\nThis library supports any `F[_]` that has `MonadError[F, Throwable]`. That\nincludes `monix.eval.Task`, `cats.effect.IO`, `scala.concurrent.Future` (and\nothers). \n\nHowever, it is very likely to be broken if:\n- you use cancellation with `Task` or `IO` - `MonadError` is not strong enough to express\n  bracketing with cancellation, so that'll have to wait for `MonadBracket` in\n  `cats-effect`;\n- you use it with a monad transformer such as `EitherT[IO, E, A]`, where there\n  are several \"layers\" in which errors could be thrown;\n- you throw exceptions in the acquire or cleanup actions that are not sequenced\n  into the `F[_]`;\n- you pass `Future` values that have already been executed in the acquire or\n  cleanup functions. The library has constructors with by-name values in most\n  places to assist with that.\n\nOther than that, it's all good ;-) The test suite exercises the common usecases;\nyou are welcome to have a look.\n\n## Usage\n\n### SBT\n\n```scala\nlibraryDependencies += ״com.iravid\" %% \"managedt\" % \"0.1\"\n```\n\n### In your project\n\nFirst, create some resources:\n\n```scala\nimport com.iravid.managedt.ManagedT\n// import com.iravid.managedt.ManagedT\n\nimport monix.eval.Task\n// import monix.eval.Task\n\nval resource1 = ManagedT(Task { println(\"Acquiring 1\"); 1 })(r =\u003e Task(println(s\"Cleaning $r\")))\n// resource1: com.iravid.managedt.ManagedT[monix.eval.Task,Int] = com.iravid.managedt.ManagedT$$anon$4@23497a65\n\nval resource2 = ManagedT(Task { println(\"Acquiring 2\"); 2 })(r =\u003e Task(println(s\"Cleaning $r\")))\n// resource2: com.iravid.managedt.ManagedT[monix.eval.Task,Int] = com.iravid.managedt.ManagedT$$anon$4@42716335\n```\n\nCompose them - `ManagedT[F, R]` is a monad in `R`, so you can use the usual forms of composition:\n```scala\nimport cats.implicits._\n// import cats.implicits._\n\nval zipped = (resource1, resource2).tupled\n// zipped: com.iravid.managedt.ManagedT[monix.eval.Task,(Int, Int)] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@6d555633\n\nval added = for {\n  r1 \u003c- resource1\n  r2 \u003c- resource2\n} yield r1 + r2\n// added: com.iravid.managedt.ManagedT[monix.eval.Task,Int] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@228720d0\n\nval resources = (1 to 10).toList traverse { r =\u003e\n  ManagedT(Task { println(s\"Acquiring $r\"); r})(r =\u003e Task(println(s\"Cleaning $r\")))\n}\n// resources: com.iravid.managedt.ManagedT[monix.eval.Task,List[Int]] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@346d3ee3\n```\n\nAnd, finally, use your acquired resource in a function of the form `R =\u003e F[A]`:\n```scala\nval zippedUsage = zipped { case (r1, r2) =\u003e \n  Task {\n    println(\"Using zipped\"); r1 + r2 \n  }\n}\n// zippedUsage: monix.eval.Task[Int] = Task.FlatMap$1596984844\n\nval addedUsage = added { r =\u003e \n  Task {\n    println(\"Using added\"); r * r \n  }\n}\n// addedUsage: monix.eval.Task[Int] = Task.FlatMap$757626346\n\nval resourcesUsage = resources { rs =\u003e \n  Task {\n    println(\"Using resources\")\n    rs.sum \n  }\n}\n// resourcesUsage: monix.eval.Task[Int] = Task.FlatMap$1046714810\n```\n\nAs we're using `Task`, nothing has actually run yet; we've composed programs that use the resources safely. Let's see what happens when we run them:\n\n```scala\nimport monix.execution.Scheduler\nimplicit val scheduler = Scheduler.singleThread(name=\"tut\")\n```\n\n```scala\nimport scala.concurrent.Await\n// import scala.concurrent.Await\n\nimport scala.concurrent.duration._\n// import scala.concurrent.duration._\n\nAwait.result(zippedUsage.runAsync, 5.seconds)\n// Acquiring 1\n// Acquiring 2\n// Using zipped\n// Cleaning 2\n// Cleaning 1\n// res0: Int = 3\n```\n\nThe program constructed by `ManagedT[F, A]` properly acquires and releases resources in the right order. This also works for the traversed list of resources:\n```scala\nAwait.result(resourcesUsage.runAsync, 5.seconds)\n// Acquiring 1\n// Acquiring 2\n// Acquiring 3\n// Acquiring 4\n// Acquiring 5\n// Acquiring 6\n// Acquiring 7\n// Acquiring 8\n// Acquiring 9\n// Acquiring 10\n// Using resources\n// Cleaning 10\n// Cleaning 9\n// Cleaning 8\n// Cleaning 7\n// Cleaning 6\n// Cleaning 5\n// Cleaning 4\n// Cleaning 3\n// Cleaning 2\n// Cleaning 1\n// res1: Int = 55\n```\n\nShould one of the acquires, clean-ups or uses fail, the clean-ups will still run properly:\n```scala\nval acquireFailure = for {\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 1\") })\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 2\")})\n  _ \u003c- ManagedT(Task.raiseError(new Exception))((_: Unit) =\u003e Task { println(\"Cleaning 3\") })\n} yield ()\n// acquireFailure: com.iravid.managedt.ManagedT[monix.eval.Task,Unit] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@de37d32\n\nAwait.result(acquireFailure(_ =\u003e Task.unit).attempt.runAsync, 5.seconds)\n// Cleaning 2\n// Cleaning 1\n// res2: Either[Throwable,Unit] = Left(java.lang.Exception)\n\nval useFailure = for {\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 1\") })\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 2\")})\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 3\") })\n} yield ()\n// useFailure: com.iravid.managedt.ManagedT[monix.eval.Task,Unit] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@6c1de753\n\nAwait.result(useFailure(_ =\u003e Task.raiseError(new Exception())).attempt.runAsync, 5.seconds)\n// Cleaning 3\n// Cleaning 2\n// Cleaning 1\n// res3: Either[Throwable,Nothing] = Left(java.lang.Exception)\n\nval cleanupFailure = for {\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 1\") })\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task.raiseError(new Exception()))\n  _ \u003c- ManagedT(Task.unit)(_ =\u003e Task { println(\"Cleaning 3\") })\n} yield ()\n// cleanupFailure: com.iravid.managedt.ManagedT[monix.eval.Task,Unit] = com.iravid.managedt.ManagedT$$anon$1$$anon$5@1417b95d\n\nAwait.result(cleanupFailure(_ =\u003e Task.unit).attempt.runAsync, 5.seconds)\n// Cleaning 3\n// Cleaning 1\n// res4: Either[Throwable,Unit] = Left(java.lang.Exception)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firavid%2Fmanagedt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Firavid%2Fmanagedt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firavid%2Fmanagedt/lists"}