All Projects → MyMedsAndMe → spell

MyMedsAndMe / spell

Licence: Apache-2.0 license
Spell is a Web Application Messaging Protocol (WAMP) client implementation in Elixir. WAMP is an open standard WebSocket subprotocol that provides two application messaging patterns in one unified protocol: Remote Procedure Calls + Publish & Subscribe: http://wamp.ws/

Programming Languages

elixir
2628 projects
HTML
75241 projects

Labels

Projects that are alternatives of or similar to spell

spring-data-starter
⚡️ A sample Spring Data Cassandra REST API
Stars: ✭ 36 (-43.75%)
Mutual labels:  dev
overflow-news
📚 Don't waste time searching for good dev blog posts. Get the latest news here.
Stars: ✭ 32 (-50%)
Mutual labels:  dev
growth.dev
[EVENT] API & IPA
Stars: ✭ 46 (-28.12%)
Mutual labels:  dev
J.A.R.V.I.S
Just A Rather Very Intelligent System
Stars: ✭ 36 (-43.75%)
Mutual labels:  dev
exploit
Collection of different exploits
Stars: ✭ 153 (+139.06%)
Mutual labels:  dev
reactcci
React create component interactive CLI
Stars: ✭ 49 (-23.44%)
Mutual labels:  dev
hacktoberfest2021-Excluded
You can submit any PR and have SWAGS. Happy Hacktoberfest !
Stars: ✭ 63 (-1.56%)
Mutual labels:  dev
Awesomo
Cool open source projects written in C, C++, Clojure, Lisp, Elixir, Erlang, Elm, Golang, Haskell, JavaScript, Lua, OCaml, Python, R, Ruby, Rust, Scala, etc.
Stars: ✭ 8,237 (+12770.31%)
Mutual labels:  dev
Hacktoberfest-2021
Create Hacktoberfest PRs. Star this Repo!⭐
Stars: ✭ 32 (-50%)
Mutual labels:  dev
Dev-Geeks
Open Source Project
Stars: ✭ 16 (-75%)
Mutual labels:  dev
laravel-web-logs
View Laravel File-Based Logs In Web
Stars: ✭ 162 (+153.13%)
Mutual labels:  dev
pug-server
🐶 A simple pug server
Stars: ✭ 19 (-70.31%)
Mutual labels:  dev
Clean-macOS
💻 A simple script to setup a clean environment on macOS
Stars: ✭ 155 (+142.19%)
Mutual labels:  dev
hacktoberfest-2019
You can check the video here: #hacktoberfest
Stars: ✭ 28 (-56.25%)
Mutual labels:  dev
webpack-plugin-ramdisk
🐏 A webpack plugin for blazing fast builds on a RAM disk / drive
Stars: ✭ 118 (+84.38%)
Mutual labels:  dev
astra-tik-tok
A simple Tik Tok clone running on AstraDB that leverages the Document API.
Stars: ✭ 21 (-67.19%)
Mutual labels:  dev
android-trinity
android-trinity is tiny proactive framework with much of the scaffolding code required to start a new Android Application.
Stars: ✭ 44 (-31.25%)
Mutual labels:  dev
Devspace
DevSpace - The Fastest Developer Tool for Kubernetes ⚡ Automate your deployment workflow with DevSpace and develop software directly inside Kubernetes.
Stars: ✭ 2,559 (+3898.44%)
Mutual labels:  dev
MMORPGMaker-MV
Plugin to transform RPG Maker MV to MMORPG Maker MV
Stars: ✭ 67 (+4.69%)
Mutual labels:  dev
ReSwiftMonitor
ReSwift+redeux dev tools
Stars: ✭ 13 (-79.69%)
Mutual labels:  dev

spell [DEPRECATED]

Spell is an Elixir WAMP client implementing the basic profile specification.

Reason for fork

For spellchecking old symposium

Oficial readme

Why WAMP?

WAMP is the Web Application Message Protocol supported by Tavendo. It's an open standard WebSocket subprotocol that provides two application messaging patterns in one unified protocol: Remote Procedure Calls + Publish & Subscribe.

Why Spell?

  • Flexible interface: one line blocking calls or raw message handling -- use whichever tool works best.
  • Robust peers: peer processes are supervised, and will restart or retry when appropriate.
  • Easy to extend: add new roles, transports, or serializers without changing the core library:

Getting Help

Spell uses GitHub issues and pull requests for development.

Spell has a mailing list at [email protected]; general questions or ideas are welcome there. See librelist for how to sign up.

Using Spell with your Elixir Project

To use Spell from within your Elixir library add, add it to your mix.exs deps, along with the required transport and serialization libraries:

defp deps do
  [
    ...
    # Required:
    {:spell, "~> 0.1"},
    # Required if using the websocket transport:
    {:websocket_client, github: "jeremyong/websocket_client", tag: "v0.7"},
    # Required if using the JSON serializer:
    {:poison, "~> 1.4"},
    # Required if using the msgpack serializer:
    {:msgpax, "~> 0.7"}
  ]
end

Fetch the dependencies by running:

$ mix deps.get

How it Works

You can run the examples you're about to run into, though first you'll need crossbar.io. You might install it via pip:

$ pip install crossbar

If you are going to use MessagePack you will need to install the optional crossbar package.

$ pip install crossbar[msgpack]

Start an Elixir shell:

$ iex -S mix

Start up Crossbar.io:

iex> Crossbar.start()

To stop Crossbar.io from IEx:

iex> Crossbar.stop()

You can find more detailed documentation at any time by checking the source code documentation. Spell provides an entry point:

iex> h Spell

You can hit C-c C-c to exit the shell. Be sure to stop Crossbar.io first.

Peers

In WAMP, messages are exchanged between peers. Peers are assigned a set of roles which define how they handle messages. A client peer (Spell!) may have any choice of client roles, and a server peer may have any choice of server roles.

There are two functional groupings of roles:

  • PubSub
    • Publisher
    • Subscriber
    • Broker [Server]
  • RPC
    • Caller
    • Callee
    • Dealer [Server]

By default a client peer is started with the above four client roles:

Spell.connect("ws://example.org", realm: "realm1")

See Spell.Peer and Spell.Role.

Authentication

Spell supports WAMP Challenge Response Authentication (CRA). This is flexible, and can be used to back a variety of authentication schemes.

To setup a Spell peer with authentication:

alias Spell.Authentication.CRA
authentication = [id: "harry", schemes: [{CRA, [secret: "alohamora"]}]]
Spell.connect("ws://example.org", realm: "realm1",
              authentication: authentication)

See Spell.Authentication.

PubSub

Once subscribed to a topic, the subscriber will receive all messages published to that topic.

# Events must be published to a topic.
topic = "com.spell.example.pubsub.topic"

# Create a peer with the subscriber role.
subscriber = Spell.connect(Crossbar.uri,
                           realm: Crossbar.get_realm(),
                           roles: [Spell.Role.Subscriber])

# `call_subscribe/2,3` synchronously subscribes to the topic.
{:ok, subscription} = Spell.call_subscribe(subscriber, topic)

# Create a peer with the publisher role.
publisher = Spell.connect(Crossbar.uri,
                          realm: Crossbar.get_realm(),
                          roles: [Spell.Role.Publisher])

# `call_publish/2,3` synchronously publishes a message to the topic.
{:ok, publication} = Spell.call_publish(publisher, topic)

# `receive_event/2,3` blocks to receive the event.
case Spell.receive_event(publisher, subscription) do
  {:ok, event}     -> handle_event(event)
  {:error, reason} -> {:error, reason}
end

# Cleanup.
for peer <- [subscriber, publisher], do: Spell.close(peer)

See Spell.Role.Publisher and Spell.Role.Subscriber for more information.

Pattern-based subscriptions

By default, peers subscribe to topics using an exact matching policy. Using pattern-based subscriptions a peer can receive messages that match certain criteria.

# assuming we have a subscriber peer connected

# exact match
{:ok, subscription} = Spell.call_subscribe(subscriber, "com.spell.my_topic")
# subscriber will receive messages published in the "com.spell.my_topic" topic

# prefix match
{:ok, subscription} = Spell.call_subscribe(subscriber, "com.spell.my_topic_prefix", options: %{match: :prefix})
# subscriber will receive messages published in topics:
# "com.spell.my_topic_prefix.foo",  "com.spell.my_topic_prefix.bar", ...

