/src/pourse_db_adapter.erl

https://gitlab.com/Pourse/Server · Erlang · 215 lines · 161 code · 47 blank · 7 comment · 0 complexity · 94f00fe81c4a27d5aff8fc2941a54e44 MD5 · raw file

  1. -module(pourse_db_adapter).
  2. -export([
  3. start/0,
  4. ensure_all_started/0,
  5. new/0,
  6. get/3,
  7. get_index/4,
  8. get_index/5,
  9. get_index/7,
  10. put/4,
  11. put/6,
  12. delete_all/1,
  13. delete/2,
  14. delete/3,
  15. list_keys/2,
  16. get_value/1,
  17. update/2,
  18. add_index/3,
  19. update_index/4,
  20. delete/1
  21. ]).
  22. -include("config.hrl").
  23. start() ->
  24. ok = application:start(riakpool),
  25. ok = start_riakpool(),
  26. ok.
  27. ensure_all_started() ->
  28. application:start(riakpool),
  29. start_riakpool(),
  30. ok.
  31. new() ->
  32. {error, pool_already_started} = start_riakpool(),
  33. {?MODULE}.
  34. start_riakpool() ->
  35. riakpool:start_pool(?env(database, host), ?env(database, port)).
  36. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  37. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  38. get(Bucket, Key, {?MODULE}) ->
  39. {ok, Res} = riakpool:execute(fun(Pid) -> riakc_pb_socket:get(Pid, Bucket, Key) end),
  40. {?MODULE, Res}.
  41. get_index(Bucket, IndexName, Value, {?MODULE}) ->
  42. case typeof(Value) of
  43. "bin" -> IndexType = binary_index;
  44. "int" -> IndexType = integer_index
  45. end,
  46. {ok, {ok, {index_results_v1, Result, _, _}}} =
  47. riakpool:execute(
  48. fun(Pid) ->
  49. riakc_pb_socket:get_index(
  50. Pid,
  51. Bucket,
  52. {IndexType, IndexName},
  53. Value
  54. )
  55. end
  56. ),
  57. {ok, Result}.
  58. get_index(Bucket, IndexName, StartRange, EndRange, {?MODULE}) ->
  59. case typeof(StartRange) of
  60. "bin" -> IndexType = binary_index;
  61. "int" -> IndexType = integer_index
  62. end,
  63. {ok, {ok, {index_results_v1, Result, undefined, undefined}}} =
  64. riakpool:execute(
  65. fun(Pid) ->
  66. riakc_pb_socket:get_index(
  67. Pid,
  68. Bucket,
  69. {IndexType, IndexName},
  70. StartRange, EndRange
  71. )
  72. end
  73. ),
  74. {ok, Result}.
  75. get_index(Bucket, IndexName, StartRange, EndRange, MaxResult, Continuation, {?MODULE}) ->
  76. case typeof(StartRange) of
  77. "bin" -> IndexType = binary_index;
  78. "int" -> IndexType = integer_index
  79. end,
  80. {ok, {ok, {index_results_v1, Result, undefined, NewContinuation}}} =
  81. riakpool:execute(
  82. fun(Pid) ->
  83. riakc_pb_socket:get_index_range(
  84. Pid,
  85. Bucket,
  86. {IndexType, IndexName},
  87. StartRange, EndRange,
  88. [
  89. {max_results, MaxResult},
  90. {continuation, Continuation}
  91. ]
  92. )
  93. end
  94. ),
  95. {ok, Result, NewContinuation}.
  96. put(Bucket, Key, Value, {?MODULE}) ->
  97. %put(Bucket, Key, Value, [], STATE).
  98. Object = riakc_obj:new(Bucket, Key, Value),
  99. {ok, ok} = riakpool:execute(fun(Pid) -> riakc_pb_socket:put(Pid, Object) end),
  100. {?MODULE, {ok, Object}}.
  101. put(Bucket, Key, Value, IndexName, IndexVal, {?MODULE}) ->
  102. Object = riakc_obj:new(Bucket, Key, Value),
  103. add_index(IndexName, IndexVal, {?MODULE, {ok, Object}}).
  104. delete_all({?MODULE}) ->
  105. {ok, {ok, Buckets}} = riakpool:execute(fun(Pid) -> riakc_pb_socket:list_buckets(Pid) end),
  106. lists:foreach(
  107. fun(B) ->
  108. case lists:prefix("Pourse_", binary_to_list(B)) of
  109. true -> delete(B, {?MODULE});
  110. false -> void
  111. end
  112. end,
  113. Buckets
  114. ),
  115. ok.
  116. delete(Bucket, {?MODULE}) ->
  117. Keys = list_keys(Bucket, {?MODULE}),
  118. lists:foreach(fun(Key) -> delete(Bucket, Key, {?MODULE}) end, Keys),
  119. ok.
  120. delete(Bucket, Key, {?MODULE}) ->
  121. ok = riakpool_client:delete(Bucket, Key).
  122. list_keys(Bucket, {?MODULE}) ->
  123. {ok, {ok, Res}} = riakpool:execute(fun(Pid) -> riakc_pb_socket:list_keys(Pid, Bucket) end),
  124. Res.
  125. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  126. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. get_value({?MODULE, {ok, Object}}) ->
  128. Value = binary_to_term(riakc_obj:get_value(Object)),
  129. {ok, Value};
  130. get_value({?MODULE, {error, Reason}}) ->
  131. {error, Reason}.
  132. update(NewValue, {?MODULE, {ok, Object}}) ->
  133. Updated = riakc_obj:update_value(Object, NewValue),
  134. {ok, ok} = riakpool:execute(fun(Pid) -> riakc_pb_socket:put(Pid, Updated) end),
  135. {?MODULE, {ok, Updated}}.
  136. add_index(IndexName, IndexVal, {?MODULE, {ok, Object}}) ->
  137. IndexType = case typeof(IndexVal) of
  138. "bin" -> binary_index;
  139. "int" -> integer_index
  140. end,
  141. Meta = riakc_obj:get_update_metadata(Object),
  142. MD = riakc_obj:set_secondary_index(Meta,[{{IndexType, IndexName}, [IndexVal]}]),
  143. O = riakc_obj:update_metadata(Object, MD),
  144. {ok, ok} = riakpool:execute(fun(Pid) -> riakc_pb_socket:put(Pid, O) end),
  145. {?MODULE, {ok, O}}.
  146. update_index(IndexName, OldValue, NewValue, {?MODULE, {ok, Object}}) ->
  147. Meta = riakc_obj:get_update_metadata(Object),
  148. F = fun({A, B}) ->
  149. case A =:= list_to_binary(IndexName ++ "_" ++ typeof(OldValue)) andalso B =:= binof(OldValue) of
  150. false ->
  151. {A, B};
  152. true ->
  153. {IndexName ++ "_" ++ typeof(NewValue), NewValue}
  154. end
  155. end,
  156. NewMeta = dict:update(<<"index">>, fun(X) -> lists:map(F, X) end, Meta),
  157. O = riakc_obj:update_metadata(Object, NewMeta),
  158. {ok, ok} = riakpool:execute(fun(Pid) -> riakc_pb_socket:put(Pid, O) end),
  159. {?MODULE, {ok, O}}.
  160. delete({?MODULE, {ok, Object}}) ->
  161. {ok, ok} = riakpool:execute(fun(Pid) -> riakc_pb_socket:delete_obj(Pid, Object) end),
  162. ok.
  163. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  164. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  165. typeof(X) when is_binary(X) -> "bin";
  166. typeof(X) when is_integer(X) -> "int".
  167. binof(X) when is_binary(X) -> X;
  168. binof(X) when is_integer(X) -> integer_to_binary(X).