Transaction API hangs on getting non-existing document in Python client

The new Multi-Document Transaction API in CouchBase looks promising from documentation.

Unfortunately, for some strange reason, client hangs when trying to get a non-existing document inside a transaction.

Environment:

  • Server side:
    • CouchBase 6.6.5, official image
  • Client side:
    • Linux Alpine 3.17
    • Python 3.10.10
    • Python SDK 4.1.3, built from source

Minimal code example:

cluster = Cluster(COUCHBASE_URI, ClusterOptions(
    PasswordAuthenticator(COUCHBASE_USER, COUCHBASE_PASS),
    # New client tries to fetch DNS SRV record when supplied with just one host
    enable_dns_srv=False,
))

def txn_logic(ctx):
    col = cluster.bucket(COUCHBASE_BUCKET).default_collection()
    ctx.get(col, "this_record_does_not_exist")

cluster.transactions.run(txn_logic)

Actual Result: application hangs forever, does not respond to interrupts, can only be killed
Other operations like get (for existing document), insert, replace work fine.

Expected Result: anything else, like raising exception or returning None

Any help of this problem appreciated.

Hi @vkhoroz
Well that’s certainly not expected - it should raise a TransactionFailed exception. It’s a scenario we test internally, and you’re on an up-to-date SDK, so I’m not sure what’s going on there. Perhaps our Python SDK guru @jcasey has some ideas.

Thanks @mreiche

Your latest post was saying that “it is reproducible”; but for some reason it is now deleted.

So, did you manage to reproduce it internally, or not?
What is the current plan for this?

It’s being investigated.

1 Like

Hi @vkhoroz – I have created PYCBC-1474 to address the issue. The root cause has been located and the change should be straight forward so we should be able to have the fix in w/ the next release of the Python SDK.

1 Like

Thanks @jcasey !

Just FYI, current documentation on transactions says that the code should raise a DocumentNotFoundException in this case, not a TransactionFailed.
I was going to leverage that property to be able to write a code like this (based on doc examples):

new_value = {"some": "value"}

def txn_logic(ctx):
    col = cluster.bucket(COUCHBASE_BUCKET).default_collection()
    try:
        val = ctx.get(col, "some_document")
    except DocumentNotFoundException:
        ctx.insert(col, "some_document", new_value)
    else:
        # maybe, do some amendments here based on the current value
        ctx.replace(val, new_value)

cluster.transactions.run(txn_logic)

I hope your plans for the fix are aligned with that, right?

Hi @vkhoroz – Yes, the plan is to align w/ the txn docs. To Graham’s point we would raise a TransactionFailed exception if the exception was not handled w/in the lambda. Within the lambda though it should be a DocumentNotFoundException.

2 Likes

This is probably an off-topic, but I find this thread to be the easiest way to deliver a message on transactions…

Can these two debug lines be removed in the next version, or at least wrapped into a debug log:

Under load these logs tend to be quite annoying:

2023-04-18 19:22:54,861 INFO: created transactions object using config=<couchbase.options.TransactionConfig object at 0x7ffa4728e320>, serializer=<couchbase.serializer.DefaultJsonSerializer object at 0x7ffa4728e380>
None
kwargs: {}
None
kwargs: {}
None
kwargs: {}
None
kwargs: {}
...

The “created transaction object” is OK, the rest doesn’t seem to bring much value in production.

Jared said he would do it in PYCBC-1474 .

Hi @vkhoroz - PYCBC-1474 has been implemented. We have updated the logic and added tests to verify functionality to be as expected. Hopefully have version 4.1.4 of the SDK released late next week. Also, as a part of the PYCBC-1474 work we have removed the unnecessary statements.

Feel free to grab the latest from Github in the interim.

2 Likes

Thank you, Jared @jcasey ! :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.