-module(eetcd_kv). -include("eetcd.hrl"). -export([txn/4]). -export([ from_key/1, with_first_create/1, with_last_create/1, with_first_rev/1, with_last_rev/1, with_first_key/1, with_last_key/1, with_sort/3, with_top/3 ]). -export_type([ range_request/0, sort_target/0, sort_order/0 ]). -type range_request() :: router_pb:'Etcd.RangeRequest'(). -type sort_target() :: 'KEY' | 'VERSION' | 'VALUE' | 'CREATE' | 'MOD'. -type sort_order() :: 'NONE' | 'ASCEND' | 'DESCEND'. -spec from_key(Key :: iodata()) -> map(). from_key(Key) -> #{key => Key, range_end => "\x00"}. %% @doc Specifies the ordering in `get' request. It requires %% `with_range' and/or `with_prefix' to be specified too. %% `target' specifies the target to sort by: 'KEY', 'VERSION', 'VALUE', 'CREATE', 'MOD'. %% `order' can be either 'NONE', 'ASCEND', 'DESCEND'. -spec with_sort(range_request(), sort_target(), sort_order()) -> range_request(). with_sort(Request, SortTarget, SortOrder) -> Targets = router_pb:find_enum_def('Etcd.RangeRequest.SortTarget'), Orders = router_pb:find_enum_def('Etcd.RangeRequest.SortOrder'), (not lists:keymember(SortTarget, 1, Targets)) andalso throw({sort_target, SortTarget}), (not lists:keymember(SortOrder, 1, Orders)) andalso throw({sort_order, SortOrder}), Request#{ sort_target => SortTarget, sort_order => SortOrder }. %% @doc Get the key with the oldest creation revision in the request range. -spec with_first_create(range_request()) -> range_request(). with_first_create(Context) -> with_top(Context, 'CREATE', 'ASCEND'). %% @doc Get the lexically last key in the request range. -spec with_last_create(range_request()) -> range_request(). with_last_create(Context) -> with_top(Context, 'CREATE', 'DESCEND'). %% @doc Get the key with the oldest modification revision in the request range. -spec with_first_rev(range_request()) -> range_request(). with_first_rev(Context) -> with_top(Context, 'MOD', 'ASCEND'). %% @doc Get the key with the latest modification revision in the request range. -spec with_last_rev(range_request()) -> range_request(). with_last_rev(Context) -> with_top(Context, 'MOD', 'DESCEND'). %% @doc Get the lexically first key in the request range. -spec with_first_key(range_request()) -> range_request(). with_first_key(Context) -> with_top(Context, 'KEY', 'ASCEND'). %% @doc Get the lexically last key in the request range. -spec with_last_key(range_request()) -> range_request(). with_last_key(RangeRequest) -> with_top(RangeRequest, 'KEY', 'DESCEND'). %% @doc Get the first key over the get's prefix given a sort order -spec with_top(range_request(), sort_target(), sort_order()) -> range_request(). with_top(#{key := Key} = RangeRequest0, SortTarget, SortOrder) -> RangeEnd = eetcd:get_prefix_range_end(Key), Request = with_sort(RangeRequest0, SortTarget, SortOrder), Request#{range_end => RangeEnd, limit => 1}. %%% @doc Txn creates a transaction. %%