{"id":20394426,"url":"https://github.com/rkuhn/akka-typed-session","last_synced_at":"2025-04-12T12:12:45.144Z","repository":{"id":48669854,"uuid":"80951254","full_name":"rkuhn/akka-typed-session","owner":"rkuhn","description":"add-on to Akka Typed that tracks effects for use with Session Types","archived":false,"fork":false,"pushed_at":"2021-07-15T00:29:53.000Z","size":81,"stargazers_count":50,"open_issues_count":5,"forks_count":7,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-12T12:12:40.134Z","etag":null,"topics":["akka","distributed-systems","scala","session-types"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rkuhn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-04T21:56:15.000Z","updated_at":"2024-03-17T22:57:08.000Z","dependencies_parsed_at":"2022-09-07T18:32:17.019Z","dependency_job_id":null,"html_url":"https://github.com/rkuhn/akka-typed-session","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/rkuhn%2Fakka-typed-session","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkuhn%2Fakka-typed-session/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkuhn%2Fakka-typed-session/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkuhn%2Fakka-typed-session/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rkuhn","download_url":"https://codeload.github.com/rkuhn/akka-typed-session/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248565079,"owners_count":21125417,"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":["akka","distributed-systems","scala","session-types"],"created_at":"2024-11-15T03:53:03.868Z","updated_at":"2025-04-12T12:12:45.118Z","avatar_url":"https://github.com/rkuhn.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/rkuhn/akka-typed-session.svg?branch=master)](https://travis-ci.org/rkuhn/akka-typed-session)\n\n# Akka Typed Session\n\nAdd-on to Akka Typed that tracks effects for use with Session Types.\n\n## Example\n\nAssume this message protocol:\n\n~~~scala\ncase class AuthRequest(credentials: String)(replyTo: ActorRef[AuthResult])\n\nsealed trait AuthResult\ncase object AuthRejected extends AuthResult\ncase class AuthSuccess(token: ActorRef[Command]) extends AuthResult\n\nsealed trait Command\ncase object DoIt extends Command\n~~~\n\nThe process to be followed is that first an `AuthRequest` is sent, answered by\nan `AuthResult` that may or may not unlock further communication of `Command`\nmessages. A more formal definition of this sequence is the following:\n\n~~~scala\ntrait Protocol {\n  type Session \u003c: Effects\n}\n\nobject MyProto extends Protocol {\n  type Session = //\n    Send[AuthRequest] :: // first ask for authentication\n    Read[AuthResult] :: // then read the response\n    Choice[(Halt :: _0) :+: _0 :+: CNil] :: // then possibly terminate if rejected\n    Send[Command] :: _0 // then send a command\n}\n~~~\n\nImplementing the first part of this exchange is the familiar ask pattern or request–response.\nWe can use the process DSL to factor this out into a utility function:\n\n~~~scala\ndef opAsk[T, U](target: ActorRef[T], msg: ActorRef[U] =\u003e T) =\n  OpDSL[U] { implicit opDSL =\u003e\n    for {\n      self \u003c- opProcessSelf\n      _ \u003c- opSend(target, msg(self))\n    } yield opRead\n  }\n~~~\n\nHere the `OpDSL` constructor provides an environment in which the behavior behind a typed\n`ActorRef[U]` can be defined. The `opProcessSelf` is an operation that when run will yield\nthe aforementioned `ActorRef[U]`. `opSend` is an operation that when run will send the given\nmessage to the given target. As the last step in this mini-protocol `opRead` awaits the\nreception of a message sent to `self`, i.e. the received message will be of type `U`.\n\n*It should be noted that in this process DSL algebra the `.map()` combinator has the same behavior\nas `.flatMap()` where possible, i.e. it will flatten if the returned value is an `Operation`. This\nis necessary in order to avoid memory leaks for infinite processing loops (as seen e.g. in\nserver processes that respond to an unbounded number of requests).*\n\nNow we can use this ask operation in the context of the larger overall process. Calling such\na compound operation is done via the `opCall` operator.\n\n~~~scala\nval auth: ActorRef[AuthRequest] = ??? // assume we get the authentication endpoint from somewhere\n\nval p = OpDSL[String] { implicit opDSL ⇒\n  for {\n    AuthSuccess(token) \u003c- opCall(opAsk(auth, AuthRequest(\"secret\")).named(\"getAuth\"))\n  } yield opSend(token, DoIt)\n}\n~~~\n\nThe resulting type of `p` is not just an Operation with `String` for the self-type, yielding `Unit` (the result of `opSend`), \nbut it also tracks the effects that occur when executing the whole process. We can assert that the externally visible effects\nof sending and receiving messages match the protocol definition given above by asking the compiler to construct a proof:\n\n~~~scala\ndef vetProtocol[E \u003c: Effects, F \u003c: Effects](p: Protocol, op: Operation[_, _, E])(\n  implicit f: E.ops.FilterAux[E, ExternalEffect, F], ev: F \u003c:\u003c p.Session): Unit = ()\n\nvetProtocol(MyProto, p)\n~~~\n\nThis works in two steps: first the list of effects E (which is somewhat like an HList with a special node for infinite loops)\nis filtered so that only effects remain that are subtypes of `ExternalEffect`, yielding the list F. Then this list is compared\nto the `Session` type member of the given protocol to see whether it is a subtype.\n\nThe result is that the whole program only compiles if the process performs all the required externally visible effects in\nthe right order. If a step is forgotten or duplicated then the `vetProtocol` invocation will raise a type error.\n\n## Legal\n\nSee the LICENSE file for details on licensing and CONTRIBUTING for the contributor’s guide.\n\nCopyright 2017 Roland Kuhn\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkuhn%2Fakka-typed-session","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frkuhn%2Fakka-typed-session","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkuhn%2Fakka-typed-session/lists"}