Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Looks like simple CAS setup doesn't work #139

Open
ghost opened this issue Dec 27, 2017 · 4 comments
Open

Looks like simple CAS setup doesn't work #139

ghost opened this issue Dec 27, 2017 · 4 comments

Comments

@ghost
Copy link

ghost commented Dec 27, 2017

I've tested simple CAS setup, two parallel python processes updating some key on single shared server:

  1. Set the key:
mc.set('k', 0)
  1. Run two processes with that code:
for x in range(10**5):
    while True:
        k = mc.gets('k')
        if mc.cas('k', k+1):
            break
  1. Read the key:
mc.get('k')
# some random number less than 2*10^5 (usually about 1.5*10^5)

The cas() call never failed.
Same test, but with cas() replaced by incr() always gives 2*10^5

Python 3.6.3, python-memcached==1.59, everything was inside docker-compose setup

@dropwhile
Copy link
Contributor

You can use ngrep to dump the traffic, and look at STORE and EXISTS responses.

From the protocol "spec":

After sending the command line and the data block the client awaits
the reply, which may be:

- "STORED\r\n", to indicate success.

- "NOT_STORED\r\n" to indicate the data was not stored, but not
because of an error. This normally means that the
condition for an "add" or a "replace" command wasn't met.

- "EXISTS\r\n" to indicate that the item you are trying to store with
a "cas" command has been modified since you last fetched it.

- "NOT_FOUND\r\n" to indicate that the item you are trying to store
with a "cas" command did not exist.

@ghost
Copy link
Author

ghost commented Feb 5, 2018

I've tried ngrep and discovered that cas command is actually not used.

Looks like cas_ids are not set for some reason and that causes using set command in place of cas:

In [10]: cl.gets('a')
Out[10]: '2'

In [11]: cl.cas_ids
Out[11]: {}

I can write tests and fixes for cas functionality, if PR's for that subsystem are welcome.

@dropwhile
Copy link
Contributor

Did you ensure that cache_cas=True was set when you initialized the clients?
According to this line if that isn't set, the cas_id basically gets ignored.

@ghost
Copy link
Author

ghost commented Mar 5, 2018

I've finally got time to debug that

Looks like there are two problems:

  • cas is ignored silently without cache_cas=True
  • cas command checks for 'i' key in cas_ids, but the dictionary has b'i' key, so cas is just ignored silently

After settting cache_cas=True and manually patching cas_ids between gets() and cas() calls I've finally got actual cas command in ngrep output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant