Skip to content

Commit 271ce7d

Browse files
authored
refactor: polish handling of fail in transaction (#18497)
* refactor: clear txn buffer at once when txn fail. * fix: http handler is no longer sticky if fail to start query.
1 parent 5945e57 commit 271ce7d

File tree

3 files changed

+58
-11
lines changed

3 files changed

+58
-11
lines changed

src/query/service/src/servers/http/v1/query/http_query.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,14 @@ impl HttpQueryRequest {
101101
} else {
102102
s.txn_state.clone()
103103
};
104+
let need_sticky = match &s.internal {
105+
Some(internal) => internal.has_temp_table,
106+
None => false,
107+
};
104108
HttpSessionConf {
105109
txn_state,
110+
need_sticky,
111+
need_keep_alive: need_sticky,
106112
..s.clone()
107113
}
108114
});
@@ -748,7 +754,7 @@ impl HttpQuery {
748754
);
749755

750756
if is_stopped
751-
&& txn_state != TxnState::AutoCommit
757+
&& txn_state == TxnState::Active
752758
&& !self.is_txn_mgr_saved.load(Ordering::Relaxed)
753759
&& self
754760
.is_txn_mgr_saved
@@ -764,7 +770,7 @@ impl HttpQuery {
764770
.await;
765771
}
766772

767-
let need_sticky = txn_state != TxnState::AutoCommit || has_temp_table;
773+
let need_sticky = txn_state == TxnState::Active || has_temp_table;
768774
let need_keep_alive = need_sticky;
769775

770776
Ok(HttpSessionConf {

src/query/storages/common/session/src/transaction.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl TxnManager {
167167

168168
pub fn set_fail(&mut self) {
169169
if let TxnState::Active = self.state {
170-
self.state = TxnState::Fail;
170+
self.force_set_fail()
171171
}
172172
}
173173

@@ -177,6 +177,8 @@ impl TxnManager {
177177

178178
pub fn force_set_fail(&mut self) {
179179
self.state = TxnState::Fail;
180+
self.txn_buffer.clear();
181+
// keep the txn_id until commit/abort for tracing
180182
}
181183

182184
pub fn is_fail(&self) -> bool {

tests/suites/1_stateful/09_http_handler/09_0008_forward.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ def do_query(query, port=8000, session=None, node_id=None, wait=100):
2828
return response
2929

3030

31-
def test_txn():
31+
def get_txn_state(resp):
32+
return (resp.get("state") == "Succeeded",
33+
resp.get("session").get("need_sticky"),
34+
resp.get("session").get("txn_state"))
35+
36+
def test_txn_success():
3237
resp = do_query("create or replace table t1(a int)").json()
3338
assert not (resp.get("session").get("need_sticky")), resp
3439

@@ -37,21 +42,54 @@ def test_txn():
3742
node_id = resp.get("node_id")
3843
session = resp.get("session")
3944

40-
# can not find txn state in node 2
41-
resp = do_query("insert into t1 values (1)", port=8002, session=session).json()
42-
assert resp.get("state") == "Failed", resp.text
43-
4445
# forward to node 1
4546
resp = do_query(
4647
"insert into t1 values (2)", port=8002, session=session, node_id=node_id
4748
).json()
48-
assert resp.get("state") == "Succeeded", resp
49-
assert resp.get("session").get("need_sticky"), resp
49+
assert get_txn_state(resp) == (True, True, "Active"), resp
5050

5151
# return need_sticky = false after commit
5252
resp = do_query("commit").json()
53+
assert get_txn_state(resp) == (True, False, "AutoCommit"), resp
54+
55+
56+
def test_txn_fail():
57+
resp = do_query("create or replace table t1(a int)").json()
5358
assert not (resp.get("session").get("need_sticky")), resp
5459

60+
resp = do_query("begin").json()
61+
assert resp.get("session").get("need_sticky"), resp
62+
node_id = resp.get("node_id")
63+
session = resp.get("session")
64+
65+
# fail
66+
resp = do_query(
67+
"select 1/0", session=session
68+
).json()
69+
assert get_txn_state(resp) == (False, False, "Fail"), resp
70+
71+
# fail because wrong node
72+
resp = do_query(
73+
"select 1", port=8002, session=session
74+
).json()
75+
session = resp.get("session")
76+
assert get_txn_state(resp) == (False, False, "Fail"), resp
77+
78+
# keep fail state until commit/abort
79+
resp = do_query(
80+
"select 1", session=session, node_id=node_id
81+
).json()
82+
assert get_txn_state(resp) == (False, False, "Fail"), resp
83+
session = resp.get("session")
84+
85+
# return need_sticky = false after commit
86+
resp = do_query("commit", session=session).json()
87+
assert get_txn_state(resp) == (True, False, "AutoCommit"), resp
88+
89+
# return need_sticky = false after abort
90+
resp = do_query("abort", session=session).json()
91+
assert get_txn_state(resp) == (True, False, "AutoCommit"), resp
92+
5593

5694
def test_query():
5795
"""each query is sticky"""
@@ -104,7 +142,8 @@ def main():
104142
return
105143

106144
test_query()
107-
test_txn()
145+
test_txn_success()
146+
test_txn_fail()
108147

109148

110149
if __name__ == "__main__":

0 commit comments

Comments
 (0)