Skip to content

Commit

Permalink
Merge pull request #1 from peillis/socket
Browse files Browse the repository at this point in the history
Socket lib
  • Loading branch information
peillis authored Sep 24, 2017
2 parents 66e0d47 + 1a406e4 commit 3323cb3
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 28 deletions.
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: elixir

elixir:
- 1.5.1

otp_release:
- 20.0
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Elasticachex

[![Build Status](https://secure.travis-ci.org/peillis/elasticachex.svg)](http://travis-ci.org/peillis/elasticachex)

An implementation of the Node Auto Discovery for Memcached in the
ElastiCache service of AWS.

Expand All @@ -18,6 +20,6 @@ dependencies in `mix.exs`:

```elixir
def deps do
[{:elasticachex, "~> 1.0"}]
[{:elasticachex, "~> 1.1"}]
end
```
6 changes: 5 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config

config :elasticachex,
socket_module: Elasticachex.Socket,
timeout: 5000

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
Expand All @@ -27,4 +31,4 @@ use Mix.Config
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
import_config "#{Mix.env}.exs"
1 change: 1 addition & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use Mix.Config
4 changes: 4 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use Mix.Config

config :elasticachex,
socket_module: Elasticachex.SocketTest
26 changes: 6 additions & 20 deletions lib/elasticachex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ defmodule Elasticachex do
It simply returns the nodes of the cache cluster.
"""

@timeout 5000 # timeout in ms
@socket Application.get_env(:elasticachex, :socket_module)
@timeout Application.get_env(:elasticachex, :timeout)

@doc """
The function to get the cluster info.
Returns `{:ok, [hosts_list], config_version}` or
`{:error, reason}`
"""
def get_cluster_info(host, port \\ 11211) do
with {:ok, socket} <- connect(host, port),
with {:ok, socket} <- @socket.connect(host, port, @timeout),
{:ok, command} <- get_command(socket),
{:ok, data} <- send_and_recv(socket, command) do
{:ok, data} <- @socket.send_and_recv(socket, command, @timeout) do
digest_cluster_data(data)
end
end
Expand All @@ -38,34 +38,20 @@ defmodule Elasticachex do
{:ok, version} ->
case Version.compare(version, "1.4.14") do
:lt -> {:ok, "get AmazonElastiCache:cluster\n"}
_ -> {:ok, "config get cluster\n"}
_ -> {:ok, "config get cluster\n"}
end
{:error, reason} -> {:error, reason}
end
end

# Gets version number
defp get_version(socket) do
case send_and_recv(socket, "version\n") do
case @socket.send_and_recv(socket, "version\n", @timeout) do
{:ok, data} ->
<<"VERSION ", version :: binary >> = data
{:ok, String.trim(version)}
{:error, reason} -> {:error, reason}
end
end

defp send_and_recv(socket, command) do
case :gen_tcp.send(socket, command) do
:ok -> :gen_tcp.recv(socket, 0, @timeout)
{:error, reason} -> {:error, reason}
end
end

defp connect(host, port) when is_binary(host) do
connect(String.to_charlist(host), port)
end
defp connect(host, port) do
:gen_tcp.connect(host, port, [:binary, active: false], @timeout)
end

end
22 changes: 22 additions & 0 deletions lib/elasticachex/socket.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Elasticachex.Socket do
@doc """
Connects to the service
"""
def connect(host, port, timeout) do
Socket.TCP.connect(host, port, timeout: timeout)
end

@doc """
Sends a command to the socket connection and returns the response.
## Example
iex> send_and_recv(socket, "version\n", 5000)
{:ok, VERSION 1.4.34\r\n"}
"""
def send_and_recv(socket, command, timeout) do
socket |> Socket.Stream.send!(command)
socket |> Socket.Stream.recv(timeout: timeout)
end

end
10 changes: 8 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ defmodule Elasticachex.Mixfile do
def project do
[
app: :elasticachex,
version: "1.0.0",
version: "1.1.0",
elixir: "~> 1.4",
elixirc_paths: elixirc_paths(Mix.env),
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
description: description(),
Expand All @@ -17,6 +18,10 @@ defmodule Elasticachex.Mixfile do
]
end

# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]

# Configuration for the OTP application
#
# Type "mix help compile.app" for more information
Expand All @@ -36,7 +41,8 @@ defmodule Elasticachex.Mixfile do
# Type "mix help deps" for more examples and options
defp deps do
[
{:ex_doc, "~> 0.15.0", only: :dev}
{:ex_doc, "~> 0.15.0", only: :dev},
{:socket, "~> 0.3"}
]
end

Expand Down
5 changes: 3 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
%{"earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []},
"ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}}
%{"earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [], [], "hexpm"}}
10 changes: 8 additions & 2 deletions test/elasticachex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ defmodule ElasticachexTest do
use ExUnit.Case
doctest Elasticachex

test "the truth" do
assert 1 + 1 == 2
test "version > 1.4.14" do
assert Elasticachex.get_cluster_info("version>1.4.14") ==
{:ok, ["10.0.9.238:11211"], "1"}
end

test "version < 1.4.14" do
assert Elasticachex.get_cluster_info("version<1.4.14") ==
{:ok, ["10.0.9.238:11211"], "1"}
end
end
23 changes: 23 additions & 0 deletions test/support/socket.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Elasticachex.SocketTest do

def connect("version>1.4.14", _port, _timeout) do
{:ok, :socket_1}
end
def connect("version<1.4.14", _port, _timeout) do
{:ok, :socket_2}
end

def send_and_recv(:socket_1, command, _timeout) do
case command do
"version\n" -> {:ok, "VERSION 1.4.14\r\n"}
"config get cluster\n" -> {:ok, "CONFIG cluster 0 74\r\n1\nmemcached-cluster.xlttkm.0001.euw1.cache.amazonaws.com|10.0.9.238|11211\n\r\nEND\r\n"}
end
end
def send_and_recv(:socket_2, command, _timeout) do
case command do
"version\n" -> {:ok, "VERSION 1.4.13\r\n"}
"get AmazonElastiCache:cluster\n" -> {:ok, "CONFIG cluster 0 74\r\n1\nmemcached-cluster.xlttkm.0001.euw1.cache.amazonaws.com|10.0.9.238|11211\n\r\nEND\r\n"}
end
end

end

0 comments on commit 3323cb3

Please sign in to comment.