# Simplex
[![Build Status](https://travis-ci.org/adamkittelson/simplex.svg)](https://travis-ci.org/adamkittelson/simplex)
[![Coverage Status](https://img.shields.io/coveralls/adamkittelson/simplex.svg)](https://coveralls.io/r/adamkittelson/simplex)
An Elixir library for interacting with the [Amazon SimpleDB](http://aws.amazon.com/simpledb/) API.
Requires Elixir ~> 1.0.0
## Installation
Install the [Hex.pm](http://hex.pm) package
1. Add simplex to your `mix.exs` dependencies:
```elixir
def deps do
[
{:simplex, "0.1.2"}
]
end
```
2. Add `:simplex` to your application dependencies:
```elixir
def application do
[applications: [:simplex]]
end
```
#### AWS Keys
To communicate with the SimpleDB API you'll need to provide your AWS Access and Secret keys.
There are two ways to provide your keys to the Simplex library:
1. Set them from within your application
```elixir
Simplex.aws_access_key "your-access-key"
Simplex.aws_secret_access_key "your-secret-access-key"
```
2. Set them as the environment variables `SIMPLEX_AWS_ACCESS_KEY` and `SIMPLEX_AWS_SECRET_ACCESS_KEY`
```
SIMPLEX_AWS_ACCESS_KEY=your-access-key SIMPLEX_AWS_SECRET_ACCESS_KEY=your-secret-access-key iex -S mix
```
3. If not provided by the above two methods Simplex will attempt to retrieve keys from [instance metadata](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) if it's running in EC2 and you launched your instance with an IAM role with permission to access SimpleDB.
#### SimpleDB URL
By default Simplex will send all requests to the us-east-1 SimpleDB url: `https://sdb.amazonaws.com`. If you want to use a [different region](http://docs.aws.amazon.com/general/latest/gr/rande.html#sdb_region) you can change the url by:
1. Setting it from within your application
```elixir
Simplex.simpledb_url "https://sdb.us-west-1.amazonaws.com"
```
2. Set it as the environment variable `SIMPLEX_SIMPLEDB_URL`
```
SIMPLEX_SIMPLEDB_URL=https://sdb.us-west-1.amazonaws.com iex -S mix
```
## Responses
Simplex will respond to SimpleDB requests with a 3 element tuple, either `{:ok, result, response}` or `{:error, messages, response}`
#### %Simplex.Response{}
A Simplex response (third element of the tuple above) has the following fields:
1. body: A Map containing the parsed body of the response
2. status_code: The HTTP status code of the response
3. headers: The response headers
4. raw_body: The raw string of the response body. (XML)
#### Pattern Matching
You can pattern match to determine how to handle the response:
```elixir
case Simplex.Domains.create "new_domain" do
{:ok, result, response} ->
# some happy path stuff here
{:error, messages, response} ->
# handle problems
end
```
## Domains
[Create](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_CreateDomain.html) a new domain.
````elixir
Simplex.Domains.create "new_domain"
````
[List](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_ListDomains.html) domains.
````elixir
Simplex.Domains.list
Simplex.Domains.list(%{"MaxNumberOfDomains" => "10", "NextToken" => "token-from-previous-list-response"})
````
[Delete](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_DeleteDomain.html) a domain.
````elixir
Simplex.Domains.delete "domain_to_delete"
````
## Attributes
[Get](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_GetAttributes.html) attributes of an item.
````elixir
Simplex.Attributes.get("your_domain", "your_item_name")
Simplex.Attributes.get("your_domain", "your_item_name", %{"AttributeName" => "some_attribute", "ConsistentRead" => "true"})
````
[Put](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_PutAttributes.html) attributes on an item (or create a new item).
````elixir
# Attribute values can be strings, lists of strings, or a
# two-element tuple of :replace and a string or list of strings
# The replace tuple indicates that the value should replace the existing
# value for that attribute, rather than be added to its values
Simplex.Attributes.put("your_domain",
"your_item_name",
%{"some_key" => "some_value",
"another_key" => ["a", "list", "of", "values"],
"yet_another_key" => {:replace, "a value to replace the existing value(s) of yet_another_key"},
"one_last_key => {:replace, ["values", "to", "replace", "one_last_key's", "previous", "value(s)"]}})
# put "some_value" in the "some_key" attribute only if
# "other_key" has the "other_value" value
Simplex.Attributes.put("your_domain",
"your_item_name",
%{"some_key" => "some_value"},
%{"Name" => "other_key", "Value" => "other_value"})
````
[Delete](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_DeleteAttributes.html) attributes on an item (or delete an item).
````elixir
# Delete the "some_value" value from the "some_key" attribute
Simplex.Attributes.delete("your_domain",
"your_item_name",
%{"some_key" => "some_value"})
# Delete "your_item_name" if it doesn't have the "some_key" attribute
Simplex.Attributes.delete("your_domain",
"your_item_name",
%{},
%{"Name" => "some_key", "Exists" => "false"})
````
## Select
[Select](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_Select.html) attributes from items matching an expression.
````elixir
Simplex.Select.select("select * from your_domain where some_key = 'some_value'")
````
----
#### TODO:
1. Implement [BatchDeleteAttributes](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_BatchDeleteAttributes.html), [BatchPutAttributes](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_BatchPutAttributes.html), and [DomainMetadata](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API_DomainMetadata.html)
2. Docs
3. [Retries and Exponential Backoff](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/APIUsage.html#APIErrorRetries)
4. Implement Select.select_all / Domains.list_all (automatically follow next_token to load more results if present)