Browse Source

Merge pull request #1510 from waiteb3/phoenix

Phoenix and Erlang/Elixir without sudo
Brittany Mazza 10 years ago
parent
commit
5a0ab67369
41 changed files with 1049 additions and 33 deletions
  1. 1 0
      .travis.yml
  2. 4 0
      frameworks/Elixir/phoenix/.gitignore
  3. 8 0
      frameworks/Elixir/phoenix/README.md
  4. 24 0
      frameworks/Elixir/phoenix/benchmark_config.json
  5. 23 0
      frameworks/Elixir/phoenix/config/config.exs
  6. 13 0
      frameworks/Elixir/phoenix/config/dev.exs
  7. 3 0
      frameworks/Elixir/phoenix/config/locales/en.exs
  8. 38 0
      frameworks/Elixir/phoenix/config/prod.exs
  9. 7 0
      frameworks/Elixir/phoenix/config/test.exs
  10. 3 0
      frameworks/Elixir/phoenix/install.sh
  11. 29 0
      frameworks/Elixir/phoenix/lib/hello.ex
  12. 30 0
      frameworks/Elixir/phoenix/lib/hello/endpoint.ex
  13. 30 0
      frameworks/Elixir/phoenix/mix.exs
  14. 6 0
      frameworks/Elixir/phoenix/priv/static/css/phoenix.css
  15. BIN
      frameworks/Elixir/phoenix/priv/static/images/phoenix.png
  16. 565 0
      frameworks/Elixir/phoenix/priv/static/js/phoenix.js
  17. 15 0
      frameworks/Elixir/phoenix/setup.sh
  18. 7 0
      frameworks/Elixir/phoenix/test/hello_test.exs
  19. 1 0
      frameworks/Elixir/phoenix/test/test_helper.exs
  20. 40 0
      frameworks/Elixir/phoenix/web/controllers/page_controller.ex
  21. 11 0
      frameworks/Elixir/phoenix/web/models/repo.exs
  22. 7 0
      frameworks/Elixir/phoenix/web/models/world.exs
  23. 31 0
      frameworks/Elixir/phoenix/web/router.ex
  24. 31 0
      frameworks/Elixir/phoenix/web/templates/layout/application.html.eex
  25. 1 0
      frameworks/Elixir/phoenix/web/templates/page/error.html.eex
  26. 34 0
      frameworks/Elixir/phoenix/web/templates/page/index.html.eex
  27. 1 0
      frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex
  28. 17 0
      frameworks/Elixir/phoenix/web/view.ex
  29. 16 0
      frameworks/Elixir/phoenix/web/views/error_view.ex
  30. 3 0
      frameworks/Elixir/phoenix/web/views/layout_view.ex
  31. 3 0
      frameworks/Elixir/phoenix/web/views/page_view.ex
  32. 1 2
      frameworks/Erlang/cowboy/.gitignore
  33. 1 1
      frameworks/Erlang/cowboy/benchmark_config.json
  34. 5 3
      frameworks/Erlang/cowboy/setup.sh
  35. 1 2
      frameworks/Erlang/elli/.gitignore
  36. 1 1
      frameworks/Erlang/elli/benchmark_config.json
  37. 2 2
      frameworks/Erlang/elli/rebar.config
  38. 5 3
      frameworks/Erlang/elli/setup.sh
  39. 14 11
      toolset/setup/linux/languages/elixir.sh
  40. 13 7
      toolset/setup/linux/languages/erlang.sh
  41. 4 1
      toolset/setup/linux/systools/rebar.sh

+ 1 - 0
.travis.yml

@@ -38,6 +38,7 @@ env:
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"
     - "TESTDIR=Dart/dart-stream"
+    - "TESTDIR=Elixir/phoenix"
     - "TESTDIR=Erlang/cowboy"
     - "TESTDIR=Erlang/elli"
     - "TESTDIR=Go/beego"

+ 4 - 0
frameworks/Elixir/phoenix/.gitignore

@@ -0,0 +1,4 @@
+/_build
+/deps
+erl_crash.dump
+*.ez

+ 8 - 0
frameworks/Elixir/phoenix/README.md

@@ -0,0 +1,8 @@
+# Hello
+
+To start your new Phoenix application:
+
+1. Install dependencies with `mix deps.get`
+2. Start Phoenix endpoint with `mix phoenix.server`
+
+Now you can visit `localhost:8080` from your browser.

