Skip to content

Commit fb84d58

Browse files
committed
RDBC-949: Refactors is_read_request to a method
Ensures `is_read_request` is consistently implemented as a method rather than a property across all commands. This change fixes potential issues where the intended behavior of checking if a command is a read request might not be correctly executed due to inconsistent implementation. Adds a test to verify the consistent implementation of `is_read_request`.
1 parent 2161369 commit fb84d58

5 files changed

Lines changed: 55 additions & 6 deletions

File tree

ravendb/documents/commands/batches.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ def __enter__(self):
130130
def __exit__(self, exc_type, exc_val, exc_tb):
131131
pass
132132

133-
@property
134-
def is_read_request(self):
133+
def is_read_request(self) -> bool:
135134
return False
136135

137136
def create_request(self, node: ServerNode) -> requests.Request:

ravendb/documents/commands/crud.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,6 @@ def prepare_request_with_multiple_ids(
324324
def set_response(self, response: str, from_cache: bool) -> None:
325325
self.result = GetDocumentsResult.from_json(json.loads(response)) if response is not None else None
326326

327-
@property
328327
def is_read_request(self) -> bool:
329328
return True
330329

ravendb/documents/commands/multi_get.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ def read_response(response_json: dict) -> GetResponse:
248248

249249
return get_response
250250

251-
@property
252251
def is_read_request(self) -> bool:
253252
return False
254253

ravendb/http/request_executor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ def choose_node_for_request(self, cmd: RavenCommand, session_info: SessionInfo)
691691
if session_info is not None and session_info.can_use_load_balance_behavior:
692692
return self._node_selector.get_node_by_session_id(session_info.session_id)
693693

694-
if not cmd.is_read_request:
694+
if not cmd.is_read_request():
695695
return self._node_selector.get_preferred_node()
696696

697697
if self.conventions.read_balance_behavior == ReadBalanceBehavior.NONE:
@@ -783,7 +783,7 @@ def _get_from_cache(
783783
if (
784784
use_cache
785785
and command.can_cache
786-
and command.is_read_request
786+
and command.is_read_request()
787787
and command.response_type == RavenCommandResponseType.OBJECT
788788
):
789789
return self._cache.get(url)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import unittest
2+
import importlib
3+
import inspect
4+
import pkgutil
5+
import ravendb
6+
7+
from ravendb.tests.test_base import TestBase
8+
9+
10+
class TestPlatformContracts(TestBase):
11+
def setUp(self):
12+
super(TestPlatformContracts, self).setUp()
13+
14+
def tearDown(self):
15+
super(TestPlatformContracts, self).tearDown()
16+
TestBase.delete_all_topology_files()
17+
18+
def test_all_commands_expose_callable_is_read_request(self):
19+
from ravendb.http.raven_command import RavenCommand
20+
21+
offenders = []
22+
for mod in self._import_all_ravendb_modules():
23+
for cls in self._iter_subclasses_in_module(mod, RavenCommand):
24+
attr = getattr(cls, "is_read_request", None)
25+
if isinstance(attr, property):
26+
offenders.append(f"{cls.__module__}.{cls.__qualname__}")
27+
28+
if offenders:
29+
self.fail("is_read_request must be a method on: " + ", ".join(offenders))
30+
31+
# private helpers
32+
def _import_all_ravendb_modules(self):
33+
for _, modname, _ in pkgutil.walk_packages(ravendb.__path__, ravendb.__name__ + "."):
34+
if modname.startswith("ravendb.tests."):
35+
continue
36+
try:
37+
yield importlib.import_module(modname)
38+
except Exception:
39+
continue
40+
41+
def _iter_subclasses_in_module(self, mod, base_cls):
42+
for _, obj in inspect.getmembers(mod):
43+
if inspect.isclass(obj) and issubclass(obj, base_cls) and obj is not base_cls:
44+
yield obj
45+
if inspect.isclass(obj):
46+
for _, inner in inspect.getmembers(obj, inspect.isclass):
47+
if issubclass(inner, base_cls) and inner is not base_cls:
48+
yield inner
49+
50+
51+
if __name__ == "__main__":
52+
unittest.main

0 commit comments

Comments
 (0)