layout | title | nav_order |
---|---|---|
default |
Managing transactions |
5 |
The MarkLogic REST transactions service
supports managing a transaction that can be referenced in
multiple separate calls to other REST API endpoints, with all calls being committed or
rolled back together. The MarkLogic Python client simplifies usage of these endpoints
via a Transaction
class that is also a
Python context manager,
thereby allowing it to handle committing or rolling back the transaction without any user
involvement.
{: .no_toc .text-delta }
- TOC {:toc}
The following example demonstrates writing documents via multiple calls to MarkLogic, all within the same REST API transaction; the example depends on first following the instructions in the setup guide:
from marklogic import Client
from marklogic.documents import Document
client = Client('http://localhost:8000', digest=('python-user', 'pyth0n'))
default_perms = {"rest-reader": ["read", "update"]}
doc1 = Document("/tx/doc1.json", {"doc": 1}, permissions=default_perms)
doc2 = Document("/tx/doc2.json", {"doc": 2}, permissions=default_perms)
with client.transactions.create() as tx:
client.documents.write(doc1, tx=tx).raise_for_status()
client.documents.write(doc2, tx=tx).raise_for_status()
The client.transactions.create()
function returns a Transaction
instance that acts
as the context manager. When the with
block completes, the Transaction
instance
calls the REST API to commit the transaction.
As of 1.1.0, each of the functions in the client.documents
object can include a
reference to the transaction to ensure that the read
or write
or search
operation
occurs within the REST API transaction.
The requests
function raise_for_status()
is used in the example above to ensure that if a request fails, an error is thrown,
causing the transaction to be rolled back. The following example demonstrates a rolled
back transaction due to an invalid JSON object that causes a write
operation to fail:
doc1 = Document("/tx/doc1.json", {"doc": 1}, permissions=default_perms)
doc2 = Document("/tx/doc2.json", "invalid json", permissions=default_perms)
with client.transactions.create() as tx:
client.documents.write(doc1, tx=tx).raise_for_status()
client.documents.write(doc2, tx=tx).raise_for_status()
The above will cause a requests
HTTPError
instance to be thrown, and the first
document will not be written due to the transaction being rolled back.
You are free to check the status code of the response object returned
by each call as well; raise_for_status()
is simply a commonly used convenience in the
requests
library.
You can reference the transaction when calling any REST API endpoint that supports the
optional txid
request parameter. The following example demonstrates this, reusing the
same client
instance from the first example:
with client.transactions.create() as tx:
client.post("/v1/resources/my-resource", params={"txid": tx.id})
client.delete("/v1/resources/other-resource", params={"txid": tx.id})
You can get the
status of the transaction
via the get_status()
function:
with client.transactions.create() as tx:
print(f"Transaction status: {tx.get_status()}")