Ok, this is probably not be an issue with the python driver, but I've got it in python, so it is for me.....
I was having a problem implementing a kind of 'row lock' using Lightweight Transactions.
I've boiled the issue down to a very short test program that demonstrates when run against a single
(non-clustered) local cassandra instance - no complications - just as it is... Just run it in
two terminals at the same time, with a different argv[1]...
#=============
import time, sys, os, cassandra
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
instance = sys.argv[1]
cluster = Cluster( auth_provider=PlainTextAuthProvider( username='cassandra', password='cassandra'))
cdb = cluster.connect()
cdb.execute("CREATE KEYSPACE IF NOT EXISTS test WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1}")
cdb.execute("CREATE TABLE IF NOT EXISTS test.test ( id text primary key, val int, lock text )")
cdb.execute("INSERT INTO test.test (id, val, lock) VALUES ('session_id1', 0, '') ")
raw_input( '<Enter> to start ... ')
i = 0
while i < 10000:
i += 1
# set lock
while True:
r = cdb.execute( "UPDATE test.test SET lock = '%s' WHERE id = 'session_id1' IF lock = '' " % instance)
if r[0].applied == True:
break
# check lock and increment val
s0 = cdb.execute("SELECT val,lock FROM test.test WHERE id = 'session_id1' " )[0]
if s0.lock != instance:
print 'error: instance [%s] %s %s' % (instance, s0, r[0])
cdb.execute( "UPDATE test.test SET val = %s WHERE id = 'session_id1'", (s0.val + 1,))
# clear lock
cdb.execute( "UPDATE test.test SET lock = '' WHERE id = 'session_id1' ")
time.sleep( .01)
.... So the 'lock' is just being used here to protect the read/increment/write of the 'val' field.
With a count of 10000 as above, and two instances, the value of 'val' should reach 20000.
It gets close, but no cigar - unless I patch in a 'fix' as follows...
#=============
# set lock
while True:
r = cdb.execute( "UPDATE test.test SET lock = '%s' WHERE id = 'session_id1' IF lock = '' " % instance)
if r[0].applied == True:
s = cdb.execute("SELECT lock FROM test.test WHERE id = 'session_id1' " )
if s[0].lock == instance:
break
# check lock and increment val
#=============
so here, after the string has been posted into 'lock', and applied==True, I now check to see if the value
of 'lock' is what I think it should be - and sometimes it isn't, so with the 'fixed' code it only breaks out of the loop
if the value of 'lock' is correct.
This really isn't what I expected! To me, these Lightweight Transactions don't seem to do what they say on the tin...
Can you throw some light on this please? (I've had this on stackoverflow - 50+ views in 8 or so days, but not a single
comment...)
Thanks again (last one for the moment - I promise...)
Regards
Alan