• Stars
    star
    203
  • Rank 191,811 (Top 4 %)
  • Language
    Scala
  • License
    Other
  • Created over 13 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Scalang is a scala wrapper that makes it easy to write services that interface with erlang.

Introduction

Scalang is a message passing and actor library that allows Scala and Erlang applications to easily communicate. Scalang includes a full implementation of the Erlang distributed node protocol. It provides an actor oriented API that can be used to interact with Erlang nodes in an idiomatic, OTP compliant way. Scalang is built on Netty for its networking layer and Jetlang for its actor implementation.

Installation

From Maven:


  <repositories>
    <repository>
      <id>Boundary Public Repo</id>
      <url>http://maven.boundary.com/artifactory/repo</url>
    </repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>com.boundary</groupId>
      <artifactId>scalang-scala_2.9.1</artifactId>
      <version>0.18</version>
    </dependency>
  </dependencies>

From SBT:


  val boundaryPublic = "Boundary Public Repo" at "http://maven.boundary.com/artifactory/repo"

  val scalang = "com.boundary" %% "scalang" % "0.18"

Scalang currently supports Scala 2.9.1. Scalang also requires epmd in order to run.

Usage

Starting

The main entry point for Scalang’s API is the node class. An instance of the Node class is a self contained representation of an Erlang Node, distinct in the set of nodes participating in a distributed system. Multiple nodes may be run within the same JVM. Start a node with the following invocation:


    val node = Node("[email protected]", "cookie")

Starting a Scalang node like this will register it with the local epmd instance, which must be running on the local host. Scalang will then be available to receive and make connections to other Erlang nodes. In this case, its node name would be [email protected] and its magic cookie is cookie. Any Erlang or Scalang node which shares this magic cookie can now connect to this node and send messages using the node name.

Processes

Scalang shares Erlang’s concept of a process, a lightweight actor that is capable of sending messages to other processes, either local or remote. You can define your own processes by subclassing the Process class. The following code defines and then spawns a process:


  class MyProcess(ctx : ProcessContext) extends Process(ctx) {
    override def onMessage(msg : Any) {
      log.info("received %s", msg)
    }
  }

  val pid = node.spawn[MyProcess]("my_process")

  //send to the pid
  node.send(pid, "hey there")

  //send to the regname
  node.send("my_process", "you wanna party?")

Message Passing

Message passing / receiving is the main means by which processes may interact with the outside world. Processes receive messages via the message handler method onMessage. Only one message may be handled by a process at a time unless that process has been spawned with the reentrant option.

