Skip to content

Commit

Permalink
Merge pull request #119 from inaka/cabolanos.90.riak_backend
Browse files Browse the repository at this point in the history
Cabolanos.90.riak backend
  • Loading branch information
Brujo Benavides committed Mar 4, 2015
2 parents e54bee8 + 58f50f9 commit 758569b
Showing 13 changed files with 740 additions and 17 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
PROJECT = sumo_db

DEPS = lager emysql emongo tirerl epgsql wpool
DEPS = lager emysql emongo tirerl epgsql wpool riakc

dep_lager = git https://github.com/basho/lager.git 2.1.0
dep_emysql = git https://github.com/Eonblast/Emysql.git v0.4.1
dep_emongo = git https://github.com/inaka/emongo.git v0.2.1
dep_tirerl = git https://github.com/inaka/tirerl 0.1.0
dep_epgsql = git https://github.com/epgsql/epgsql 2.0.0
dep_wpool = git https://github.com/inaka/worker_pool.git 1.0
dep_wpool = git https://github.com/inaka/worker_pool.git 1.0.1
dep_riakc = git https://github.com/basho/riak-erlang-client.git 2.0.1

TEST_DEPS = mixer
dep_mixer = git git://github.com/inaka/mixer.git 0.1.2
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -72,6 +72,76 @@ being in the top level directory:

make all blog

## Running Tests

To run tests successfully, you need to follow these steps first:

* Start the database engines: **MySQL**, **PostgreSQL**, **MongoDB** and
**ElasticSearch**

* For **MySQL**, **PostgreSQL** and **MongoDB**, you need to:
- Create an user (or use defaults) and configure it on `test/test.config`
file.
- Create test database `sumo_test` on each DB.

