Giter VIP home page Giter VIP logo

jobim's Introduction

jobim

An actors library for Clojure modelled after Erlang OTP plaform.

External dependencies

Jobim has two dependencies:

  • Directory service: ZooKeeper
  • Messaging system: RabbitMQ/ZeroMQ

RabbitMQ or ZeroMQ both can be used as the underlying messaging solution. In order to use Jobim, ZeroMQ java bindings must be installed, including the native jni library.

Basic usage

starting a node : jobim/bootstrap-node

A path to a configuration file must be provided. The path must include the name of the node, the selected messaging mechanism and configuration options for RabbitMQ, ZeroMQ and ZooKeeper.

This is a sample configuration file:

;; RabbitMQ used
{:node-name "remote-test"
 :messaging-type :rabbitmq
 :messaging-options {:host "192.168.1.35"}
 :zookeeper-options ["192.168.1.35:2181" {:timeout 3000}]}

 This is a configuration file for ZeroMQ:

{:node-name "remote-test"
 :messaging-type :zeromq
 :messaging-options {:protocol-and-port "tcp://192.168.1.35:5555"}
 :zookeeper-options ["localhost:2181" {:timeout 3000}]}

Checking available nodes : jobim/nodes jobim/resolve-node-name

The nodes function returns a map with all the node names and their identifiers. The function resolve-node-name can be used to retrieve the indetifier of a node provided its name.

=> (use 'jobim)

nil

=> (bootstrap-node "node-config.clj")

"6811651bd83e4d428359b419e7f76a75"

=> (nodes)

{"osx" "5299491ea4184c02ad8c0fbc100c49f9", "linux" "6811651bd83e4d428359b419e7f76a75"}

Agent creation : jobim/spawn

We can define an actor using any Clojure function and the spawn function.

; A Sample echo actor
(defn ping
  ([]
     (loop [continue true
            msg (receive)]
       (cond-match
        [#"exit" msg]       (recur false msg)
        [#"exception" msg]  (throw (Exception.
                                     (str "Ping actor with PID:"
                                          (self)
                                          "received exception")))
        [[?from ?data] msg] (do (send! from data)
                            (recur true (receive)))))))

Creation of the actor:

=> (def *pid* (spawn examples/ping))

#'clojure.core/*pid*

=> *pid*

"5299491ea4184c02ad8c0fbc100c49f9.1"

Transforming a thread into an actor : jobim/spawn-in-repl

The REPL or any other thread can become an actor calling spawn-in-repl from the code being executed in the thread:

=> (spawn-in-repl)

"5299491ea4184c02ad8c0fbc100c49f9.2"

=> (send! *pid* [(self) 13123])

:ok

=> (receive)

13123

Sending and receiving : jobim/send! jobim/receive

This couple of function can be used to send and receive messages to and from actors. The PID of the actor must be provided. By default, any serializable java object can be send and retrieved.

=> (send! pid [(self) (java.util.Date.)]) :ok

=> (receive)

#<Date Fri Sep 03 13:20:26 CEST 2010>

RPC calls : jobim/rpc-call jobim/rpc-blocking-call

Used to execute a function call in a remote node. They can be used to spawn remote actors and retrieve the PID (using the blocking variant).

=> (nodes)

{"osx" "5299491ea4184c02ad8c0fbc100c49f9", "linux" "6811651bd83e4d428359b419e7f76a75"}

=> (resolve-node-name "linux")

"6811651bd83e4d428359b419e7f76a75"

=> (rpc-blocking-call (resolve-node-name "linux") "clojure.core/+" [1 2 3 4 5])

15

Spawning a remote actor:

=> (def *pid* (rpc-blocking-call (resolve-node-name "linux") "jobim/spawn" ["jobim.examples.actors/ping"]))

#'clojure.core/*pid*

=> *pid*

"6811651bd83e4d428359b419e7f76a75.1"

=> (send! *pid* [(self) 345])

nil

=> (receive)

345

Registering PIDs : jobim/register-name jobim/registered-names jobim/resolve-name

An actor can be registered with a globally available name using the register-name function. All registered names can be retrieved with the registered-names function.

To transform an actor name into a PID the resolve-name function can be used.

=> (def *ping* (spawn examples/ping))

#'clojure.core/*ping*

=> *ping*

"5299491ea4184c02ad8c0fbc100c49f9.8"

=> (register-name "ping" *ping*)

:ok

=> (registered-names)

{"ping" "5299491ea4184c02ad8c0fbc100c49f9.8"}

=> (resolve-name "ping")

"5299491ea4184c02ad8c0fbc100c49f9.8"

=> (send! (resolve-name "ping") [(self) 1234])

:ok

=> (receive)

1234

Error notifications : jobim/link

Two actors can be linked using the link function. From that moment onwards if one of the actors dies because of an exception or the node where it is being executed becomes unavailable due to a network partition, the other actor will receive a special message containing a signal.

=> (self)

"5299491ea4184c02ad8c0fbc100c49f9.1"

=> (def *pid* (spawn examples/ping))

#'clojure.core/*pid*

=> (link *pid*)

{"5299491ea4184c02ad8c0fbc100c49f9.1" ["5299491ea4184c02ad8c0fbc100c49f9.9"], "5299491ea4184c02ad8c0fbc100c49f9.9" ["5299491ea4184c02ad8c0fbc100c49f9.1"]}

=> ; the ping actor will throw an exception if receives a message containing the

"exception" string

=> (send! *pid* "exception")

:ok

=> (receive)

{:signal :link-broken, :from "5299491ea4184c02ad8c0fbc100c49f9.9", :cause "class java.lang.Exception:Ping actor received exception"}

Threadless actors : jobim/spawn-evented jobim/react-loop jobim/react

To avoid the limitation on the number of java threads that can be created in a single java VM, an evented actor can be created not attached to a single thread.

Functions react-loop and react can be used as subtitues of loop and receive in the code of the evented actor.

The evented actor must be started with the spawn-evented function.

This is an example of the evented actor equivalent to the previously shown echo actor.

(defn ping-evented
  ([]
     (let [name "test evented"]
       (react-loop [c 0]
         (react [msg]
           (cond-match
             [#"exit" msg]       false
             [#"exception" msg]  (throw (Exception. "Ping actor received exception"))
             [[?from ?data] msg] (do
                                   (send! from (str "actor " name " says "data " " c))
                                   (recur (inc c))))))))))

Tests

To run the tests follow the next instructions:

  • edit the test-node.clj file inserting the right configuration.

  • edit test/jobim/test/jobim.clj and select the right communication mechanism:

    (defonce messaging-to-test :rabbitmq)

  • Start the relevant services: ZooKeeper and RabbitMQ/ZeroMQ

  • Start the test node that will execute the test-node.clj configuration:

$ java -cp jobim-0.0.4-SNAPSHOT-standalone.jar -Djava.library.path=/usr/local/lib jobim.main test-node.clj

** Jobim node started **

- node-name: remote-test

- messaging-type :rabbitmq

- messaging-args {:host "192.168.1.35"}

- zookeeper-args ["192.168.1.35:2181" {:timeout 3000}

clojure.core=>

  • Run the tests using

$ lein test

License

Copyright (C) 2010 Antonio Garrote

Distributed under the LGPL

jobim's People

Contributors

antoniogarrote avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.