15
15
16
16
logger = logging .getLogger (__name__ )
17
17
18
- # def patch_table_service_tx_mode_to_query_service(tx_mode: AbstractTransactionModeBuilder):
19
- # if tx_mode.name == 'snapshot_read_only':
20
- # tx_mode = _ydb_query_public.QuerySnapshotReadOnly()
21
- # elif tx_mode.name == 'serializable_read_write':
22
- # tx_mode = _ydb_query_public.QuerySerializableReadWrite()
23
- # elif tx_mode.name =='online_read_only':
24
- # tx_mode = _ydb_query_public.QueryOnlineReadOnly()
25
- # elif tx_mode.name == 'stale_read_only':
26
- # tx_mode = _ydb_query_public.QueryStaleReadOnly()
27
- # else:
28
- # raise issues.YDBInvalidArgumentError(f'Unknown transaction mode: {tx_mode.name}')
29
18
30
- # return tx_mode
19
+ class QueryTxStateEnum (enum .Enum ):
20
+ NOT_INITIALIZED = "NOT_INITIALIZED"
21
+ BEGINED = "BEGINED"
22
+ COMMITTED = "COMMITTED"
23
+ ROLLBACKED = "ROLLBACKED"
24
+ DEAD = "DEAD"
25
+
26
+
27
+ class QueryTxStateHelper (abc .ABC ):
28
+ _VALID_TRANSITIONS = {
29
+ QueryTxStateEnum .NOT_INITIALIZED : [QueryTxStateEnum .BEGINED , QueryTxStateEnum .DEAD ],
30
+ QueryTxStateEnum .BEGINED : [QueryTxStateEnum .COMMITTED , QueryTxStateEnum .ROLLBACKED , QueryTxStateEnum .DEAD ],
31
+ QueryTxStateEnum .COMMITTED : [],
32
+ QueryTxStateEnum .ROLLBACKED : [],
33
+ QueryTxStateEnum .DEAD : [],
34
+ }
35
+
36
+ _TERMINAL_STATES = [
37
+ QueryTxStateEnum .COMMITTED ,
38
+ QueryTxStateEnum .ROLLBACKED ,
39
+ QueryTxStateEnum .DEAD ,
40
+ ]
41
+
42
+ @classmethod
43
+ def valid_transition (cls , before : QueryTxStateEnum , after : QueryTxStateEnum ) -> bool :
44
+ return after in cls ._VALID_TRANSITIONS [before ]
45
+
46
+ @classmethod
47
+ def terminal (cls , state : QueryTxStateEnum ) -> bool :
48
+ return state in cls ._TERMINAL_STATES
31
49
32
50
33
51
def reset_tx_id_handler (func ):
@@ -36,7 +54,7 @@ def decorator(rpc_state, response_pb, session_state, tx_state, *args, **kwargs):
36
54
try :
37
55
return func (rpc_state , response_pb , session_state , tx_state , * args , ** kwargs )
38
56
except issues .Error :
39
- tx_state .change_state ( base . QueryTxStateEnum .DEAD )
57
+ tx_state ._change_state ( QueryTxStateEnum .DEAD )
40
58
tx_state .tx_id = None
41
59
raise
42
60
@@ -51,16 +69,23 @@ def __init__(self, tx_mode: base.BaseQueryTxMode):
51
69
"""
52
70
self .tx_id = None
53
71
self .tx_mode = tx_mode
54
- self ._state = base . QueryTxStateEnum .NOT_INITIALIZED
72
+ self ._state = QueryTxStateEnum .NOT_INITIALIZED
55
73
56
- def check_invalid_transition (self , target : base . QueryTxStateEnum ):
57
- if not base . QueryTxStateHelper .is_valid_transition (self ._state , target ):
74
+ def _check_invalid_transition (self , target : QueryTxStateEnum ):
75
+ if not QueryTxStateHelper .valid_transition (self ._state , target ):
58
76
raise RuntimeError (f"Transaction could not be moved from { self ._state .value } to { target .value } " )
59
77
60
- def change_state (self , target : base . QueryTxStateEnum ):
61
- self .check_invalid_transition (target )
78
+ def _change_state (self , target : QueryTxStateEnum ):
79
+ self ._check_invalid_transition (target )
62
80
self ._state = target
63
81
82
+ def _check_tx_not_terminal (self ):
83
+ if QueryTxStateHelper .terminal (self ._state ):
84
+ raise RuntimeError (f"Transaction is in terminal state: { self ._state .value } " )
85
+
86
+ def _already_in (self , target : QueryTxStateEnum ):
87
+ return self ._state == target
88
+
64
89
65
90
def _construct_tx_settings (tx_state ):
66
91
tx_settings = _ydb_query .TransactionSettings .from_public (tx_state .tx_mode )
@@ -93,7 +118,7 @@ def _create_rollback_transaction_request(session_state, tx_state):
93
118
def wrap_tx_begin_response (rpc_state , response_pb , session_state , tx_state , tx ):
94
119
message = _ydb_query .BeginTransactionResponse .from_proto (response_pb )
95
120
issues ._process_response (message .status )
96
- tx_state .change_state ( base . QueryTxStateEnum .BEGINED )
121
+ tx_state ._change_state ( QueryTxStateEnum .BEGINED )
97
122
tx_state .tx_id = message .tx_meta .tx_id
98
123
return tx
99
124
@@ -104,7 +129,7 @@ def wrap_tx_commit_response(rpc_state, response_pb, session_state, tx_state, tx)
104
129
message = _ydb_query .CommitTransactionResponse (response_pb )
105
130
issues ._process_response (message .status )
106
131
tx_state .tx_id = None
107
- tx_state .change_state ( base . QueryTxStateEnum .COMMITTED )
132
+ tx_state ._change_state ( QueryTxStateEnum .COMMITTED )
108
133
return tx
109
134
110
135
@base .bad_session_handler
@@ -113,7 +138,7 @@ def wrap_tx_rollback_response(rpc_state, response_pb, session_state, tx_state, t
113
138
message = _ydb_query .RollbackTransactionResponse (response_pb )
114
139
issues ._process_response (message .status )
115
140
tx_state .tx_id = None
116
- tx_state .change_state ( base . QueryTxStateEnum .ROLLBACKED )
141
+ tx_state ._change_state ( QueryTxStateEnum .ROLLBACKED )
117
142
return tx
118
143
119
144
@@ -196,7 +221,7 @@ def begin(self, settings=None):
196
221
197
222
:return: An open transaction
198
223
"""
199
- self ._tx_state .check_invalid_transition ( base . QueryTxStateEnum .BEGINED )
224
+ self ._tx_state ._check_invalid_transition ( QueryTxStateEnum .BEGINED )
200
225
201
226
return self ._driver (
202
227
_create_begin_transaction_request (self ._session_state , self ._tx_state ),
@@ -216,8 +241,9 @@ def commit(self, settings=None):
216
241
217
242
:return: A committed transaction or exception if commit is failed
218
243
"""
219
-
220
- self ._tx_state .check_invalid_transition (base .QueryTxStateEnum .COMMITTED )
244
+ if self ._tx_state ._already_in (QueryTxStateEnum .COMMITTED ):
245
+ return
246
+ self ._tx_state ._check_invalid_transition (QueryTxStateEnum .COMMITTED )
221
247
222
248
return self ._driver (
223
249
_create_commit_transaction_request (self ._session_state , self ._tx_state ),
@@ -229,7 +255,10 @@ def commit(self, settings=None):
229
255
)
230
256
231
257
def rollback (self , settings = None ):
232
- self ._tx_state .check_invalid_transition (base .QueryTxStateEnum .ROLLBACKED )
258
+ if self ._tx_state ._already_in (QueryTxStateEnum .ROLLBACKED ):
259
+ return
260
+
261
+ self ._tx_state ._check_invalid_transition (QueryTxStateEnum .ROLLBACKED )
233
262
234
263
return self ._driver (
235
264
_create_rollback_transaction_request (self ._session_state , self ._tx_state ),
@@ -240,5 +269,24 @@ def rollback(self, settings=None):
240
269
(self ._session_state , self ._tx_state , self ),
241
270
)
242
271
272
+ def _execute_call (self , query : str , commit_tx : bool ):
273
+ request = base .create_execute_query_request (
274
+ query = query ,
275
+ session_id = self ._session_state .session_id ,
276
+ commit_tx = commit_tx
277
+ )
278
+ return self ._driver (
279
+ request ,
280
+ _apis .QueryService .Stub ,
281
+ _apis .QueryService .ExecuteQuery ,
282
+ )
283
+
243
284
def execute (self , query , parameters = None , commit_tx = False , settings = None ):
244
- pass
285
+ self ._tx_state ._check_tx_not_terminal ()
286
+
287
+ stream_it = self ._execute_call (query , commit_tx )
288
+
289
+ return _utilities .SyncResponseIterator (
290
+ stream_it ,
291
+ lambda resp : base .wrap_execute_query_response (rpc_state = None , response_pb = resp ),
292
+ )
0 commit comments