# wildcard match
{:ok, subscription} = Spell.call_subscribe(subscriber, "com.spell..my_topic", options: %{match: :wildcard})
# subscriber will receive messages published in topics:
# "com.spell.foo.my_topic", "com.spell.bar.my_topic", ...

RPC

RPC allows a caller to call a procedure using a remote callee.

Let's start with the caller's half:

# Calls are sent to a particular procedure.
procedure = "com.spell.example.rpc.procedure"

# Create a peer with the callee role.
caller = Spell.connect(Crossbar.uri,
                       realm: Crossbar.get_realm(),
                       roles: [Spell.Role.Callee])

# `call_register/2,3` synchronously calls the procedure with the arguments.
{:ok, registration} = Spell.call(subscriber, procedure,
                                 arguments: ["args"],
                                 arguments_kw: %{})

Spell.close(caller)

In addition to the synchronous Spell.call_... type functions described so far, Spell includes asynchronous Spell.cast_... functions. To handle the result of these messages you can use a Spell.receive_... helper, or, most flexibly, use a receive clause.

Next is a contrived example showing the RPC caller and the callee being used from a single process. Note how asynchronous casts and receive functions are used to avoid a deadlock.

Note: I omitted the arguments and arguments_kw options for brevity's sake.

# Calls are sent to a particular procedure.
procedure = "com.spell.example.rpc.procedure"

# Create a peer with the callee role.
callee = Spell.connect(Crossbar.uri,
                       realm: Crossbar.get_realm(),
                       roles: [Spell.Role.Callee])

# `call_register/2,3` synchronously registers the procedure.
{:ok, registration} = Spell.call_register(callee, procedure)

# Create a peer with the caller role.
caller = Spell.connect(Crossbar.uri,
                       realm: Crossbar.get_realm(),
                       roles: [Spell.Role.Caller])

# `cast_call/2,3` asynchronously calls the procedure.
{:ok, call} = Spell.cast_call(caller, procedure)

# `receive_invocation/2,3` blocks until it receives the call invocation.
{:ok, invocation} = Spell.receive_invocation(callee, call)

# `cast_yield/2,3` asynchronously yields the result back to the caller
:ok = Spell.cast_yield(callee, invocation.id, handle_invocation(invocation))

# `receive_event/2,3` blocks until timeout to receive the result.
case Spell.receive_result(publisher, call) do
  {:ok, result}    -> handle_result(result)
  {:error, reason} -> {:error, reason}
end

# Cleanup.
for peer <- [callee, caller], do: Spell.close(peer)

See Spell.Role.Caller and Spell.Role.Callee for more information.

Adding New Roles

In Spell, Roles are middleware for handling messages. Technically they're most similar to GenEvent handlers: callbacks which are hooked into a manager. In this case, the manager is a Spell.Peer process.

It's easy to get started:

defmodule Broker do
  use Spell.Role

  def get_features(_options), do: {:broker, %{}}

  def handle_message(%Message{type: :publish} = message, peer, state) do
    publish(message, peer, state)
  end

  ... shamelessly skipping the real work.
end

Spell.Peer.connect(Crossbar.uri, realm: Crossbar.get_realm(), roles: [Broker])

See Spell.Role for descriptions of the Role callbacks.

Examples

Look in examples/ for the scripts.

There are shortcuts to run the examples -- run the following from Spell's root:

$ mix spell.example.pubsub

Testing

To run Spell's integration tests, you must have crossbar installed.

To run the tests:

# run unit and integration tests with default configuration
$ mix test

# run only unit tests
$ mix test.unit

# run integration tests using a specific serializer
$ SERIALIZER=json mix test.integration
$ SERIALIZER=msgpack mix test.integration

# run integration tests with all possible serializers
$ SERIALIZER=all mix test.integration
$ mix test.integration

# run unit and integration tests with all possible configurations
$ mix test.all

The Crossbar.io test server can be configured to listen on a different port by running:

$ CROSSBAR_PORT=8000 mix ...

Creating the Documentation

To generate HTML from the source code documentation you can run:

$ mix docs
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].