Skip to content

Instantly share code, notes, and snippets.

@binarytemple
Last active April 20, 2016 16:37
Show Gist options
  • Save binarytemple/7fa3b01957a44cf0fcfc9f37c139ff5d to your computer and use it in GitHub Desktop.
Save binarytemple/7fa3b01957a44cf0fcfc9f37c139ff5d to your computer and use it in GitHub Desktop.

Some trivial experiments I performed while exploring the integration of Riak and Elixir (thanks Drew Kerrigan)

Error seen while running with a single node.

iex(120)> Riak.find("user", "hero")
** (FunctionClauseError) no function clause matching in Riak.find/4
    (riak) lib/riak.ex:301: Riak.find(:error_no_members, :error_no_members, "user", "hero")
    (riak) lib/riak.ex:301: Riak.find/3
    (riak) lib/riak.ex:282: Riak.find/2

Successfull GET

iex(120)> Riak.find("user", "hero")
%Riak.Object{bucket: "user", content_type: 'application/json',
 data: "han solo the second", key: "hero",
 metadata: {:dict, 3, 16, 16, 8, 80, 48,
  {[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []},
  {{[], [], [], [], [], [], [], [], [], [],
    [["content-type", 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47,
      106, 115, 111, 110],
     ["X-Riak-VTag", 52, 107, 107, 70, 111, 69, 106, 68, 118, 108, 52, 107, 68,
      50, 97, 121, 86, 55, 104, 121, 56, 68]], [], [],
    [["X-Riak-Last-Modified" | {1461, 97432, 474244}]], [], []}}},
 type: :undefined,
 vclock: <<107, 206, 97, 96, 96, 96, 204, 96, 202, 5, 82, 60, 202, 156, 255, 126, 126, 232, 153, 215, 192, 192, 224, 167, 152, 193, 148, 40, 152, 199, 202, 112, 131, 191, 251, 2, 95, 22, 0>>}

We would need to implement the Access behavior (Protocol) for the 'Riak.Object' in order to access it's attributes in a single call (TODO)

iex(121)> Riak.find("user", "hero")[:data]
** (UndefinedFunctionError) undefined function Riak.Object.fetch/2 (Riak.Object does not implement the Access behaviour)
      (riak) Riak.Object.fetch(%Riak.Object{bucket: "user", content_type: 'application/json', data: "han solo the second", key: "hero", metadata: {:dict, 3, 16, 16, 8, 80, 48, {[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []}, {{[], [], [], [], [], [], [], [], [], [], [["content-type", 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, 115, 111, 110], ["X-Riak-VTag", 52, 107, 107, 70, 111, 69, 106, 68, 118, 108, 52, 107, 68, 50, 97, 121, 86, 55, 104, 121, 56, 68]], [], [], [["X-Riak-Last-Modified" | {1461, 97432, 474244}]], [], []}}}, type: :undefined, vclock: <<107, 206, 97, 96, 96, 96, 204, 96, 202, 5, 82, 60, 202, 156, 255, 126, 126, 232, 153, 215, 192, 192, 224, 167, 152, 193, 148, 40, 152, 199, 202, 112, 131, 191, 251, 2, 95, 22, 0>>}, :data)

Accessing the attribute 'data' - having performed a sucessfull fetch and assigned to r:

iex(124)> r.data
"han solo the second"

Inspecting in order to determine if the result is indeed a Record, it is in fact a Struct (a Map with a __struct__ attribute):

iex(129)> require Record
nil
iex(130)> Record.is_record(r)
false

Converting to a Map

iex(131)> Map.from_struct(r)
%{bucket: "user", content_type: 'application/json', data: "han solo the second",
  key: "hero",
  metadata: {:dict, 3, 16, 16, 8, 80, 48,
   {[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []},
   {{[], [], [], [], [], [], [], [], [], [],
     [["content-type", 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47,
       106, 115, 111, 110],
      ["X-Riak-VTag", 52, 107, 107, 70, 111, 69, 106, 68, 118, 108, 52, 107, 68,
       50, 97, 121, 86, 55, 104, 121, 56, 68]], [], [],
     [["X-Riak-Last-Modified" | {1461, 97432, 474244}]], [], []}}},
  type: :undefined,
  vclock: <<107, 206, 97, 96, 96, 96, 204, 96, 202, 5, 82, 60, 202, 156, 255, 126, 126, 232, 153, 215, 192, 192, 224, 167, 152, 193, 148, 40, 152, 199, 202, 112, 131, 191, 251, 2, 95, 22, 0>>}

And here's the __struct__ attribute, it dereferences to Riak.Object:

iex(134)> r.__struct__
Riak.Object

How to perform matching the ugly way:

iex(144)> is_map(r) && Map.has_key?(r,:__struct__) && r.__struct__ == Riak.Object
true

And two other ways of matching on 'type' - firstly for function clauses:

iex(148)> match?(%Riak.Object{}, r)
true

Or:

iex(149)> %Riak.Object{} = r
%Riak.Object{bucket: "user", content_type: 'application/json',
 data: "han solo the second", key: "hero",
 metadata: {:dict, 3, 16, 16, 8, 80, 48,
  {[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []},
  {{[], [], [], [], [], [], [], [], [], [],
    [["content-type", 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47,
      106, 115, 111, 110],
     ["X-Riak-VTag", 52, 107, 107, 70, 111, 69, 106, 68, 118, 108, 52, 107, 68,
      50, 97, 121, 86, 55, 104, 121, 56, 68]], [], [],
    [["X-Riak-Last-Modified" | {1461, 97432, 474244}]], [], []}}},
 type: :undefined,
 vclock: <<107, 206, 97, 96, 96, 96, 204, 96, 202, 5, 82, 60, 202, 156, 255, 126, 126, 232, 153, 215, 192, 192, 224, 167, 152, 193, 148, 40, 152, 199, 202, 112, 131, 191, 251, 2, 95, 22, 0>>}

And how to match when using case statement pattern matching:

iex(152)> case r do
...(152)> %Riak.Object{} = r -> true
...(152)> _ -> false
...(152)> end
true

Fini

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment