Skip to content

Commit 653331b

Browse files
committed
RDBC-1048 Fix cluster transaction validation, compare exchange state checks, and batch patch status handling
1 parent c60cd18 commit 653331b

4 files changed

Lines changed: 70 additions & 5 deletions

File tree

ravendb/documents/operations/batch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def _handle_patch(self, batch_result: dict) -> None:
190190
self._throw_missing_field(CommandType.PATCH, "PatchStatus")
191191

192192
status = PatchStatus(patch_status)
193-
if status == PatchStatus.CREATED or PatchStatus.PATCHED:
193+
if status in (PatchStatus.CREATED, PatchStatus.PATCHED):
194194
document = batch_result.get("ModifiedDocument")
195195
if not document:
196196
return

ravendb/documents/operations/compare_exchange/compare_exchange.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def delete(self, index: int) -> None:
133133
self._state = CompareExchangeValueState.DELETED
134134

135135
def __assert_state(self) -> None:
136-
if self._state == CompareExchangeValueState.NONE or CompareExchangeValueState.MISSING:
136+
if self._state in (CompareExchangeValueState.NONE, CompareExchangeValueState.MISSING):
137137
return
138138
elif self._state == CompareExchangeValueState.CREATED:
139139
raise RuntimeError(f"The compare exchange value with key {self._key} was already stored.")
@@ -144,7 +144,7 @@ def get_command(
144144
self, conventions: DocumentConventions
145145
) -> Optional[Union[DeleteCompareExchangeCommandData, PutCompareExchangeCommandData]]:
146146
s = self._state
147-
if s == CompareExchangeValueState.NONE or CompareExchangeValueState.CREATED:
147+
if s in (CompareExchangeValueState.NONE, CompareExchangeValueState.CREATED):
148148
if not self.__value:
149149
return None
150150

ravendb/documents/session/document_session_operations/in_memory_document_session_operations.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,13 +985,13 @@ def validate_cluster_transaction(self, result: SaveChangesData) -> None:
985985
)
986986

987987
for command_data in result.session_commands:
988-
if command_data.command_type == CommandType.PUT or CommandType.DELETE:
988+
if command_data.command_type in (CommandType.PUT, CommandType.DELETE):
989989
if command_data.change_vector is not None:
990990
raise ValueError(
991991
f"Optimistic concurrency for {command_data.key} "
992992
f"is not supported when using a cluster transaction"
993993
)
994-
elif command_data.command_type == CommandType.COMPARE_EXCHANGE_DELETE or CommandType.COMPARE_EXCHANGE_PUT:
994+
elif command_data.command_type in (CommandType.COMPARE_EXCHANGE_DELETE, CommandType.COMPARE_EXCHANGE_PUT):
995995
pass
996996
else:
997997
raise ValueError(f"The command '{command_data.command_type}' is not supported in a cluster session.")

ravendb/tests/jvm_migrated_tests/cluster_tests/test_cluster_transaction.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import unittest
2+
3+
from ravendb.documents.commands.batches import CommandType, CountersBatchCommandData
4+
from ravendb.documents.operations.counters import CounterOperation, CounterOperationType
15
from ravendb.documents.session.misc import SessionOptions, TransactionMode
26
from ravendb.infrastructure.entities import User
37
from ravendb.tests.test_base import TestBase
@@ -74,3 +78,64 @@ def test_session_sequence(self):
7478
user1.age = 10
7579
session.store(user1, "users/1")
7680
session.save_changes()
81+
82+
def test_throw_on_unsupported_operations(self):
83+
session_options = SessionOptions(
84+
transaction_mode=TransactionMode.CLUSTER_WIDE,
85+
disable_atomic_document_writes_in_cluster_wide_transaction=True,
86+
)
87+
88+
with self.store.open_session(session_options=session_options) as session:
89+
from ravendb.documents.session.document_session_operations.in_memory_document_session_operations import (
90+
InMemoryDocumentSessionOperations,
91+
)
92+
93+
counter_op = CounterOperation("likes", CounterOperationType.INCREMENT, 1)
94+
counter_cmd = CountersBatchCommandData("docs/1", counter_op)
95+
96+
save_changes_data = InMemoryDocumentSessionOperations.SaveChangesData(session)
97+
save_changes_data.session_commands.append(counter_cmd)
98+
99+
with self.assertRaises(ValueError) as ctx:
100+
session.validate_cluster_transaction(save_changes_data)
101+
102+
self.assertIn("not supported", str(ctx.exception))
103+
104+
def test_compare_exchange_double_create_raises(self):
105+
session_options = SessionOptions(
106+
transaction_mode=TransactionMode.CLUSTER_WIDE,
107+
disable_atomic_document_writes_in_cluster_wide_transaction=True,
108+
)
109+
110+
with self.store.open_session(session_options=session_options) as session:
111+
session.advanced.cluster_transaction.create_compare_exchange_value("users/emails/john", "john@doe.com")
112+
113+
with self.assertRaises(RuntimeError):
114+
session.advanced.cluster_transaction.create_compare_exchange_value("users/emails/john", "other@doe.com")
115+
116+
117+
class TestClusterTransactionValidation(unittest.TestCase):
118+
def test_cluster_tx_rejects_unsupported_command_types(self):
119+
import inspect
120+
from ravendb.documents.session.document_session_operations.in_memory_document_session_operations import (
121+
InMemoryDocumentSessionOperations,
122+
)
123+
124+
src = inspect.getsource(InMemoryDocumentSessionOperations.validate_cluster_transaction)
125+
self.assertNotIn(
126+
"== CommandType.PUT or CommandType.DELETE",
127+
src,
128+
"Cluster TX validation uses 'x == A or B' (always True). Must use 'x in (A, B)'.",
129+
)
130+
131+
def test_compare_exchange_rejects_double_create(self):
132+
from ravendb.documents.operations.compare_exchange.compare_exchange import (
133+
CompareExchangeSessionValue,
134+
CompareExchangeValueState,
135+
)
136+
137+
value = CompareExchangeSessionValue.__new__(CompareExchangeSessionValue)
138+
value._key = "test"
139+
value._state = CompareExchangeValueState.CREATED
140+
with self.assertRaises(RuntimeError):
141+
value._CompareExchangeSessionValue__assert_state()

0 commit comments

Comments
 (0)