Packages
erlcloud
0.9.2-rc.1
3.8.3
3.8.2
3.8.1
3.7.6
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.8
3.6.7
3.6.5
3.6.4
3.6.3
3.6.2
3.6.1
3.6.0
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.5
3.4.3
3.4.1
3.4.0
3.3.9
3.3.8
3.3.7
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.18
3.2.17
3.2.16
3.2.15
3.2.14
3.2.13
3.2.12
3.2.11
3.2.10
3.2.7
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.17
3.1.16
3.1.14
3.1.13
3.1.12
3.1.11
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
2.2.16
2.2.15
2.2.14
2.2.13
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.2
2.2.1
2.2.0
2.1.0
2.0.5
2.0.4
2.0.3
2.0.0
0.13.10
0.13.9
0.13.8
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.0
0.12.0
0.11.0
0.9.2
0.9.2-rc.1
0.9.1
0.9.0
AWS APIs library for Erlang
Current section
Files
Jump to
Current section
Files
src/erlcloud_ddb1.erl
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% @author Ransom Richardson <ransom@ransomr.net>
%% @doc
%% An low level Erlang interface to Amazon's DynamoDB.
%%
%% This API is lower level than the one in `erlcloud_ddb'. It takes JSON terms as
%% defined by `jsx'.
%%
%% @end
-module(erlcloud_ddb1).
-include("erlcloud.hrl").
-include("erlcloud_aws.hrl").
%% DDB API Functions
-export([batch_get_item/1, batch_get_item/2,
batch_write_item/1, batch_write_item/2,
create_table/4, create_table/5,
delete_item/2, delete_item/3, delete_item/4,
delete_table/1, delete_table/2,
describe_table/1, describe_table/2,
get_item/2, get_item/3, get_item/4,
list_tables/0, list_tables/1, list_tables/2,
put_item/2, put_item/3, put_item/4,
%% Note that query is a Erlang reserved word, so we use q instead
q/2, q/3, q/4,
scan/1, scan/2, scan/3,
update_item/3, update_item/4, update_item/5,
update_table/3, update_table/4
]).
%% Helpers
-export([key_value/1, backoff/1, retry/2]).
-export_type([key/0, key_schema_value/0, key_schema/0, json_return/0,
batch_write_item_request/0, attempt/0, retry_fun/0]).
-type table_name() :: binary().
-type attr_type() :: binary().
-type attr_value() :: binary().
-type attr() :: {attr_type(), attr_value()}.
-type hash_key() :: attr().
-type range_key() :: attr().
-type hash_range_key() :: {hash_key(), range_key()}.
-type key() :: hash_key() | hash_range_key().
-type attr_name() :: binary().
-type key_schema_value() :: {attr_name(), attr_type()}.
-type key_schema() :: key_schema_value() | {key_schema_value(), key_schema_value()}.
-type item() :: jsx:json_term().
-type opts() :: jsx:json_term().
-type updates() :: jsx:json_term().
-type json_return() :: {ok, jsx:json_term()} | {error, term()}.
-spec key_value(key()) -> jsx:json_term().
key_value({{HK, HV} = HashKey, {RK, RV} = RangeKey}) when
is_binary(HK), is_binary(HV), is_binary(RK), is_binary(RV) ->
[{<<"HashKeyElement">>, [HashKey]}, {<<"RangeKeyElement">>, [RangeKey]}];
key_value({HK, HV} = HashKey) when
is_binary(HK), is_binary(HV) ->
[{<<"HashKeyElement">>, [HashKey]}].
-spec key_json(key()) -> {binary(), jsx:json_term()}.
key_json(Key) ->
{<<"Key">>, key_value(Key)}.
-spec hash_key_json(hash_key()) -> {binary(), jsx:json_term()}.
hash_key_json(HashKey) ->
{<<"HashKeyValue">>, [HashKey]}.
-spec item_json(item()) -> {binary(), item()}.
item_json(Item) ->
{<<"Item">>, Item}.
-spec updates_json(updates()) -> {binary(), updates()}.
updates_json(Updates) ->
{<<"AttributeUpdates">>, Updates}.
-type batch_get_item_request_item() :: {table_name(), [key(),...], opts()} | {table_name(), [key(),...]}.
-spec batch_get_item_request_item_json(batch_get_item_request_item()) -> {binary(), jsx:json_term()}.
batch_get_item_request_item_json({Table, Keys}) ->
batch_get_item_request_item_json({Table, Keys, []});
batch_get_item_request_item_json({Table, Keys, Opts}) ->
{Table, [{<<"Keys">>, [key_value(K) || K <- Keys]}] ++ Opts}.
-spec batch_get_item([batch_get_item_request_item()]) -> json_return().
batch_get_item(RequestItems) ->
batch_get_item(RequestItems, default_config()).
-spec batch_get_item([batch_get_item_request_item()], aws_config()) -> json_return().
batch_get_item(RequestItems, Config) ->
Json = [{<<"RequestItems">>, [batch_get_item_request_item_json(R) || R <- RequestItems]}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.BatchGetItem", Json).
-type batch_write_item_put() :: {put, item()}.
-type batch_write_item_delete() :: {delete, key()}.
-type batch_write_item_request() :: batch_write_item_put() | batch_write_item_delete().
-type batch_write_item_request_item() :: {table_name(), [batch_write_item_request()]}.
-spec batch_write_item_request_json(batch_write_item_request()) -> {binary(), jsx:json_term()}.
batch_write_item_request_json({put, Item}) ->
{<<"PutRequest">>, [item_json(Item)]};
batch_write_item_request_json({delete, Key}) ->
{<<"DeleteRequest">>, [key_json(Key)]}.
-spec batch_write_item_request_item_json(batch_write_item_request_item()) -> {binary(), jsx:json_term()}.
batch_write_item_request_item_json({Table, Requests}) ->
{Table, [[batch_write_item_request_json(R)] || R <- Requests]}.
-spec batch_write_item([batch_write_item_request_item()]) -> json_return().
batch_write_item(RequestItems) ->
batch_get_item(RequestItems, default_config()).
-spec batch_write_item([batch_write_item_request_item()], aws_config()) -> json_return().
batch_write_item(RequestItems, Config) ->
Json = [{<<"RequestItems">>, [batch_write_item_request_item_json(R) || R <- RequestItems]}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.BatchWriteItem", Json).
-spec key_schema_value_json(key_schema_value()) -> jsx:json_term().
key_schema_value_json({Name, Type}) ->
[{<<"AttributeName">>, Name}, {<<"AttributeType">>, Type}].
-spec key_schema_json(key_schema()) -> {binary(), jsx:json_term()}.
key_schema_json({{_, _} = HashKey, {_, _} = RangeKey}) ->
{<<"KeySchema">>, [{<<"HashKeyElement">>, key_schema_value_json(HashKey)},
{<<"RangeKeyElement">>, key_schema_value_json(RangeKey)}]};
key_schema_json(HashKey) ->
{<<"KeySchema">>, [{<<"HashKeyElement">>, key_schema_value_json(HashKey)}]}.
-spec create_table(table_name(), key_schema(), non_neg_integer(), non_neg_integer()) -> json_return().
create_table(Table, KeySchema, ReadUnits, WriteUnits) ->
create_table(Table, KeySchema, ReadUnits, WriteUnits, default_config()).
-spec create_table(table_name(), key_schema(), non_neg_integer(), non_neg_integer(), aws_config()) -> json_return().
create_table(Table, KeySchema, ReadUnits, WriteUnits, Config) ->
Json = [{<<"TableName">>, Table},
key_schema_json(KeySchema),
{<<"ProvisionedThroughput">>, [{<<"ReadCapacityUnits">>, ReadUnits},
{<<"WriteCapacityUnits">>, WriteUnits}]}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.CreateTable", Json).
-spec delete_item(table_name(), key()) -> json_return().
delete_item(Table, Key) ->
delete_item(Table, Key, [], default_config()).
-spec delete_item(table_name(), key(), opts()) -> json_return().
delete_item(Table, Key, Opts) ->
delete_item(Table, Key, Opts, default_config()).
-spec delete_item(table_name(), key(), opts(), aws_config()) -> json_return().
delete_item(Table, Key, Opts, Config) ->
Json = [{<<"TableName">>, Table},
key_json(Key)]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.DeleteItem", Json).
-spec delete_table(table_name()) -> json_return().
delete_table(Table) ->
delete_table(Table, default_config()).
-spec delete_table(table_name(), aws_config()) -> json_return().
delete_table(Table, Config) ->
Json = [{<<"TableName">>, Table}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.DeleteTable", Json).
-spec describe_table(table_name()) -> json_return().
describe_table(Table) ->
describe_table(Table, default_config()).
-spec describe_table(table_name(), aws_config()) -> json_return().
describe_table(Table, Config) ->
Json = [{<<"TableName">>, Table}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.DescribeTable", Json).
-spec get_item(table_name(), key()) -> json_return().
get_item(Table, Key) ->
get_item(Table, Key, [], default_config()).
-spec get_item(table_name(), key(), opts()) -> json_return().
get_item(Table, Key, Opts) ->
get_item(Table, Key, Opts, default_config()).
-spec get_item(table_name(), key(), opts(), aws_config()) -> json_return().
get_item(Table, Key, Opts, Config) ->
Json = [{<<"TableName">>, Table},
key_json(Key)]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.GetItem", Json).
-spec list_tables() -> json_return().
list_tables() ->
list_tables([], default_config()).
-spec list_tables(opts()) -> json_return().
list_tables(Opts) ->
list_tables(Opts, default_config()).
-spec list_tables(opts(), aws_config()) -> json_return().
list_tables(Opts, Config) ->
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.ListTables", Opts).
-spec put_item(table_name(), item()) -> json_return().
put_item(Table, Item) ->
put_item(Table, Item, [], default_config()).
-spec put_item(table_name(), item(), opts()) -> json_return().
put_item(Table, Item, Opts) ->
put_item(Table, Item, Opts, default_config()).
-spec put_item(table_name(), item(), opts(), aws_config()) -> json_return().
put_item(Table, Item, Opts, Config) ->
Json = [{<<"TableName">>, Table},
item_json(Item)]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.PutItem", Json).
-spec q(table_name(), hash_key()) -> json_return().
q(Table, HashKey) ->
q(Table, HashKey, [], default_config()).
-spec q(table_name(), hash_key(), opts()) -> json_return().
q(Table, HashKey, Opts) ->
q(Table, HashKey, Opts, default_config()).
-spec q(table_name(), hash_key(), opts(), aws_config()) -> json_return().
q(Table, HashKey, Opts, Config) ->
Json = [{<<"TableName">>, Table},
hash_key_json(HashKey)]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.Query", Json).
-spec scan(table_name()) -> json_return().
scan(Table) ->
scan(Table, [], default_config()).
-spec scan(table_name(), opts()) -> json_return().
scan(Table, Opts) ->
scan(Table, Opts, default_config()).
-spec scan(table_name(), opts(), aws_config()) -> json_return().
scan(Table, Opts, Config) ->
Json = [{<<"TableName">>, Table}]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.Scan", Json).
-spec update_item(table_name(), key(), updates()) -> json_return().
update_item(Table, Key, Updates) ->
update_item(Table, Key, Updates, [], default_config()).
-spec update_item(table_name(), key(), updates(), opts()) -> json_return().
update_item(Table, Key, Updates, Opts) ->
update_item(Table, Key, Updates, Opts, default_config()).
-spec update_item(table_name(), key(), updates(), opts(), aws_config()) -> json_return().
update_item(Table, Key, Updates, Opts, Config) ->
Json = [{<<"TableName">>, Table},
key_json(Key),
updates_json(Updates)]
++ Opts,
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.UpdateItem", Json).
-spec update_table(table_name(), non_neg_integer(), non_neg_integer()) -> json_return().
update_table(Table, ReadUnits, WriteUnits) ->
update_table(Table, ReadUnits, WriteUnits, default_config()).
-spec update_table(table_name(), non_neg_integer(), non_neg_integer(), aws_config()) -> json_return().
update_table(Table, ReadUnits, WriteUnits, Config) ->
Json = [{<<"TableName">>, Table},
{<<"ProvisionedThroughput">>, [{<<"ReadCapacityUnits">>, ReadUnits},
{<<"WriteCapacityUnits">>, WriteUnits}]}],
erlcloud_ddb_impl:request(Config, "DynamoDB_20111205.UpdateTable", Json).
%% backoff and retry are here for backwards compat. Use the ones in erlcloud_ddb_impl instead.
-define(NUM_ATTEMPTS, 10).
%% Sleep after an attempt
-spec backoff(pos_integer()) -> ok.
backoff(1) -> ok;
backoff(Attempt) ->
timer:sleep(random:uniform((1 bsl (Attempt - 1)) * 100)).
-type attempt() :: {attempt, pos_integer()} | {error, term()}.
-type retry_fun() :: fun((pos_integer(), term()) -> attempt()).
-spec retry(pos_integer(), term()) -> attempt().
retry(Attempt, Reason) when Attempt >= ?NUM_ATTEMPTS ->
{error, Reason};
retry(Attempt, _) ->
backoff(Attempt),
{attempt, Attempt + 1}.
default_config() -> erlcloud_aws:default_config().