+ 24 - 0
frameworks/Elixir/phoenix/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+    "framework": "phoenix",
+    "tests": [{
+        "default": {
+            "setup_file": "setup",
+            "json_url": "/json",
+            "plaintext_url": "/plaintext",
+            "port": 8080,
+            "approach": "Realistic",
+            "classification": "Framework",
+            "database": "Postgres",
+            "framework": "Phoenix",
+            "language": "elixir",
+            "orm": "etco",
+            "platform": "Erlang/OTP",
+            "webserver": "cowboy",
+            "os": "Linux",
+            "database_os": "Linux",
+            "display_name": "phoenix",
+            "notes": "",
+            "versus": ""
+        }
+    }]
+}

+ 23 - 0
frameworks/Elixir/phoenix/config/config.exs

@@ -0,0 +1,23 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# Configures the endpoint
+config :hello, Hello.Endpoint,
+  url: [host: "localhost"],
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  debug_errors: false,
+  pubsub: [adapter: Phoenix.PubSub.PG2]
+
+
+# Configures Elixir's Logger
+config :logger, :console,
+  format: "$time $metadata[$level] $message\n",
+  metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"

+ 13 - 0
frameworks/Elixir/phoenix/config/dev.exs

@@ -0,0 +1,13 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  url: [host: "localhost", port: 8080],
+  http: [port: System.get_env("PORT") || 8080],
+  debug_errors: true,
+  cache_static_lookup: false
+
+# Enables code reloading for development
+config :phoenix, :code_reloader, true
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"

+ 3 - 0
frameworks/Elixir/phoenix/config/locales/en.exs

@@ -0,0 +1,3 @@
+[
+  hello: "Hello"
+]

+ 38 - 0
frameworks/Elixir/phoenix/config/prod.exs

@@ -0,0 +1,38 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  url: [host: "localhost", port: 8080],
+  http: [port: 8080],
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  cache_static_lookup: false
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section:
+#
+#  config:hello, Hello.Endpoint,
+#    ...
+#    https: [port: 443,
+#            keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+#            certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables point to a file on
+# disk for the key and cert.
+
+
+# Do not pring debug messages in production
+config :logger, level: :info
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+#    config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+#     config :hello, Hello.Endpoint, server: true
+#

+ 7 - 0
frameworks/Elixir/phoenix/config/test.exs

@@ -0,0 +1,7 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  http: [port: System.get_env("PORT") || 4001]
+
+# Print only warnings and errors during test
+config :logger, level: :warn

+ 3 - 0
frameworks/Elixir/phoenix/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends elixir

+ 29 - 0
frameworks/Elixir/phoenix/lib/hello.ex

@@ -0,0 +1,29 @@
+defmodule Hello do
+  use Application
+
+  # See http://elixir-lang.org/docs/stable/elixir/Application.html
+  # for more information on OTP Applications
+  def start(_type, _args) do
+    import Supervisor.Spec, warn: false
+
+    children = [
+      # Start the endpoint when the application starts
+      supervisor(Hello.Endpoint, []),
+      # Here you could define other workers and supervisors as children
+      # worker(Hello.Worker, [arg1, arg2, arg3]),
+      # worker(Hello.Repo, [])
+    ]
+
+    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
+    # for other strategies and supported options
+    opts = [strategy: :one_for_one, name: Hello.Supervisor]
+    Supervisor.start_link(children, opts)
+  end
+
+  # Tell Phoenix to update the endpoint configuration
+  # whenever the application is updated.
+  def config_change(changed, _new, removed) do
+    Hello.Endpoint.config_change(changed, removed)
+    :ok
+  end
+end

+ 30 - 0
frameworks/Elixir/phoenix/lib/hello/endpoint.ex

@@ -0,0 +1,30 @@
+defmodule Hello.Endpoint do
+  use Phoenix.Endpoint, otp_app: :hello
+
+  # Serve at "/" the given assets from "priv/static" directory
+  plug Plug.Static,
+    at: "/", from: :hello,
+    only: ~w(css images js favicon.ico robots.txt)
+
+  plug Plug.Logger
+
+  # Code reloading will only work if the :code_reloader key of
+  # the :phoenix application is set to true in your config file.
+  plug Phoenix.CodeReloader
+
+  plug Plug.Parsers,
+    parsers: [:urlencoded, :multipart, :json],
+    pass: ["*/*"],
+    json_decoder: Poison
+
+  plug Plug.MethodOverride
+  plug Plug.Head
+
+  plug Plug.Session,
+    store: :cookie,
+    key: "_hello_key",
+    signing_salt: "DNlAnJ2o",
+    encryption_salt: "AOXxaZRq"
+
+  plug :router, Hello.Router
+end

+ 30 - 0
frameworks/Elixir/phoenix/mix.exs

