All Projects → rkuhn → Akka Typed Session

rkuhn / Akka Typed Session

Licence: other
add-on to Akka Typed that tracks effects for use with Session Types

Programming Languages

scala
5932 projects

Projects that are alternatives of or similar to Akka Typed Session

Lagom
Reactive Microservices for the JVM
Stars: ✭ 2,590 (+5410.64%)
Mutual labels:  akka, distributed-systems
Protoactor Dotnet
Proto Actor - Ultra fast distributed actors for Go, C# and Java/Kotlin
Stars: ✭ 1,070 (+2176.6%)
Mutual labels:  akka, distributed-systems
Akkeeper
An easy way to deploy your Akka services to a distributed environment.
Stars: ✭ 30 (-36.17%)
Mutual labels:  akka, distributed-systems
Akka
Build highly concurrent, distributed, and resilient message-driven applications on the JVM
Stars: ✭ 11,938 (+25300%)
Mutual labels:  akka, distributed-systems
nact
nact ⇒ node.js + actors ⇒ your services have never been so µ
Stars: ✭ 1,003 (+2034.04%)
Mutual labels:  distributed-systems, akka
protoactor-go
Proto Actor - Ultra fast distributed actors for Go, C# and Java/Kotlin
Stars: ✭ 4,138 (+8704.26%)
Mutual labels:  distributed-systems, akka
Nact
nact ⇒ node.js + actors ⇒ your services have never been so µ
Stars: ✭ 848 (+1704.26%)
Mutual labels:  akka, distributed-systems
Openagent
An agent library for systems of nested automata.
Stars: ✭ 28 (-40.43%)
Mutual labels:  distributed-systems
Toketi Iothubreact
Akka Stream library for Azure IoT Hub
Stars: ✭ 36 (-23.4%)
Mutual labels:  akka
Lagom Example
Example usage of the Lagom Framework for writing Java-based microservices
Stars: ✭ 20 (-57.45%)
Mutual labels:  akka
Lasp
Prototype implementation of Lasp in Erlang.
Stars: ✭ 876 (+1763.83%)
Mutual labels:  distributed-systems
Docker Airflow
Repo for building docker based airflow image. Containers support multiple features like writing logs to local or S3 folder and Initializing GCP while container booting. https://abhioncbr.github.io/docker-airflow/
Stars: ✭ 29 (-38.3%)
Mutual labels:  distributed-systems
Cachex
A powerful caching library for Elixir with support for transactions, fallbacks and expirations
Stars: ✭ 985 (+1995.74%)
Mutual labels:  distributed-systems
Awesome Scalability
The Patterns of Scalable, Reliable, and Performant Large-Scale Systems
Stars: ✭ 36,688 (+77959.57%)
Mutual labels:  distributed-systems
Dbfs
Distributed Blockchain-based File Storage 📡
Stars: ✭ 45 (-4.26%)
Mutual labels:  distributed-systems
Go Queue
Multi backend queues for Golang
Stars: ✭ 15 (-68.09%)
Mutual labels:  distributed-systems
Spark As Service Using Embedded Server
This application comes as Spark2.1-as-Service-Provider using an embedded, Reactive-Streams-based, fully asynchronous HTTP server
Stars: ✭ 46 (-2.13%)
Mutual labels:  akka
Elixirbooks
List of Elixir books
Stars: ✭ 1,021 (+2072.34%)
Mutual labels:  distributed-systems
Awesome Scalability Toolbox
My opinionated list of products and tools used for high-scalability projects
Stars: ✭ 34 (-27.66%)
Mutual labels:  distributed-systems
Constructr Consul
This library enables to use Consul as cluster coordinator in a ConstructR based node
Stars: ✭ 32 (-31.91%)
Mutual labels:  akka

Build Status

Akka Typed Session

Add-on to Akka Typed that tracks effects for use with Session Types.

Example

Assume this message protocol:

case class AuthRequest(credentials: String)(replyTo: ActorRef[AuthResult])

sealed trait AuthResult
case object AuthRejected extends AuthResult
case class AuthSuccess(token: ActorRef[Command]) extends AuthResult

sealed trait Command
case object DoIt extends Command

The process to be followed is that first an AuthRequest is sent, answered by an AuthResult that may or may not unlock further communication of Command messages. A more formal definition of this sequence is the following:

trait Protocol {
  type Session <: Effects
}

object MyProto extends Protocol {
  type Session = //
    Send[AuthRequest] :: // first ask for authentication
    Read[AuthResult] :: // then read the response
    Choice[(Halt :: _0) :+: _0 :+: CNil] :: // then possibly terminate if rejected
    Send[Command] :: _0 // then send a command
}

Implementing the first part of this exchange is the familiar ask pattern or request–response. We can use the process DSL to factor this out into a utility function:

def opAsk[T, U](target: ActorRef[T], msg: ActorRef[U] => T) =
  OpDSL[U] { implicit opDSL =>
    for {
      self <- opProcessSelf
      _ <- opSend(target, msg(self))
    } yield opRead
  }

Here the OpDSL constructor provides an environment in which the behavior behind a typed ActorRef[U] can be defined. The opProcessSelf is an operation that when run will yield the aforementioned ActorRef[U]. opSend is an operation that when run will send the given message to the given target. As the last step in this mini-protocol opRead awaits the reception of a message sent to self, i.e. the received message will be of type U.

It should be noted that in this process DSL algebra the .map() combinator has the same behavior as .flatMap() where possible, i.e. it will flatten if the returned value is an Operation. This is necessary in order to avoid memory leaks for infinite processing loops (as seen e.g. in server processes that respond to an unbounded number of requests).

Now we can use this ask operation in the context of the larger overall process. Calling such a compound operation is done via the opCall operator.

val auth: ActorRef[AuthRequest] = ??? // assume we get the authentication endpoint from somewhere

val p = OpDSL[String] { implicit opDSL 
  for {
    AuthSuccess(token) <- opCall(opAsk(auth, AuthRequest("secret")).named("getAuth"))
  } yield opSend(token, DoIt)
}

The resulting type of p is not just an Operation with String for the self-type, yielding Unit (the result of opSend), but it also tracks the effects that occur when executing the whole process. We can assert that the externally visible effects of sending and receiving messages match the protocol definition given above by asking the compiler to construct a proof:

def vetProtocol[E <: Effects, F <: Effects](p: Protocol, op: Operation[_, _, E])(
  implicit f: E.ops.FilterAux[E, ExternalEffect, F], ev: F <:< p.Session): Unit = ()

vetProtocol(MyProto, p)

This works in two steps: first the list of effects E (which is somewhat like an HList with a special node for infinite loops) is filtered so that only effects remain that are subtypes of ExternalEffect, yielding the list F. Then this list is compared to the Session type member of the given protocol to see whether it is a subtype.

The result is that the whole program only compiles if the process performs all the required externally visible effects in the right order. If a step is forgotten or duplicated then the vetProtocol invocation will raise a type error.

Legal

See the LICENSE file for details on licensing and CONTRIBUTING for the contributor’s guide.

Copyright 2017 Roland Kuhn

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].