The following shows a simple echo server and client that demonstrate message sending.


  class EchoServer(ctx : ProcessContext) extends Process(ctx) {
    override def onMessage(msg : Any) = msg match {
      case (pid : Pid, request : Any) =>
        pid ! request
      case m =>
        log.error("sorry I don't understand %s.", m)
    }
  }


  val server = node.spawn[EchoServer]("echo_server")

  val client = node.spawn { mbox =>
    mbox.send(server, (client,'derp))
    val received = mbox.receive
    println("received " + received)
  }

Messages can also easily be passed from a remote node. Scalang supports Erlang’s convention of addressing messages to the tuple of a registered name and a node name.


  val remoteNode = Node("remote", cookie)
  val client = node.spawn { mbox =>
    mbox.send(('echo_server, Symbol("test@localhost")), "heyo!")
  }

The above code will send a message to the process registered as “echo_server” on the node named “test@localhost”.

Error Handling

Scalang implements the Erlang concept of links. A link is a bidirectional relationship between two processes. If one of the processes exits the link will break and the other process will receive an exit notification. The default behavior of a process during exit notification is for the receiving process to exit with the same error message that was delivered with the link breakage. Creating a link between two processes requires both pids.

Processes that must implement custom behavior may override the trapExit method.


  class ExitHandler(ctx : ProcessContext) extends Process(ctx) {
    override def onMessage(msg : Any) = msg match {
      case _ => log.info("derp %s", msg)
    }

    override def trapExit(from : Pid, msg : Any) {
      log.warning("got exit notification from %s reason %s", from, msg)
    }
  }

Serialization

Scalang messages are serialized into Erlang’s external term format. Serialization automatically happens when messages are either sent from or received by a Scalang process. For the most part Scalang provides a 1-1 mapping of Erlangs terms onto Scala types. The type mappings are illustrated below.

From Erlang To Scala
Small Integer Int
Integer Int
Float Double
Boolean Boolean
Atom Symbol
Reference Reference
Port Port
Pid Pid
Small Tuple Tuple
Large Tuple BigTuple
String String
List List
Binary ByteBuffer
Small Bignum Long
Large Bignum BigInt
Fun Fun
Bistring Bitstring
From Scala To Erlang
Byte Small Integer
Int Integer
Long Small Bignum
Double Float
Symbol Atom
Reference Reference
Port Port
Pid Pid
Fun Fun
String String
List List
BigInteger Large Bignum
Array[Byte] Binary
ByteBuffer Binary
BitString Bitstring
Tuple Tuple
BigTuple Tuple

Rich Type Mappings

Sometimes the built-in type mappings in Scalang are not sufficient for an application’s message format. Scalang provides the TypeFactory trait for client code to provide custom decoding behavior. A TypeFactory is invoked when Scalang comes across a term that looks like an erlang record: a tuple where the first element is an atom. The createType method is called with the first tuple element as the name and the arity of the tuple.


  object StructFactory extends TypeFactory {
    def createType(name : Symbol, arity : Int, reader : TermReader) : Option[Seq[Any]] = {
      try {
        reader.mark
        (name,arity) match {
          case ('struct,2) => Some(readMap(reader))
          case _ => None
        }
      }
    }

    protected def readSeq(reader : TermReader) : Map[Symbol,Any] = {
      val proplist = reader.readAs[List[Symbol,Any]]
      proplist.toMap
    }
  }

  val node = Node("test", cookie, NodeConfig(
    typeFactory = StructFactory))

The above code will spawn a Scalang node that uses the StructFactory singleton to decode into a map any arity 2 tuples that begin with the atom struct. Anything else will get decoded with the normal type mappings.

A more complex example is the CaseClassFactory. It will attempt to decode Erlang records into Scala case classes reflectively.

Services

Most modern Erlang applications are built using the OTP framework, and in particular the gen_server. In order to more effectively interface with gen_server based processes, Scalang has a special kind of process known as a service. Services respond to casts and calls like a gen_server and allow you to send casts and calls to gen_servers running in an Erlang VM.


  case class EchoServiceArgs(name : String)
  class EchoService(ctx : ServiceContext[EchoServiceArgs]) extends Service(ctx) {
    val EchoServiceArgs(name) = ctx.args

    override def handleCall(tag: (Pid, Reference), request: Any): Any = { 
      name + " " + request
    }   

    override def handleCast(request : Any) {
      log.info("Can't echo a cast. %s", request)
    }   

    override def handleInfo(request : Any) {
      log.info("A wild message appeared. %s, request")
    }   
  }

  val node = Node("test", cookie)
  val pid = node.spawnService[EchoService, EchoServiceArgs]("echo", EchoServiceArgs("test_echo"))

This will spawn a new process with the registered name “echo” and it will be initialized with the argument “test_echo”. The handleCall method will automatically send its return value to the caller. Casts are meant to be one directional, therefore the return value of handleCast is discarded. The handleInfo method is invoked when a message shows up without the appropriate call or cast semantics.

Roadmap

Upgrade Node Protocol

Scalang uses the same version of Erlang’s node protocol as JInterface. This means that for some operations Scalang nodes are not treated as full fledged members of the cluster. For instance, features like monitors and atom caches are not currently supported. Additionally, Scalang nodes will appear as hidden nodes. This is disadvantageous for Scalang’s goal of transparent interoperability.

Supervision Trees

Scalang needs its own implementation of Erlang OTP’s supervision tree. All of the primitives are in place to support supervision trees currently, so an implementation of the actual supervisor process is all that’s needed.

Pre-emptable Actors

Scalang uses Jetlang’s thread pool based actor implementation. There is currently no API for pre-empting these types of Jetlang actors. Therefore either Jetlang needs to be patched to allow this or another actor backend needs to be chosen.

More Repositories

1

folsom

Expose Erlang Events and Metrics
Erlang
587
star
2

flake

A decentralized, k-ordered id generation service in Erlang
Erlang
573
star
3

high-scale-lib

A fork of Cliff Click's High Scale Library. Improved with bug fixes and a real build system.
Java
408
star
4

ordasity

Ordasity is Boundary's library for building stateful clustered services on the JVM.
Scala
343
star
5

wireshark

wireshark + boundary IPFIX decode patches
C
165
star
6

fasttuple

Java
142
star
7

firespray

Blazingly fast streaming charts
JavaScript
106
star
8

html5-node-diagram

JavaScript
86
star
9

bear

a set of statistics functions for erlang
Erlang
68
star
10

overlock

Boundary's suite of concurrent scala utilities.
Scala
67
star
11

gen_lb

A generic library to load balance communication between Erlang nodes
Erlang
64
star
12

zoocreeper

A ZooKeeper backup tool.
Java
49
star
13

folsom_cowboy

A Cowboy based Folsom HTTP Wrapper.
Erlang
39
star
14

libdnet

updated fork of libdnet from https://code.google.com/p/libdnet/
C
39
star
15

folsom_webmachine

folsom based metrics via HTTP and JSON
Erlang
37
star
16

small_wonder

A Deployment Tool
Ruby
25
star
17

knife-plugins

Ruby
21
star
18

khial

a fake network driver to test network applications
C
19
star
19

atomicmap_challenge

A multithreaded scala programming challenge.
Scala
16
star
20

winpcap-installer

fork of the NMAP's silent WinPCAP installer
NSIS
13
star
21

labs-graphs

JavaScript
13
star
22

boundary_scripts

Shell
12
star
23

archaius-consul

A consul-backed configuration source for Archaius
Java
10
star
24

childspec_validator

Verify your Erlang childspecs before you use them.
Erlang
7
star
25

bprobe_cookbook

The Boundary bprobe cookbook.
Ruby
7
star
26

pulse-api-cli

Command line tools for Boundary APIs
Python
6
star
27

chef-boundary-annotations-handler

Chef exception handler for adding annotations to Boundary.
Ruby
5
star
28

boundary-event-plugins

Python
4
star
29

meter-plugin-rabbitmq

Metrics Plugin for RabbitMQ
Java
4
star
30

dw-consul

Tools for integrating consul with dropwizard applications.
Java
4
star
31

dropwizard-kafka

Kotlin
3
star
32

meter-plugin-sdk-lua

This is the framework for making the creation and maintenance of plugins easy.
Lua
3
star
33

boundary_splunk_app

A Splunk App for integration with Boundary
Python
3
star
34

meter-plugin-sdk-java

Java framework for creating plugins
Java
3
star
35

boundary-client-js

JavaScript
3
star
36

ibrowse

Erlang
3
star
37

boundary-vmware

Boundary Enterprise Integration with VMWare
Java
3
star
38

boundary-plugin-disk-summary

Disk Summary Plugin
Lua
2
star
39

boundary-plugin-lua-test

Repo for testing the LUA plugin framework
Lua
2
star
40

jenkins-boundary-annotations-plugin

Java
2
star
41

boundary_puppet

Boundary Meter puppet module
Puppet
2
star
42

java-streaming-client-example

A Java WebSocket client example for the Boundary Streaming API
Java
2
star
43

boundary-vagrant-snmp

Environment for testing SNMP integrations and plugins
Puppet
2
star
44

meter-plugin-zookeeper

Lua
2
star
45

meter-plugin-docker

Lua
2
star
46

chef-boundary-events-handler

Ruby
2
star
47

dataCommander

Data manager using Backbone: query, cache, merge
JavaScript
2
star
48

boundary-meter_cookbook

Boundary Meter Chef Cookbook
Ruby
2
star
49

boundary-plugin-aws-elb

Plugin that extracts metrics from AWS Cloud Watch on ELBs(Elastic Load Balancers)
Python
2
star
50

boundary-event-sdk

Boundary Event SDK
Java
2
star
51

meter-plugin-developer-guide

Documentation on how to development and deploy Boundary metric plugins
Makefile
2
star
52

boundary-plugin-aws-rds

Collects metrics from the Amazon Relational Database Service (RDS)
Python
2
star
53

meter-plugin-nginx-plus

This plugin is for Nginx+ Users to Monitor Nginx
Lua
2
star
54

jenkins-boundary-event-plugin

Java
1
star
55

boundary-plugin-syslog

Boundary Plugin for Syslog
1
star
56

meter-plugin-activemq

Collect metrics from an active MQ instance
Lua
1
star
57

meter-plugin-snmp

Boundary Plugin for SNMP
1
star
58

boundary-plugin-consul-healthchecks

Queries Consul health checks and returns events to Boundary on a status change of a given health check
Lua
1
star
59

boundary-plugin-diskrw_summary

Lua
1
star
60

webhook-action-example

Provides an example of the handling of the webhook call from a Boundary action
1
star
61

vagrant-plugin-dev-env

Vagrant environment for developing plugins
Shell
1
star
62

meter-plugin-wmi

Lua
1
star
63

ZenPacks.boundary.EventAdapter

Zenoss 4.x event adapter for Boundary
Python
1
star
64

meter-plugin-apache-tomcat

Java
1
star
65

libstatsite

C
1
star
66

meter-plugin-solr

Lua
1
star
67

plugin-flask

boundary meter flask plugin
Lua
1
star
68

meter-plugin-cassandra

Collects metrics from a cassandra instance
Java
1
star
69

boundary-plugin-elasticsearch

Collects metrics from a elasticsearch
Lua
1
star
70

boundary-plugin-riak

Plugin for extracting metrics from a Riak instance.
Lua
1
star
71

boundary-plugin-aws-redshift

Collects metrics from Amazon Redshift
Python
1
star
72

meter-plugin-windows-process

PowerShell
1
star
73

tsi-lab

Virtual machine for examples on getting data into TrueSight Intelligence
Python
1
star
74

boundary-action-handler

Endpoint to handle actions from Boundary Premimum
Java
1
star
75

meter-plugin-hello-world-lua

Example plugin in "Hello World" fashion.
Lua
1
star
76

meter-plugin-http

Meter plugin to measure http request page load
Python
1
star