Skip to content

Commit 58ed200

Browse files
isapegoivandasch
andauthored
GG-33875 [IGNITE-14850] Document Transactions API (#50)
(cherry picked from commit a53afcc) (cherry picked from commit 0afab5b) (cherry picked from commit c64fb10) Co-authored-by: Ivan Daschinsky <[email protected]>
1 parent 1fc5d32 commit 58ed200

File tree

5 files changed

+239
-13
lines changed

5 files changed

+239
-13
lines changed

docs/async_examples.rst

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,50 @@ Secondly, expiry policy can be set for all cache operations, which are done unde
7777
:dedent: 12
7878
:lines: 96-105
7979

80+
Transactions
81+
------------
82+
File: `transactions.py`_.
83+
84+
Client transactions are supported for caches with
85+
:py:attr:`~pygridgain.datatypes.cache_config.CacheAtomicityMode.TRANSACTIONAL` mode.
86+
87+
Let's create transactional cache:
88+
89+
.. literalinclude:: ../examples/transactions.py
90+
:language: python
91+
:dedent: 8
92+
:lines: 30-33
93+
94+
Let's start a transaction and commit it:
95+
96+
.. literalinclude:: ../examples/transactions.py
97+
:language: python
98+
:dedent: 8
99+
:lines: 36-41
100+
101+
Let's check that the transaction was committed successfully:
102+
103+
.. literalinclude:: ../examples/transactions.py
104+
:language: python
105+
:dedent: 8
106+
:lines: 44-45
107+
108+
Let's check that raising exception inside `async with` block leads to transaction's rollback
109+
110+
.. literalinclude:: ../examples/transactions.py
111+
:language: python
112+
:dedent: 8
113+
:lines: 48-59
114+
115+
Let's check that timed out transaction is successfully rolled back
116+
117+
.. literalinclude:: ../examples/transactions.py
118+
:language: python
119+
:dedent: 8
120+
:lines: 62-73
121+
122+
See more info about transaction's parameters in a documentation of :py:meth:`~pygridgain.aio_client.AioClient.tx_start`
123+
80124
SQL
81125
---
82126
File: `async_sql.py`_.
@@ -170,6 +214,7 @@ Finally, delete the tables used in this example with the following queries:
170214

171215

172216

173-
.. _expiry_policy.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/expiry_policy.py
174-
.. _async_key_value.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/async_key_value.py
175-
.. _async_sql.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/async_sql.py
217+
.. _expiry_policy.py: https://github.com/gridgain/python-thin-client/blob/master/examples/expiry_policy.py
218+
.. _async_key_value.py: https://github.com/gridgain/python-thin-client/blob/master/examples/async_key_value.py
219+
.. _async_sql.py: https://github.com/gridgain/python-thin-client/blob/master/examples/async_sql.py
220+
.. _transactions.py: https://github.com/gridgain/python-thin-client/blob/master/examples/transactions.py

docs/datatypes/cache_props.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Cache Properties
2121
The :mod:`~pygridgain.datatypes.prop_codes` module contains a list of ordinal
2222
values, that represent various cache settings.
2323

24-
Please refer to the `GridGain Data Grid`_ documentation on cache
24+
Please refer to the `Configuring Caches`_ documentation on cache
2525
synchronization, rebalance, affinity and other cache configuration-related
2626
matters.
2727

@@ -161,10 +161,10 @@ A dict of the following format:
161161
- `type_name`: name of the complex object,
162162
- `affinity_key_field_name`: name of the affinity key field.
163163

164-
.. _GridGain Data Grid: https://www.gridgain.com/technology/in-memory-computing-platform/data-grid
164+
.. _Configuring Caches: https://www.gridgain.com/docs/latest/configuring-caches/configuration-overview.html
165165

166166
Expiry policy
167-
-------------
167+
-------------https://www.gridgain.com/docs/latest/developers-guide/configuring-caches/configuration-overview
168168

169169
Set expiry policy to cache (see :py:class:`~pygridgain.datatypes.expiry_policy.ExpiryPolicy`). If set to `None`,
170170
expiry policy will not be set.

docs/examples.rst

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,51 @@ contents. But it still can be used for interoperability with Java.
205205
:dedent: 4
206206
:lines: 56-65
207207

208+
209+
Transactions
210+
------------
211+
File: `transactions.py`_.
212+
213+
Client transactions are supported for caches with
214+
:py:attr:`~pygridgain.datatypes.cache_config.CacheAtomicityMode.TRANSACTIONAL` mode.
215+
216+
Let's create transactional cache:
217+
218+
.. literalinclude:: ../examples/transactions.py
219+
:language: python
220+
:dedent: 8
221+
:lines: 82-85
222+
223+
Let's start a transaction and commit it:
224+
225+
.. literalinclude:: ../examples/transactions.py
226+
:language: python
227+
:dedent: 8
228+
:lines: 88-92
229+
230+
Let's check that the transaction was committed successfully:
231+
232+
.. literalinclude:: ../examples/transactions.py
233+
:language: python
234+
:dedent: 8
235+
:lines: 94-95
236+
237+
Let's check that raising exception inside `with` block leads to transaction's rollback
238+
239+
.. literalinclude:: ../examples/transactions.py
240+
:language: python
241+
:dedent: 8
242+
:lines: 98-108
243+
244+
Let's check that timed out transaction is successfully rolled back
245+
246+
.. literalinclude:: ../examples/transactions.py
247+
:language: python
248+
:dedent: 8
249+
:lines: 111-121
250+
251+
See more info about transaction's parameters in a documentation of :py:meth:`~pygridgain.client.Client.tx_start`
252+
208253
SQL
209254
---
210255
File: `sql.py`_.
@@ -705,26 +750,26 @@ with the following message:
705750
# pygridgain.exceptions.HandshakeError: Handshake error: Unauthenticated sessions are prohibited.
706751
707752
.. _get_and_put.py: https://github.com/gridgain/python-thin-client/tree/master/examples/get_and_put.py
708-
.. _async_key_value.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/async_key_value.py
753+
.. _async_key_value.py: https://github.com/gridgain/python-thin-client/blob/master/examples/async_key_value.py
709754
.. _type_hints.py: https://github.com/gridgain/python-thin-client/tree/master/examples/type_hints.py
710755
.. _failover.py: https://github.com/gridgain/python-thin-client/tree/master/examples/failover.py
711756
.. _scans.py: https://github.com/gridgain/python-thin-client/tree/master/examples/scans.py
712-
.. _expiry_policy.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/expiry_policy.py
757+
.. _expiry_policy.py: https://github.com/gridgain/python-thin-client/blob/master/examples/expiry_policy.py
713758
.. _sql.py: https://github.com/gridgain/python-thin-client/tree/master/examples/sql.py
714-
.. _async_sql.py: https://github.com/apache/ignite-python-thin-client/blob/master/examples/async_sql.py
759+
.. _async_sql.py: https://github.com/gridgain/python-thin-client/blob/master/examples/async_sql.py
715760
.. _binary_basics.py: https://github.com/gridgain/python-thin-client/tree/master/examples/binary_basics.py
716761
.. _read_binary.py: https://github.com/gridgain/python-thin-client/tree/master/examples/read_binary.py
717762
.. _create_binary.py: https://github.com/gridgain/python-thin-client/tree/master/examples/create_binary.py
718763
.. _migrate_binary.py: https://github.com/gridgain/python-thin-client/tree/master/examples/migrate_binary.py
719-
.. _Getting Started: https://ignite.apache.org/docs/latest/quick-start/sql
764+
.. _transactions.py: https://github.com/gridgain/python-thin-client/blob/master/examples/transactions.py
765+
.. _Getting Started: https://www.gridgain.com/docs/latest/getting-started/quick-start/sql
720766
.. _GridGain CE GitHub repository: https://github.com/gridgain/gridgain/blob/master/examples/sql/world.sql
721767
.. _Complex object: https://ignite.apache.org/docs/latest/binary-client-protocol/data-format#complex-object
722768
.. _Java keytool: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html
723-
.. _Securing Connection Between Nodes: https://ignite.apache.org/docs/latest/security/ssl-tls#ssltls-for-nodes
769+
.. _Securing Connection Between Nodes: https://www.gridgain.com/docs/latest/administrators-guide/security/ssl-tls#ssltls-for-nodes
724770
.. _ClientConnectorConfiguration: https://www.gridgain.com/sdk/latest/javadoc/org/apache/ignite/configuration/ClientConnectorConfiguration.html
725771
.. _openssl: https://www.openssl.org/docs/manmaster/man1/openssl.html
726-
.. _Authentication: https://ignite.apache.org/docs/latest/security/authentication
772+
.. _Authentication: https://www.gridgain.com/docs/latest/administrators-guide/security/authentication
727773
.. _attrs: https://pypi.org/project/attrs/
728774
.. _get_and_put_complex.py: https://github.com/gridgain/python-thin-client/tree/master/examples/get_and_put_complex.py
729775
.. _Collection: https://ignite.apache.org/docs/latest/binary-client-protocol/data-format#collection
730-
.. _simple class names: https://ignite.apache.org/docs/latest/data-modeling/binary-marshaller#binary-name-mapper-and-binary-id-mapper

examples/transactions.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#
2+
# Copyright 2021 GridGain Systems, Inc. and Contributors.
3+
#
4+
# Licensed under the GridGain Community Edition License (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
import asyncio
17+
import sys
18+
import time
19+
20+
from pygridgain import AioClient, Client
21+
from pygridgain.datatypes import TransactionIsolation, TransactionConcurrency
22+
from pygridgain.datatypes.prop_codes import PROP_CACHE_ATOMICITY_MODE, PROP_NAME
23+
from pygridgain.datatypes.cache_config import CacheAtomicityMode
24+
from pygridgain.exceptions import CacheError
25+
26+
27+
async def async_example():
28+
client = AioClient()
29+
async with client.connect('127.0.0.1', 10800):
30+
cache = await client.get_or_create_cache({
31+
PROP_NAME: 'tx_cache',
32+
PROP_CACHE_ATOMICITY_MODE: CacheAtomicityMode.TRANSACTIONAL
33+
})
34+
35+
# starting transaction
36+
key = 1
37+
async with client.tx_start(
38+
isolation=TransactionIsolation.REPEATABLE_READ, concurrency=TransactionConcurrency.PESSIMISTIC
39+
) as tx:
40+
await cache.put(key, 'success')
41+
await tx.commit()
42+
43+
# key=1 value=success
44+
val = await cache.get(key)
45+
print(f"key=1 value={val}")
46+
47+
# rollback transaction.
48+
try:
49+
async with client.tx_start(
50+
isolation=TransactionIsolation.REPEATABLE_READ, concurrency=TransactionConcurrency.PESSIMISTIC
51+
):
52+
await cache.put(key, 'fail')
53+
raise RuntimeError('test')
54+
except RuntimeError:
55+
pass
56+
57+
# key=1 value=success
58+
val = await cache.get(key)
59+
print(f"key=1 value={val}")
60+
61+
# rollback transaction on timeout.
62+
try:
63+
async with client.tx_start(timeout=1.0, label='long-tx') as tx:
64+
await cache.put(key, 'fail')
65+
await asyncio.sleep(2.0)
66+
await tx.commit()
67+
except CacheError as e:
68+
# Cache transaction timed out: GridNearTxLocal[...timeout=1000, ... label=long-tx]
69+
print(e)
70+
71+
# key=1 value=success
72+
val = await cache.get(key)
73+
print(f"key=1 value={val}")
74+
75+
# destroy cache
76+
await cache.destroy()
77+
78+
79+
def sync_example():
80+
client = Client()
81+
with client.connect('127.0.0.1', 10800):
82+
cache = client.get_or_create_cache({
83+
PROP_NAME: 'tx_cache',
84+
PROP_CACHE_ATOMICITY_MODE: CacheAtomicityMode.TRANSACTIONAL
85+
})
86+
87+
# starting transaction
88+
with client.tx_start(
89+
isolation=TransactionIsolation.REPEATABLE_READ, concurrency=TransactionConcurrency.PESSIMISTIC
90+
) as tx:
91+
cache.put(1, 'success')
92+
tx.commit()
93+
94+
# key=1 value=success
95+
print(f"key=1 value={cache.get(1)}")
96+
97+
# rollback transaction.
98+
try:
99+
with client.tx_start(
100+
isolation=TransactionIsolation.REPEATABLE_READ, concurrency=TransactionConcurrency.PESSIMISTIC
101+
):
102+
cache.put(1, 'fail')
103+
raise RuntimeError('test')
104+
except RuntimeError:
105+
pass
106+
107+
# key=1 value=success
108+
print(f"key=1 value={cache.get(1)}")
109+
110+
# rollback transaction on timeout.
111+
try:
112+
with client.tx_start(timeout=1.0, label='long-tx') as tx:
113+
cache.put(1, 'fail')
114+
time.sleep(2.0)
115+
tx.commit()
116+
except CacheError as e:
117+
# Cache transaction timed out: GridNearTxLocal[...timeout=1000, ... label=long-tx]
118+
print(e)
119+
120+
# key=1 value=success
121+
print(f"key=1 value={cache.get(1)}")
122+
123+
# destroy cache
124+
cache.destroy()
125+
126+
127+
if __name__ == '__main__':
128+
print("Starting sync example")
129+
sync_example()
130+
131+
if sys.version_info >= (3, 7):
132+
print("Starting async example")
133+
loop = asyncio.get_event_loop()
134+
loop.run_until_complete(async_example())

tests/common/test_transactions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def tx_cache(client):
6868
PROP_NAME: 'tx_cache',
6969
PROP_CACHE_ATOMICITY_MODE: CacheAtomicityMode.TRANSACTIONAL
7070
})
71+
time.sleep(1.0) # Need to sleep because of https://issues.apache.org/jira/browse/IGNITE-14868
7172
yield cache
7273
cache.destroy()
7374

@@ -78,6 +79,7 @@ async def async_tx_cache(async_client):
7879
PROP_NAME: 'tx_cache',
7980
PROP_CACHE_ATOMICITY_MODE: CacheAtomicityMode.TRANSACTIONAL
8081
})
82+
await asyncio.sleep(1.0) # Need to sleep because of https://issues.apache.org/jira/browse/IGNITE-14868
8183
yield cache
8284
await cache.destroy()
8385

0 commit comments

Comments
 (0)