@@ -0,0 +1,30 @@
+defmodule Hello.Mixfile do
+  use Mix.Project
+
+  def project do
+    [app: :hello,
+     version: "0.0.1",
+     elixir: "~> 1.0",
+     elixirc_paths: ["lib", "web"],
+     compilers: [:phoenix] ++ Mix.compilers,
+     deps: deps]
+  end
+
+  # Configuration for the OTP application
+  #
+  # Type `mix help compile.app` for more information
+  def application do
+    [mod: {Hello, []},
+     applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto]]
+  end
+
+  # Specifies your project dependencies
+  #
+  # Type `mix help deps` for examples and options
+  defp deps do
+    [{:phoenix, "~> 0.9.0"},
+     {:cowboy, "~> 1.0"},
+     {:postgrex, "~> 0.6.0"},
+     {:ecto, "~> 0.2.5"}]
+  end
+end

File diff suppressed because it is too large
+ 6 - 0
frameworks/Elixir/phoenix/priv/static/css/phoenix.css


BIN
frameworks/Elixir/phoenix/priv/static/images/phoenix.png


+ 565 - 0
frameworks/Elixir/phoenix/priv/static/js/phoenix.js

@@ -0,0 +1,565 @@
+"use strict";
+
+var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+(function (root, factory) {
+  if (typeof define === "function" && define.amd) {
+    return define(["phoenix"], factory);
+  } else if (typeof exports === "object") {
+    return factory(exports);
+  } else {
+    root.Phoenix = {};
+    return factory.call(root, root.Phoenix);
+  }
+})(Function("return this")(), function (exports) {
+  var root = this;
+  var SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 };
+
+  exports.Channel = (function () {
+    function Channel(topic, message, callback, socket) {
+      _classCallCheck(this, Channel);
+
+      this.topic = topic;
+      this.message = message;
+      this.callback = callback;
+      this.socket = socket;
+      this.bindings = null;
+
+      this.reset();
+    }
+
+    _prototypeProperties(Channel, null, {
+      reset: {
+        value: function reset() {
+          this.bindings = [];
+        },
+        writable: true,
+        configurable: true
+      },
+      on: {
+        value: function on(event, callback) {
+          this.bindings.push({ event: event, callback: callback });
+        },
+        writable: true,
+        configurable: true
+      },
+      isMember: {
+        value: function isMember(topic) {
+          return this.topic === topic;
+        },
+        writable: true,
+        configurable: true
+      },
+      off: {
+        value: function off(event) {
+          this.bindings = this.bindings.filter(function (bind) {
+            return bind.event !== event;
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      trigger: {
+        value: function trigger(triggerEvent, msg) {
+          this.bindings.filter(function (bind) {
+            return bind.event === triggerEvent;
+          }).map(function (bind) {
+            return bind.callback(msg);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(event, payload) {
+          this.socket.send({ topic: this.topic, event: event, payload: payload });
+        },
+        writable: true,
+        configurable: true
+      },
+      leave: {
+        value: function leave() {
+          var message = arguments[0] === undefined ? {} : arguments[0];
+          this.socket.leave(this.topic, message);
+          this.reset();
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return Channel;
+  })();
+
+
+  exports.Socket = (function () {
+    // Initializes the Socket
+    //
+    // endPoint - The string WebSocket endpoint, ie, "ws://example.com/ws",
+    //                                               "wss://example.com"
+    //                                               "/ws" (inherited host & protocol)
+    // opts - Optional configuration
+    //   transport - The Websocket Transport, ie WebSocket, Phoenix.LongPoller.
+    //               Defaults to WebSocket with automatic LongPoller fallback.
+    //   heartbeatIntervalMs - The millisecond interval to send a heartbeat message
+    //   logger - The optional function for specialized logging, ie:
+    //            `logger: (msg) -> console.log(msg)`
+    //
+    function Socket(endPoint) {
+      var opts = arguments[1] === undefined ? {} : arguments[1];
+      _classCallCheck(this, Socket);
+
+      this.states = SOCKET_STATES;
+      this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] };
+      this.flushEveryMs = 50;
+      this.reconnectTimer = null;
+      this.reconnectAfterMs = 5000;
+      this.heartbeatIntervalMs = 30000;
+      this.channels = [];
+      this.sendBuffer = [];
+
+      this.transport = opts.transport || root.WebSocket || exports.LongPoller;
+      this.heartbeatIntervalMs = opts.heartbeatIntervalMs || this.heartbeatIntervalMs;
+      this.logger = opts.logger || function () {}; // noop
+      this.endPoint = this.expandEndpoint(endPoint);
+      this.resetBufferTimer();
+      this.reconnect();
+    }
+
+    _prototypeProperties(Socket, null, {
+      protocol: {
+        value: function protocol() {
+          return location.protocol.match(/^https/) ? "wss" : "ws";
+        },
+        writable: true,
+        configurable: true
+      },
+      expandEndpoint: {
+        value: function expandEndpoint(endPoint) {
+          if (endPoint.charAt(0) !== "/") {
+            return endPoint;
+          }
+          if (endPoint.charAt(1) === "/") {
+            return "" + this.protocol() + ":" + endPoint;
+          }
+
+          return "" + this.protocol() + "://" + location.host + "" + endPoint;
+        },
+        writable: true,
+        configurable: true
+      },
+      close: {
+        value: function close(callback, code, reason) {
+          if (this.conn) {
+            this.conn.onclose = function () {}; // noop
+            if (code) {
+              this.conn.close(code, reason || "");
+            } else {
+              this.conn.close();
+            }
+            this.conn = null;
+          }
+          callback && callback();
+        },
+        writable: true,
+        configurable: true
+      },
+      reconnect: {
+        value: function reconnect() {
+          var _this = this;
+          this.close(function () {
+            _this.conn = new _this.transport(_this.endPoint);
+            _this.conn.onopen = function () {
+              return _this.onConnOpen();
+            };
+            _this.conn.onerror = function (error) {
+              return _this.onConnError(error);
+            };
+            _this.conn.onmessage = function (event) {
+              return _this.onConnMessage(event);
+            };
+            _this.conn.onclose = function (event) {
+              return _this.onConnClose(event);
+            };
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      resetBufferTimer: {
+        value: function resetBufferTimer() {
+          var _this = this;
+          clearTimeout(this.sendBufferTimer);
+          this.sendBufferTimer = setTimeout(function () {
+            return _this.flushSendBuffer();
+          }, this.flushEveryMs);
+        },
+        writable: true,
+        configurable: true
+      },
+      log: {
+
+        // Logs the message. Override `this.logger` for specialized logging. noops by default
+        value: function log(msg) {
+          this.logger(msg);
+        },
+        writable: true,
+        configurable: true
+      },
+      onOpen: {
+
+        // Registers callbacks for connection state change events
+        //
+        // Examples
+        //
+        //    socket.onError (error) -> alert("An error occurred")
+        //
+        value: function onOpen(callback) {
+          this.stateChangeCallbacks.open.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onClose: {
+        value: function onClose(callback) {
+          this.stateChangeCallbacks.close.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onError: {
+        value: function onError(callback) {
+          this.stateChangeCallbacks.error.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onMessage: {
+        value: function onMessage(callback) {
+          this.stateChangeCallbacks.message.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnOpen: {
+        value: function onConnOpen() {
+          var _this = this;
+          clearInterval(this.reconnectTimer);
+          if (!this.transport.skipHeartbeat) {
+            this.heartbeatTimer = setInterval(function () {
+              return _this.sendHeartbeat();
+            }, this.heartbeatIntervalMs);
+          }
+          this.rejoinAll();
+          this.stateChangeCallbacks.open.forEach(function (callback) {
+            return callback();
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnClose: {
+        value: function onConnClose(event) {
+          var _this = this;
+          this.log("WS close:");
+          this.log(event);
+          clearInterval(this.reconnectTimer);
+          clearInterval(this.heartbeatTimer);
+          this.reconnectTimer = setInterval(function () {
+            return _this.reconnect();
+          }, this.reconnectAfterMs);
+          this.stateChangeCallbacks.close.forEach(function (callback) {
+            return callback(event);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnError: {
+        value: function onConnError(error) {
+          this.log("WS error:");
+          this.log(error);
+          this.stateChangeCallbacks.error.forEach(function (callback) {
+            return callback(error);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      connectionState: {
+        value: function connectionState() {
+          switch (this.conn && this.conn.readyState) {
+            case this.states.connecting:
+              return "connecting";
+            case this.states.open:
+              return "open";
+            case this.states.closing:
+              return "closing";
+            default:
+              return "closed";
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      isConnected: {
+        value: function isConnected() {
+          return this.connectionState() === "open";
+        },
+        writable: true,
+        configurable: true
+      },
+      rejoinAll: {
+        value: function rejoinAll() {
+          var _this = this;
+          this.channels.forEach(function (chan) {
+            return _this.rejoin(chan);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      rejoin: {
+        value: function rejoin(chan) {
+          chan.reset();
+          this.send({ topic: chan.topic, event: "join", payload: chan.message });
+          chan.callback(chan);
+        },
+        writable: true,
+        configurable: true
+      },
+      join: {
+        value: function join(topic, message, callback) {
+          var chan = new exports.Channel(topic, message, callback, this);
+          this.channels.push(chan);
+          if (this.isConnected()) {
+            this.rejoin(chan);
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      leave: {
+        value: function leave(topic) {
+          var message = arguments[1] === undefined ? {} : arguments[1];
+          this.send({ topic: topic, event: "leave", payload: message });
+          this.channels = this.channels.filter(function (c) {
+            return !c.isMember(topic);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(data) {
+          var _this = this;
+          var callback = function () {
+            return _this.conn.send(root.JSON.stringify(data));
+          };
+          if (this.isConnected()) {
+            callback();
+          } else {
+            this.sendBuffer.push(callback);
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      sendHeartbeat: {
+        value: function sendHeartbeat() {
+          this.send({ topic: "phoenix", event: "heartbeat", payload: {} });
+        },
+        writable: true,
+        configurable: true
+      },
+      flushSendBuffer: {
+        value: function flushSendBuffer() {
+          if (this.isConnected() && this.sendBuffer.length > 0) {
+            this.sendBuffer.forEach(function (callback) {
+              return callback();
+            });
+            this.sendBuffer = [];
+          }
+          this.resetBufferTimer();
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnMessage: {
+        value: function onConnMessage(rawMessage) {
+          this.log("message received:");
+          this.log(rawMessage);
+          var _root$JSON$parse = root.JSON.parse(rawMessage.data);
+
+          var topic = _root$JSON$parse.topic;
+          var event = _root$JSON$parse.event;
+          var payload = _root$JSON$parse.payload;
+          this.channels.filter(function (chan) {
+            return chan.isMember(topic);
+          }).forEach(function (chan) {
+            return chan.trigger(event, payload);
+          });
+          this.stateChangeCallbacks.message.forEach(function (callback) {
+            callback(topic, event, payload);
+          });
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return Socket;
+  })();
+
+
+  exports.LongPoller = (function () {
+    function LongPoller(endPoint) {
+      _classCallCheck(this, LongPoller);
+
+      this.retryInMs = 5000;
+      this.endPoint = null;
+      this.token = null;
+      this.sig = null;
+      this.skipHeartbeat = true;
+      this.onopen = function () {}; // noop
+      this.onerror = function () {}; // noop
+      this.onmessage = function () {}; // noop
+      this.onclose = function () {}; // noop
+      this.states = SOCKET_STATES;
+      this.upgradeEndpoint = this.normalizeEndpoint(endPoint);
+      this.pollEndpoint = this.upgradeEndpoint + (/\/$/.test(endPoint) ? "poll" : "/poll");
+      this.readyState = this.states.connecting;
+
+      this.poll();
+    }
+
+    _prototypeProperties(LongPoller, null, {
+      normalizeEndpoint: {
+        value: function normalizeEndpoint(endPoint) {
+          return endPoint.replace("ws://", "http://").replace("wss://", "https://");
+        },
+        writable: true,
+        configurable: true
+      },
+      endpointURL: {
+        value: function endpointURL() {
+          return this.pollEndpoint + ("?token=" + encodeURIComponent(this.token) + "&sig=" + encodeURIComponent(this.sig));
+        },
+        writable: true,
+        configurable: true
+      },
+      closeAndRetry: {
+        value: function closeAndRetry() {
+          this.close();
+          this.readyState = this.states.connecting;
+        },
+        writable: true,
+        configurable: true
+      },
+      ontimeout: {
+        value: function ontimeout() {
+          this.onerror("timeout");
+          this.closeAndRetry();
+        },
+        writable: true,
+        configurable: true
+      },
+      poll: {
+        value: function poll() {
+          var _this = this;
+          if (!(this.readyState === this.states.open || this.readyState === this.states.connecting)) {
+            return;
+          }
+
+          exports.Ajax.request("GET", this.endpointURL(), "application/json", null, this.ontimeout.bind(this), function (status, resp) {
+            if (resp && resp !== "") {
+              var _root$JSON$parse = root.JSON.parse(resp);
+
+              var token = _root$JSON$parse.token;
+              var sig = _root$JSON$parse.sig;
+              var messages = _root$JSON$parse.messages;
+              _this.token = token;
+              _this.sig = sig;
+            }
+            switch (status) {
+              case 200:
+                messages.forEach(function (msg) {
+                  return _this.onmessage({ data: root.JSON.stringify(msg) });
+                });
+                _this.poll();
+                break;
+              case 204:
+                _this.poll();
+                break;
+              case 410:
+                _this.readyState = _this.states.open;
+                _this.onopen();
+                _this.poll();
+                break;
+              case 0:
+              case 500:
+                _this.onerror();
+                _this.closeAndRetry();
+                break;
+              default:
+                throw "unhandled poll status " + status;
+            }
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(body) {
+          var _this = this;
+          exports.Ajax.request("POST", this.endpointURL(), "application/json", body, this.onerror.bind(this, "timeout"), function (status, resp) {
+            if (status !== 200) {
+              _this.onerror(status);
+            }
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      close: {
+        value: function close(code, reason) {
+          this.readyState = this.states.closed;
+          this.onclose();
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return LongPoller;
+  })();
+
+
+  exports.Ajax = {
+
+    states: { complete: 4 },
+
+    request: function (method, endPoint, accept, body, ontimeout, callback) {
+      var _this = this;
+      var req = root.XMLHttpRequest ? new root.XMLHttpRequest() : // IE7+, Firefox, Chrome, Opera, Safari
+      new root.ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5
+      req.open(method, endPoint, true);
+      req.setRequestHeader("Content-type", accept);
+      req.onerror = function () {
+        callback && callback(500, null);
+      };
+      req.onreadystatechange = function () {
+        if (req.readyState === _this.states.complete && callback) {
+          callback(req.status, req.responseText);
+        }
+      };
+      if (ontimeout) {
+        req.ontimeout = ontimeout;
+      }
+
+      req.send(body);
+    }
+  };
+});

+ 15 - 0
frameworks/Elixir/phoenix/setup.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+source $IROOT/elixir.installed
+
+sed -i 's|db_host: "localhost",|db_host: "${DBHOST}",|g' config/config.exs
+
+rm -rf _build deps
+
+mix local.hex --force
+mix local.rebar --force
+mix deps.get --force
+
+MIX_ENV=prod mix compile.protocols --force
+MIX_ENV=prod elixir --detached -pa _build/$MIX_ENV/consolidated -S mix phoenix.server
+

+ 7 - 0
frameworks/Elixir/phoenix/test/hello_test.exs

@@ -0,0 +1,7 @@
+defmodule HelloTest do
+  use ExUnit.Case
+
+  test "the truth" do
+    assert 1 + 1 == 2
+  end
+end

+ 1 - 0
frameworks/Elixir/phoenix/test/test_helper.exs

@@ -0,0 +1 @@
+ExUnit.start

+ 40 - 0
frameworks/Elixir/phoenix/web/controllers/page_controller.ex

@@ -0,0 +1,40 @@
+defmodule Hello.PageController do
+  use Phoenix.Controller
+
+  plug :action
+
+  def index(conn, _params) do
+    json conn, %{
+      "TE Benchmarks\n" => "Started",
+      "DBHOST" => System.get_env("DBHOST"),
+      "DBPORT" => System.get_env("DBPORT"),
+    }
+  end
+
+  # avoid namespace collision
+  def _json(conn, _params) do
+    json conn, %{message: "Hello, world!"}
+  end
+
+  def db(conn, _params) do
+    :random.seed(:erlang.now)
+    id = :random.uniform(10000)
+    text conn, "TE Benchmarks\n"
+  end
+
+  def queries(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def fortunes(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def updates(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def plaintext(conn, _params) do
+    text conn, "Hello, world!"
+  end
+end

+ 11 - 0
frameworks/Elixir/phoenix/web/models/repo.exs

@@ -0,0 +1,11 @@
+defmodule Hello.Repo do
+  use Ecto.Repo, adapter: Ecto.Adapters.Postgres
+
+  def conf do
+    parse_url "ecto://username:password@host/database_name"
+  end
+
+  def priv do
+    app_dir(:hello, "priv/repo")
+  end
+end

+ 7 - 0
frameworks/Elixir/phoenix/web/models/world.exs

@@ -0,0 +1,7 @@
+defmodule Hello.User do
+  use Ecto.Model
+
+  schema "world" do
+    field :randomNumber, :integer
+  end
+end

+ 31 - 0
frameworks/Elixir/phoenix/web/router.ex

@@ -0,0 +1,31 @@
+defmodule Hello.Router do
+  use Phoenix.Router
+
+  pipeline :browser do
+    plug :accepts, ~w(html)
+    plug :fetch_session
+    plug :fetch_flash
+    plug :protect_from_forgery
+  end
+
+  pipeline :api do
+    plug :accepts, ~w(json)
+  end
+
+  scope "/", Hello do
+    pipe_through :browser # Use the default browser stack
+
+    get "/json", PageController, :_json
+    get "/db", PageController, :db
+    get "/queries", PageController, :queries
+    get "/fortunes", PageController, :fortunes
+    get "/updates", PageController, :updates
+    get "/plaintext", PageController, :plaintext
+    get "/", PageController, :index
+  end
+
+  # Other scopes may use custom stacks.
+  # scope "/api", Hello do
+  #   pipe_through :api
+  # end
+end

+ 31 - 0
frameworks/Elixir/phoenix/web/templates/layout/application.html.eex

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <title>Hello Phoenix!</title>
+    <link rel="stylesheet" href="/css/phoenix.css">
+  </head>
+
+  <body>
+    <div class="container">
+      <div class="header">
+        <ul class="nav nav-pills pull-right">
+          <li><a href="http://www.phoenixframework.org/docs">Get Started</a></li>
+        </ul>
+        <span class="logo"></span>
+      </div>
+
+      <%= @inner %>
+
+      <div class="footer">
+        <p><a href="http://phoenixframework.org">phoenixframework.org</a></p>
+      </div>
+
+    </div> <!-- /container -->
+  </body>
+</html>

+ 1 - 0
frameworks/Elixir/phoenix/web/templates/page/error.html.eex

@@ -0,0 +1 @@
+Something went wrong

+ 34 - 0
frameworks/Elixir/phoenix/web/templates/page/index.html.eex

@@ -0,0 +1,34 @@
+<div class="jumbotron">
+  <h2>Welcome to Phoenix!</h2>
+  <p class="lead">Phoenix is an Elixir Web Framework targeting full-featured, fault tolerant applications with realtime functionality.</p>
+</div>
+
+<div class="row marketing">
+  <div class="col-lg-6">
+    <h4>Resources</h4>
+    <ul>
+      <li>
+        <a href="http://hexdocs.pm/phoenix">Docs</a>
+      </li>
+      <li>
+        <a href="https://github.com/phoenixframework/phoenix">Source</a>
+      </li>
+    </ul>
+  </div>
+
+  <div class="col-lg-6">
+    <h4>Help</h4>
+    <ul>
+      <li>
+        <a href="https://github.com/phoenixframework/phoenix/issues?state=open">Issues</a>
+      </li>
+      <li>
+        <a href="irc://irc.freenode.net/elixir-lang">#elixir-lang on freenode IRC</a>
+      </li>
+      <li>
+        <a href="https://twitter.com/chris_mccord">@chris_mccord</a>
+      </li>
+    </ul>
+  </div>
+</div>
+

+ 1 - 0
frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex

@@ -0,0 +1 @@
+The page you are looking for does not exist

+ 17 - 0
frameworks/Elixir/phoenix/web/view.ex

@@ -0,0 +1,17 @@
+defmodule Hello.View do
+  use Phoenix.View, root: "web/templates"
+
+  # The quoted expression returned by this block is applied
+  # to this module and all other views that use this module.
+  using do
+    quote do
+      # Import common functionality
+      import Hello.Router.Helpers
+
+      # Use Phoenix.HTML to import all HTML functions (forms, tags, etc)
+      use Phoenix.HTML
+    end
+  end
+
+  # Functions defined here are available to all other views/templates
+end

+ 16 - 0
frameworks/Elixir/phoenix/web/views/error_view.ex

@@ -0,0 +1,16 @@
+defmodule Hello.ErrorView do
+  use Hello.View
+
+  def render("404.html", _assigns) do
+    "Page not found - 404"
+  end
+
+  def render("500.html", _assigns) do
+    "Server internal error - 500"
+  end
+
+  # Render all other templates as 500
+  def render(_, assigns) do
+    render "500.html", assigns
+  end
+end

+ 3 - 0
frameworks/Elixir/phoenix/web/views/layout_view.ex

@@ -0,0 +1,3 @@
+defmodule Hello.LayoutView do
+  use Hello.View
+end

+ 3 - 0
frameworks/Elixir/phoenix/web/views/page_view.ex

@@ -0,0 +1,3 @@
+defmodule Hello.PageView do
+  use Hello.View
+end

+ 1 - 2
frameworks/Erlang/cowboy/.gitignore

@@ -1,5 +1,4 @@
 erl_crash.dump
-__init__.py
 deps
 ebin
-*.deb
+.rebar

+ 1 - 1
frameworks/Erlang/cowboy/benchmark_config.json

@@ -2,7 +2,7 @@
   "framework": "cowboy",
   "tests": [{
     "default": {
-      "setup_file": "setup_erlang",
+      "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
       "query_url": "/query?queries=",

+ 5 - 3
frameworks/Erlang/cowboy/setup_erlang.sh → frameworks/Erlang/cowboy/setup.sh

@@ -1,9 +1,11 @@
 #!/bin/bash
-export REBAR_HOME=$IROOT/rebar
+
+source $IROOT/erlang.installed
+source $IROOT/rebar.installed
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/hello_world_app.erl
 
-rm -rf deps/*
+rm -rf deps/* ebin/*
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar compile
-erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached
+erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached

+ 1 - 2
frameworks/Erlang/elli/.gitignore

@@ -1,5 +1,4 @@
 erl_crash.dump
-__init__.py
 deps
 ebin
-*.deb
+.rebar

+ 1 - 1
frameworks/Erlang/elli/benchmark_config.json

@@ -2,7 +2,7 @@
   "framework": "elli",
   "tests": [{
     "default": {
-      "setup_file": "setup_erlang",
+      "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
       "query_url": "/query?queries=",

+ 2 - 2
frameworks/Erlang/elli/rebar.config

@@ -1,6 +1,6 @@
 {deps,
  [
-  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.5"}}},
+  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.13.3"}}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
-  {elli, "", {git, "git://github.com/knutin/elli.git"}}
+  {elli, "", {git, "git://github.com/knutin/elli.git", {tag, "v1.0.3"}}}
  ]}.

+ 5 - 3
frameworks/Erlang/elli/setup_erlang.sh → frameworks/Erlang/elli/setup.sh

@@ -1,9 +1,11 @@
 #!/bin/bash
-export REBAR_HOME=$IROOT/rebar
+
+source $IROOT/erlang.installed
+source $IROOT/rebar.installed
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/elli_bench_sup.erl
 
-rm -rf deps/*
+rm -rf deps/* ebin/*
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar compile
-erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached
+erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached

+ 14 - 11
toolset/setup/linux/languages/elixir.sh

@@ -1,16 +1,19 @@
 #!/bin/bash
 
-# TODO seems to be broken installation
-echo "WARN: Elixir does not install"
-return 1
+RETCODE=$(fw_exists $IROOT/elixir.installed)
+[ ! "$RETCODE" == 0 ] || { . $IROOT/elixir.installed; return 0; }
 
-# fw_exists v0.13.3.tar.gz
-# [ $? -ne 0 ] || { return 0; }
+fw_depends erlang
+export PATH=$PATH:$IROOT/erlang/bin
 
-# fw_get https://github.com/elixir-lang/elixir/archive/v0.13.3.tar.gz
-# fw_untar v0.13.3.tar.gz
+VERSION="1.0.4"
+fw_get https://codeload.github.com/elixir-lang/elixir/tar.gz/v$VERSION
+fw_untar v$VERSION
 
-# cd elixir-0.13.3 
-# bash -c -i 'sudo make install'
-# sudo make clean
-# sudo make test
+(
+	mv elixir-$VERSION elixir
+	cd elixir
+	make compile
+)
+
+echo "export PATH=$IROOT/erlang/bin:$IROOT/elixir/bin:$PATH" >> $IROOT/elixir.installed

+ 13 - 7
toolset/setup/linux/languages/erlang.sh

@@ -1,12 +1,18 @@
 #!/bin/bash
 
-RETCODE=$(fw_exists ${IROOT}/erlang.installed)
-[ ! "$RETCODE" == 0 ] || { return 0; }
+RETCODE=$(fw_exists $IROOT/erlang.installed)
+[ ! "$RETCODE" == 0 ] || { . $IROOT/erlang.installed; return 0; }
 
-wget http://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
-sudo dpkg -i erlang-solutions_1.0_all.deb
+export OTP_SRC="otp_src_17.5"
+fw_get http://www.erlang.org/download/${OTP_SRC}.tar.gz
+fw_untar ${OTP_SRC}.tar.gz
 
-sudo apt-get -y update
-sudo apt-get install -y esl-erlang
+(
+	cd $OTP_SRC
+	export ERL_TOP=`pwd`
+	./configure --prefix=$IROOT/erlang --without-termcap
+	make
+	make install
+)
 
-touch ${IROOT}/erlang.installed
+echo "export PATH=$IROOT/erlang/bin:$PATH" >> $IROOT/erlang.installed

+ 4 - 1
toolset/setup/linux/systools/rebar.sh

@@ -3,10 +3,13 @@
 RETCODE=$(fw_exists $IROOT/rebar.installed)
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
+fw_depends erlang
+source $IROOT/erlang.installed
+
 fw_get https://github.com/rebar/rebar/archive/2.5.1.tar.gz -O rebar-2.5.1.tar.gz
 fw_untar rebar-2.5.1.tar.gz
 mv rebar-2.5.1 rebar
 cd rebar
 ./bootstrap
 
-touch $IROOT/rebar.installed
+echo "export REBAR_HOME=$IROOT/rebar" >> $IROOT/rebar.installed

Some files were not shown because too many files changed in this diff