> **Note:**
> - For **MongoDB** you first create the test database and then create an user
to access that DB. For more information visit [MongoDB Tutorial](http://docs.mongodb.org/manual/tutorial).
> - For **Riak** please follow instructions below ([<i class="icon-refresh"></i> Riak](#riak)).
## Riak

### Install Riak

To install/upgrade **Riak** please follow the instructions in this link:
[Installing and Upgrading Riak](http://docs.basho.com/riak/latest/ops/building/installing).

### Initial Configurations

Due to the fact that **Riak** comes with default configuration, we need to
change some parameters required by `sumo_db`.

**Riak** has a main configuration file `riak.conf`, which you can find into
your installation path `$YOUR_INSTALL_PATH/etc/riak.conf`.

> **Note:** For more information check this link [Configuration Files](http://docs.basho.com/riak/latest/ops/advanced/configs/configuration-files).
First parameter to change is the default **Riak** backend from **Bitcask** to
**LevelDB**. This change also enables the use of [Riak Secondary Indexes](http://docs.basho.com/riak/latest/ops/advanced/configs/secondary-index/).

storage_backend = leveldb

Then proceed to enable search capabilities:

search = on

> **Note:** For more information check this link [Riak Search Settings](http://docs.basho.com/riak/latest/ops/advanced/configs/search/).
### Configuring Riak Data Types and Search

First, let's create and activate a bucket type simply called maps that is set up
to store Riak maps:

$ riak-admin bucket-type create maps '{"props":{"datatype":"map"}}'
$ riak-admin bucket-type activate mapsdmin bucket-type activate maps

Now, let's create a search index called `sumo_test_index` using the default
schema:

$ curl -XPUT $RIAK_HOST/search/index/sumo_test_index \
-H 'Content-Type: application/json' \
-d '{"schema":"_yz_default"}'

With our index created, we can associate our new `sumo_test_index` index with
our `maps` bucket type:

$ riak-admin bucket-type update maps '{"props":{"search_index":"sumo_test_index"}}'

Now we can start working with **Riak** from `sumo_db`.

> **Note:** For more information check this link [Riak Data Types and Search](http://docs.basho.com/riak/latest/dev/search/search-data-types/#Maps-Example).
## Change Log

All notable changes to this project will be documented in the
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
@@ -25,7 +25,8 @@
{tirerl, ".*", {git, "git://github.com/inaka/tirerl", "0.1.0"}},
{epgsql, ".*", {git, "git://github.com/epgsql/epgsql", "2.0.0"}},
{mixer, ".*", {git, "git://github.com/inaka/mixer", "0.1.2"}},
{worker_pool, ".*", {git, "git://github.com/inaka/worker_pool.git", "1.0"}}
{worker_pool, ".*", {git, "git://github.com/inaka/worker_pool.git", "1.0.1"}},
{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", "2.0.1"}}
]}.
{xref_warnings, true}.
{xref_checks, [undefined_function_calls, undefined_functions, locals_not_used, deprecated_function_calls, deprecated_functions]}.
135 changes: 135 additions & 0 deletions src/sumo_backend_riak.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
%%% @hidden
%%% @doc Riak storage backend implementation.
%%%
%%% Copyright 2012 Inaka &lt;hello@inaka.net&gt;
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
%%% @end
%%% @copyright Inaka <hello@inaka.net>
%%%
-module(sumo_backend_riak).
-author("Carlos Andres Bolanos <candres.bolanos@inakanetworks.com>").
-license("Apache License 2.0").

-behaviour(gen_server).
-behaviour(sumo_backend).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Exports.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%% Public API.
-export(
[ get_connection/1,
get_state/1
]).

%%% Exports for sumo_backend
-export(
[ start_link/2
]).

%%% Exports for gen_server
-export(
[ init/1
, handle_call/3
, handle_cast/2
, handle_info/2
, terminate/2
, code_change/3
]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Types.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-record(state, {conn :: pid(), bucket :: binary(), index :: binary()}).
-type state() :: #state{}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% External API.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec start_link(atom(), proplists:proplist()) -> {ok, pid()}|term().
start_link(Name, Options) ->
gen_server:start_link({local, Name}, ?MODULE, Options, []).

-spec get_connection(atom() | pid()) -> atom().
get_connection(Name) ->
gen_server:call(Name, get_connection).

-spec get_state(atom() | pid()) -> state().
get_state(Name) ->
gen_server:call(Name, get_state).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% gen_server stuff.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec init([term()]) -> {ok, state()}.
init(Options) ->
%% Get connection parameters
Host = proplists:get_value(host, Options, "127.0.0.1"),
Port = proplists:get_value(port, Options, 8087),
Opts = riak_opts(Options),
%% Get DB parameters
BucketType = iolist_to_binary(
proplists:get_value(bucket_type, Options)),
Bucket = iolist_to_binary(
proplists:get_value(bucket, Options, <<"sumo_test">>)),
Index = iolist_to_binary(
proplists:get_value(index, Options, <<"sumo_test_index">>)),
%% Place Riak connection
{ok, Conn} = riakc_pb_socket:start_link(Host, Port, Opts),
%% Initial state
{ok, #state{conn = Conn, bucket = {BucketType, Bucket}, index = Index}}.

-spec handle_call(term(), term(), state()) -> {reply, term(), state()}.
handle_call(get_connection, _From, State = #state{conn = Conn}) ->
{reply, Conn, State};
handle_call(get_state, _From, State) ->
{reply, State, State}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Unused Callbacks
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec handle_cast(term(), state()) -> {noreply, state()}.
handle_cast(_Msg, State) -> {noreply, State}.

-spec handle_info(term(), state()) -> {noreply, state()}.
handle_info(_Msg, State) -> {noreply, State}.

-spec terminate(term(), state()) -> ok.
terminate(_Reason, _State) -> ok.

-spec code_change(term(), state(), term()) -> {ok, state()}.
code_change(_OldVsn, State, _Extra) -> {ok, State}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% gen_server stuff.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec riak_opts([term()]) -> [term()].
riak_opts(Options) ->
User = proplists:get_value(username, Options),
Pass = proplists:get_value(password, Options),
Opts0 = case User /= undefined andalso Pass /= undefined of
true -> [{credentials, User, Pass}];
_ -> []
end,
Opts1 = case lists:keyfind(connect_timeout, 1, Options) of
{_, V1} -> [{connect_timeout, V1}, {auto_reconnect, true}] ++ Opts0;
_ -> [{auto_reconnect, true}] ++ Opts0
end,
Opts1.
Loading

0 comments on commit 758569b

Please sign in to comment.