Skip to content

Commit 13fe4e5

Browse files
committed
RDBC-780 IndexesFromClientTest::setLockModeAndSetPriority
1 parent 781e543 commit 13fe4e5

File tree

5 files changed

+194
-28
lines changed

5 files changed

+194
-28
lines changed

ravendb/documents/indexes/definitions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22
import datetime
3+
import enum
34
import re
45
from enum import Enum
56
from abc import ABC
@@ -641,3 +642,10 @@ def _strip_comments(map_str: str) -> str:
641642
@staticmethod
642643
def _unify_white_space(map_str: str) -> str:
643644
return re.sub("\\s+", " ", map_str)
645+
646+
647+
class IndexRunningStatus(enum.Enum):
648+
RUNNING = "Running"
649+
PAUSED = "Paused"
650+
DISABLED = "Disabled"
651+
PENDING = "Pending"

ravendb/documents/indexes/stats.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
from __future__ import annotations
2+
from datetime import datetime
3+
from typing import Dict, Any
4+
5+
from ravendb.documents.indexes.definitions import IndexState, IndexPriority, IndexLockMode, IndexType, IndexSourceType, \
6+
IndexRunningStatus
7+
from ravendb.tools.utils import Utils
8+
9+
10+
class IndexStats:
11+
def __init__(
12+
self,
13+
name: str = None,
14+
map_attempts: int = None,
15+
map_successes: int = None,
16+
map_errors: int = None,
17+
map_reference_attempts: int = None,
18+
map_reference_successes: int = None,
19+
map_reference_errors: int = None,
20+
reduce_attempts: int = None,
21+
reduce_successes: int = None,
22+
reduce_errors: int = None,
23+
reduce_output_collection: str = None,
24+
reduce_output_reference_pattern: str = None,
25+
pattern_references_collection_name: str = None,
26+
mapped_per_second_rate: float = None,
27+
reduced_per_second_rate: float = None,
28+
max_number_of_outputs_per_document: int = None,
29+
collections: Dict[str, CollectionStats] = None,
30+
last_querying_time: datetime = None,
31+
state: IndexState = None,
32+
priority: IndexPriority = None,
33+
created_timestamp: datetime = None,
34+
last_indexing_time: datetime = None,
35+
stale: bool = None,
36+
lock_mode: IndexLockMode = None,
37+
type: IndexType = None,
38+
status: IndexRunningStatus = None,
39+
entries_count: int = None,
40+
errors_count: int = None,
41+
source_type: IndexSourceType = None,
42+
is_test_index: bool = None,
43+
):
44+
self.name = name
45+
self.map_attempts = map_attempts
46+
self.map_successes = map_successes
47+
self.map_errors = map_errors
48+
self.map_reference_attempts = map_reference_attempts
49+
self.map_reference_successes = map_reference_successes
50+
self.map_reference_errors = map_reference_errors
51+
self.reduce_attempts = reduce_attempts
52+
self.reduce_successes = reduce_successes
53+
self.reduce_errors = reduce_errors
54+
self.reduce_output_collection = reduce_output_collection
55+
self.reduce_output_reference_pattern = reduce_output_reference_pattern
56+
self.pattern_references_collection_name = pattern_references_collection_name
57+
self.mapped_per_second_rate = mapped_per_second_rate
58+
self.reduced_per_second_rate = reduced_per_second_rate
59+
self.max_number_of_outputs_per_document = max_number_of_outputs_per_document
60+
self.collections = collections
61+
self.last_querying_time = last_querying_time
62+
self.state = state
63+
self.priority = priority
64+
self.created_timestamp = created_timestamp
65+
self.last_indexing_time = last_indexing_time
66+
self.stale = stale
67+
self.lock_mode = lock_mode
68+
self.type = type
69+
self.status = status
70+
self.entries_count = entries_count
71+
self.errors_count = errors_count
72+
self.source_type = source_type
73+
self.is_test_index = is_test_index
74+
75+
class CollectionStats:
76+
def __init__(
77+
self,
78+
last_processed_document_etag: int = None,
79+
last_processed_tombstone_etag: int = None,
80+
document_lag: int = None,
81+
tombstone_lag: int = None,
82+
):
83+
self.last_processed_document_etag = last_processed_document_etag
84+
self.last_processed_tombstone_etag = last_processed_tombstone_etag
85+
self.document_lag = document_lag
86+
self.tombstone_lag = tombstone_lag
87+
88+
@classmethod
89+
def from_json(cls, json_dict: Dict[str, Any]) -> "IndexStats.CollectionStats":
90+
return cls(
91+
json_dict["LastProcessedDocumentEtag"],
92+
json_dict["LastProcessedTombstoneEtag"],
93+
json_dict["DocumentLag"],
94+
json_dict["TombstoneLag"],
95+
)
96+
97+
@classmethod
98+
def from_json(cls, json_dict: Dict[str, Any]) -> IndexStats:
99+
return cls(
100+
json_dict["Name"],
101+
json_dict["MapAttempts"],
102+
json_dict["MapSuccesses"],
103+
json_dict["MapErrors"],
104+
json_dict["MapReferenceAttempts"],
105+
json_dict["MapReferenceSuccesses"],
106+
json_dict["MapReferenceErrors"],
107+
json_dict["ReduceAttempts"],
108+
json_dict["ReduceSuccesses"],
109+
json_dict["ReduceErrors"],
110+
json_dict["ReduceOutputCollection"],
111+
json_dict["ReduceOutputReferencePattern"],
112+
json_dict["PatternReferencesCollectionName"],
113+
json_dict["MappedPerSecondRate"],
114+
json_dict["ReducedPerSecondRate"],
115+
json_dict["MaxNumberOfOutputsPerDocument"],
116+
{key: cls.CollectionStats.from_json(value) for key, value in json_dict["Collections"].items()},
117+
Utils.string_to_datetime(json_dict["LastQueryingTime"]),
118+
IndexState(json_dict["State"]),
119+
IndexPriority(json_dict["Priority"]),
120+
Utils.string_to_datetime(json_dict["CreatedTimestamp"]),
121+
Utils.string_to_datetime(json_dict["LastIndexingTime"]),
122+
json_dict["IsStale"],
123+
IndexLockMode(json_dict["LockMode"]),
124+
IndexType(json_dict["Type"]),
125+
IndexRunningStatus(json_dict["Status"]),
126+
json_dict["EntriesCount"],
127+
json_dict["ErrorsCount"],
128+
IndexSourceType(json_dict["SourceType"]),
129+
json_dict.get("IsTestIndex", None),
130+
)

ravendb/documents/operations/indexes.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
from __future__ import annotations
2-
import enum
32
import json
43
from typing import List, TYPE_CHECKING, Optional, Tuple
54

65
import requests
76

87
from ravendb.exceptions import exceptions
98
from ravendb.exceptions.exceptions import ErrorResponseException
10-
from ravendb.documents.indexes.definitions import IndexDefinition, IndexErrors, IndexLockMode, IndexPriority
9+
from ravendb.documents.indexes.definitions import IndexDefinition, IndexErrors, IndexLockMode, IndexPriority, \
10+
IndexRunningStatus
1111
from ravendb.documents.operations.definitions import MaintenanceOperation, VoidMaintenanceOperation
1212
from ravendb.http.raven_command import RavenCommand, VoidRavenCommand
1313
from ravendb.http.server_node import ServerNode
1414
from ravendb.http.topology import RaftCommand
1515
from ravendb.tools.utils import Utils
1616
from ravendb.util.util import RaftIdGenerator
17+
from ravendb.documents.indexes.stats import IndexStats
1718

1819
if TYPE_CHECKING:
1920
from ravendb.documents.conventions import DocumentConventions
@@ -270,13 +271,6 @@ def create_request(self, server_node) -> requests.Request:
270271
)
271272

272273

273-
class IndexRunningStatus(enum.Enum):
274-
RUNNING = "Running"
275-
PAUSED = "Paused"
276-
DISABLED = "Disabled"
277-
PENDING = "Pending"
278-
279-
280274
class IndexStatus:
281275
def __init__(self, name: str = None, status: IndexRunningStatus = None):
282276
self.name = name
@@ -290,7 +284,7 @@ def from_json(cls, json_dict: dict) -> IndexStatus:
290284
class IndexingStatus:
291285
def __init__(
292286
self, status: IndexRunningStatus = None, indexes: List[IndexStatus] = None
293-
): # todo: Optional typehints
287+
):
294288
self.status = status
295289
self.indexes = indexes
296290

@@ -325,43 +319,44 @@ def set_response(self, response: str, from_cache: bool) -> None:
325319
self.result = IndexingStatus.from_json(response)
326320

327321

328-
class GetIndexStatisticsOperation(MaintenanceOperation[dict]): # replace returned type with IndexStats -> its enormous
322+
class GetIndexStatisticsOperation(MaintenanceOperation["IndexStats"]):
329323
def __init__(self, name):
330324
if name is None:
331325
raise ValueError("Index name cannot be None")
332326
super().__init__()
333327
self.__index_name = name
334328

335-
def get_command(self, conventions) -> RavenCommand[dict]:
336-
return self.__GetIndexStatisticsCommand(self.__index_name)
329+
def get_command(self, conventions) -> RavenCommand["IndexStats"]:
330+
return self._GetIndexStatisticsCommand(self.__index_name)
337331

338-
class __GetIndexStatisticsCommand(RavenCommand[dict]):
332+
class _GetIndexStatisticsCommand(RavenCommand["IndexStats"]):
339333
def __init__(self, index_name: str):
340334
if not index_name:
341335
raise ValueError("Index name can't be None or empty")
342336
super().__init__(dict)
343337
self.__index_name = index_name
344338

345339
def create_request(self, server_node) -> requests.Request:
340+
url = f"{server_node.url}/databases/{server_node.database}/indexes/stats?name={Utils.quote_key(self.__index_name)}"
346341
return requests.Request(
347342
"GET",
348-
f"{server_node.url}/databases/{server_node.database}"
349-
f"/indexes/stats?name={Utils.escape(self.__index_name, False, False)}",
343+
url,
350344
)
351345

352346
def is_read_request(self) -> bool:
353347
return True
354348

