ananthakumaran/memcachex

[BUG] :get return invalid digit format after :decr

Closed this issue · 6 comments

[BUG] :get return invalid digit format after :decr

Environment

  • Memcache (Docker) memcached:1.5.16-alpine
  • Erlang OTP 24.1
  • Elixir 1.13.1
    • {:memcachex, "~> 0.5.4"}

Examples

iex(1)> Memcache.set(pid, "a", "10")
{:ok}
iex(2)> Memcache.decr(pid, "a")      
{:ok, 9}
iex(3)> Memcache.get(pid, "a") 
{:ok, "9 "}
iex(1)> Memcache.set(pid, "a", "100")
{:ok}
iex(2)> Memcache.decr(pid, "a")
{:ok, 99}
iex(3)> Memcache.get(pid, "a")
{:ok, "99 "}

@ananthakumaran Thanks you, but
If use a number when calling set, an error occurs.

iex(1)> Memcache.set(pid, "a", 10)
** (exit) exited in: :gen_server.call(#PID<0.2080.0>, {:execute, :SET, ["a", 10, 0, 86400], %{cas: false}})
    ** (EXIT) an exception was raised:
        ** (ArgumentError) errors were found at the given arguments:

  * 1st argument: not an iodata term

            :erlang.iolist_size(10)
            (memcachex 0.5.4) lib/memcache/protocol.ex:384: Memcache.Protocol.to_binary/7
            (memcachex 0.5.4) lib/memcache/connection.ex:364: Memcache.Connection.send_and_receive/5
            (connection 1.1.0) lib/connection.ex:488: Connection.handle_call/3
            (stdlib 3.16.1) gen_server.erl:721: :gen_server.try_handle_call/4
            (stdlib 3.16.1) gen_server.erl:750: :gen_server.handle_msg/6
            (stdlib 3.16.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
    (stdlib 3.16.1) gen_server.erl:239: :gen_server.call/2
    (memcachex 0.5.4) lib/memcache/connection.ex:133: Memcache.Connection.with_telemetry/2
    (memcachex 0.5.4) lib/memcache.ex:638: Memcache.execute_kv/5

@ananthakumaran
Thank you so much !
Enjoy your vacation.
Now, I'm your fan.

I got some time to look into the issue. Memcache stores everything as a string, so there is no difference between "100" and 100. So your first attempt to use string is correct. The 3rd get command seems to return an extra space. So I looked at the spec once more and came across the relevant part

Note also that decrementing a number such that it loses length isn't
guaranteed to decrement its returned length.  The number MAY be
space-padded at the end, but this is purely an implementation
optimization, so you also shouldn't rely on that.

Seems like this is a valid response from memcached server (though very unintuitive)

I checked ruby client (dalli) to see how it's handled, it's same as what we do now. The response contains an extra space. I am thinking about what can be done at the library level. Trimming space at the end won't work in general case (as we have no idea whether the value is string or integer).

❯ cat test.rb
require 'dalli'
require 'pp'
dc = Dalli::Client.new('localhost:21211')
dc.set('a', 100, 0, raw: true)
pp dc.decr('a')
pp dc.get('a')
❯ bundle exec ruby test.rb
99
"99 "

"(as we have no idea whether the value is string or integer)"
I agree your view.

I'm impressed with your professional skills.
Thank you soooo much @ananthakumaran !
See ya.