355349
def set_response(self, response: str, from_cache: bool) -> None:
356350
if response is None:
357-
raise ValueError("Invalid response")
351+
self._throw_invalid_response()
358352

359353
response = json.loads(response)
360-
if "Error" in response:
361-
raise exceptions.ErrorResponseException(response["Error"])
362-
if "Results" not in response or len(response["Results"]) > 1:
363-
raise ValueError("Invalid response")
364-
self.result = response["Results"]
354+
results = response["Results"]
355+
356+
if len(results) != 1:
357+
self._throw_invalid_response()
358+
359+
self.result = IndexStats.from_json(results[0])
365360

366361

367362
class GetIndexesStatisticsOperation(

ravendb/tests/jvm_migrated_tests/client_tests/indexing_tests/test_indexes_from_client.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import time
22
from typing import Optional
33

4-
from ravendb import QueryStatistics, IndexQuery
4+
from ravendb.documents.session.query import QueryStatistics
5+
from ravendb.documents.queries.index_query import IndexQuery
56
from ravendb.documents.commands.explain import ExplainQueryCommand
67
from ravendb.documents.operations.statistics import GetStatisticsOperation
78
from ravendb.documents.indexes.index_creation import IndexCreation
@@ -11,12 +12,14 @@
1112
DeleteIndexOperation,
1213
ResetIndexOperation,
1314
GetIndexingStatusOperation,
14-
IndexRunningStatus,
1515
StopIndexingOperation,
1616
StartIndexingOperation,
1717
StopIndexOperation,
18+
GetIndexesOperation,
19+
GetIndexStatisticsOperation, SetIndexesLockOperation, SetIndexesPriorityOperation,
1820
)
19-
from ravendb.documents.indexes.definitions import FieldIndexing, FieldStorage
21+
from ravendb.documents.indexes.definitions import FieldIndexing, FieldStorage, IndexLockMode, IndexRunningStatus, \
22+
IndexPriority
2023
from ravendb.documents.indexes.abstract_index_creation_tasks import AbstractIndexCreationTask
2124
from ravendb.infrastructure.entities import User, Post
2225
from ravendb.tests.test_base import TestBase
@@ -243,3 +246,34 @@ def _stats_callback(qs: QueryStatistics) -> None:
243246
self.assertEqual(1, len(explanations))
244247
self.assertIsNotNone(explanations[0].index)
245248
self.assertIsNotNone(explanations[0].reason)
249+
250+
def test_set_lock_mode_and_set_priority(self):
251+
Users_ByName().execute(self.store)
252+
253+
with self.store.open_session() as session:
254+
session.store(User(name="Fitzchak"))
255+
session.store(User(name="Arek"))
256+
session.save_changes()
257+
258+
with self.store.open_session() as session:
259+
users = list(
260+
session.query_index_type(Users_ByName, User).wait_for_non_stale_results().where_equals("name", "Arek")
261+
)
262+
self.assertEqual(1, len(users))
263+
264+
indexes = self.store.maintenance.send(GetIndexesOperation(0, 128))
265+
self.assertEqual(1, len(indexes))
266+
267+
index = indexes[0]
268+
stats = self.store.maintenance.send(GetIndexStatisticsOperation(index.name))
269+
270+
self.assertEqual(stats.lock_mode, IndexLockMode.UNLOCK)
271+
self.assertEqual(stats.priority, IndexPriority.NORMAL)
272+
273+
self.store.maintenance.send(SetIndexesLockOperation(IndexLockMode.LOCKED_IGNORE, index.name))
274+
self.store.maintenance.send(SetIndexesPriorityOperation(IndexPriority.LOW,index.name ))
275+
276+
stats = self.store.maintenance.send(GetIndexStatisticsOperation(index.name))
277+
278+
self.assertEqual(IndexLockMode.LOCKED_IGNORE, stats.lock_mode)
279+
self.assertEqual(IndexPriority.LOW, stats.priority)

ravendb/tests/jvm_migrated_tests/index_tests/test_index_operation.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ravendb.documents.indexes.definitions import IndexDefinition, IndexLockMode, IndexPriority
1+
from ravendb.documents.indexes.definitions import IndexDefinition, IndexLockMode, IndexPriority, IndexRunningStatus
22
from ravendb.documents.operations.indexes import (
33
PutIndexesOperation,
44
GetIndexNamesOperation,
@@ -8,7 +8,6 @@
88
IndexingStatus,
99
EnableIndexOperation,
1010
IndexStatus,
11-
IndexRunningStatus,
1211
GetIndexStatisticsOperation,
1312
StopIndexOperation,
1413
StartIndexOperation,
@@ -86,7 +85,7 @@ def test_can_get_index_statistics(self):
8685
session.save_changes()
8786
self.wait_for_indexing(self.store, self.store.database)
8887
stats = self.store.maintenance.send(GetIndexStatisticsOperation(index.name))
89-
self.assertEqual(1, len(stats))
88+
self.assertEqual(1, stats.entries_count)
9089

9190
def test_can_list_errors(self):
9291
index = UsersInvalidIndex()

0 commit comments

Comments
 (0)