Skip to content

Commit f532840

Browse files
committed
RDBC-700 MultiGetCommand, IndexDefinitionBase, Conventions, Headers
1 parent d15e278 commit f532840

File tree

8 files changed

+106
-78
lines changed

8 files changed

+106
-78
lines changed

ravendb/documents/commands/batches.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,15 @@ def serialize(self, conventions: DocumentConventions) -> dict:
270270

271271

272272
class DeleteCommandData(CommandData):
273-
def __init__(self, key: str, change_vector: str):
274-
super(DeleteCommandData, self).__init__(key=key, command_type=CommandType.DELETE)
273+
def __init__(self, key: str, change_vector: str, original_change_vector: str = None):
274+
super(DeleteCommandData, self).__init__(key=key, command_type=CommandType.DELETE, change_vector=change_vector)
275+
self.original_change_vector = original_change_vector
275276

276277
def serialize(self, conventions: DocumentConventions) -> dict:
277-
return {"Id": self.key, "ChangeVector": self.change_vector, "Type": CommandType.DELETE}
278+
data = {"Id": self.key, "ChangeVector": self.change_vector, "Type": CommandType.DELETE}
279+
if self.original_change_vector is not None:
280+
data.update({"OriginalChangeVector": self.original_change_vector})
281+
return data
278282

279283

280284
class PutCommandDataBase(CommandData):

ravendb/documents/commands/crud.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def create_request(self, node: ServerNode) -> requests.Request:
9090
url = f"{node.url}/databases/{node.database}/docs?id={Utils.escape(self.__key, True, False)}"
9191
request = requests.Request("HEAD", url)
9292
if self.__change_vector is not None:
93-
request.headers["If-None-Match"] = self.__change_vector
93+
request.headers[constants.Headers.IF_NONE_MATCH] = self.__change_vector
9494
return request
9595

9696
def process_response(self, cache: HttpCache, response: requests.Response, url) -> ResponseDisposeHandling:
@@ -387,7 +387,7 @@ def create_request(self, node: ServerNode) -> requests.Request:
387387
f"{node.url}/databases/{node.database}"
388388
f"/attachments?id={Utils.quote_key(self.__document_id)}"
389389
f"&name={Utils.quote_key(self.__name)}",
390-
{"If-None-Match": self.__change_vector} if self.__change_vector else None,
390+
{constants.Headers.IF_NONE_MATCH: self.__change_vector} if self.__change_vector else None,
391391
)
392392

393393
def process_response(self, cache: HttpCache, response: requests.Response, url) -> http.ResponseDisposeHandling:
@@ -435,7 +435,7 @@ def __init__(self, key: str, change_vector: str):
435435
def create_request(self, node: ServerNode) -> requests.Request:
436436
url = f"{node.url}/databases/{node.database}/docs?id={Utils.quote_key(self.__key)}"
437437
request = requests.Request("GET", url)
438-
request.headers["If-None-Match"] = f'"{self.__change_vector}"'
438+
request.headers[constants.Headers.IF_NONE_MATCH] = f'"{self.__change_vector}"'
439439

440440
return request
441441

ravendb/documents/commands/multi_get.py

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -115,36 +115,6 @@ def __init__(self, request_executor: RequestExecutor, commands: List[GetRequest]
115115
def create_request(self, node: ServerNode) -> Optional[requests.Request]:
116116
self.__base_url = f"{node.url}/databases/{node.database}"
117117
url = self.__base_url + "/multi_get"
118-
# todo: aggressive caching
119-
# if self.__maybe_read_all_from_cache(self.__request_executor.aggressive_caching):
120-
# self.aggressively_cached = True
121-
# return None
122-
#
123-
# aggressive_cache_options: AggressiveCacheOptions = self.__request_executor.aggressive_caching
124-
# if aggressive_cache_options and aggressive_cache_options.mode == AggressiveCacheMode.TRACK_CHANGES:
125-
# self.result = []
126-
# for command in self.__commands:
127-
# if not command.can_cache_aggressively:
128-
# break
129-
# cache_key = self.__get_cache_key(command)[0]
130-
# cached_item, _, cached_ref = self.__http_cache.get(cache_key, "", "")
131-
# cached_item: ReleaseCacheItem
132-
# if (
133-
# cached_ref is None
134-
# or cached_item.age > aggressive_cache_options.duration
135-
# or cached_item.might_have_been_modified
136-
# ):
137-
# break
138-
# get_response = GetResponse()
139-
# get_response.result = cached_ref
140-
# get_response.status_code = http.HTTPStatus.NOT_MODIFIED
141-
# self.result.append(get_response)
142-
#
143-
# if len(self.result) == len(self.__commands):
144-
# return None
145-
#
146-
# self.result = None
147-
148118
request = requests.Request("POST", url)
149119

150120
request.data = {
@@ -211,7 +181,6 @@ def __get_cache_key(self, command: GetRequest) -> (str, str):
211181
req_url = self.__base_url + command.url_and_query
212182
return command.method + "-" + req_url if command.method else req_url, req_url
213183

214-
# todo: make sure json parses correctly down there
215184
def set_response_raw(self, response: requests.Response, stream: bytes) -> None:
216185
try:
217186
try:
@@ -224,7 +193,7 @@ def set_response_raw(self, response: requests.Response, stream: bytes) -> None:
224193

225194
for get_response in self.read_responses(response_temp):
226195
command = self.__commands[i]
227-
self.__maybe_set_cache(get_response, command)
196+
self.__maybe_set_cache(get_response, command, i)
228197

229198
if self.__cached is not None and get_response.status_code == http.HTTPStatus.NOT_MODIFIED:
230199
cloned_response = GetResponse()
@@ -241,8 +210,11 @@ def set_response_raw(self, response: requests.Response, stream: bytes) -> None:
241210
except Exception as e:
242211
self._throw_invalid_response(e)
243212

244-
def __maybe_set_cache(self, get_response: GetResponse, command: GetRequest):
213+
def __maybe_set_cache(self, get_response: GetResponse, command: GetRequest, cached_index: int):
245214
if get_response.status_code == http.HTTPStatus.NOT_MODIFIED:
215+
# if not modified - update age
216+
if self.__cached is not None:
217+
self.__cached.values[cached_index][0].not_modified()
246218
return
247219

248220
cache_key = self.__get_cache_key(command)[0]
@@ -281,7 +253,19 @@ def is_read_request(self) -> bool:
281253
return False
282254

283255
def close_cache(self):
256+
# If _cached is not null - it means that the client approached with this multitask request to node
257+
# and the request failed and now client tries to send it to another node.
258+
284259
if self.__cached is not None:
285260
self.__cached.close()
286261

287262
self.__cached = None
263+
# The client sends the commands.
264+
# Some of which could be saved in cache with a response
265+
# that includes the change vector that received from the old fallen node.
266+
# The client can't use those responses because their URLs are different
267+
# (include the IP and port of the old node), because of that the client
268+
# needs to get those docs again from the new node.
269+
270+
for command in self.__commands:
271+
command.headers.remove(constants.Headers.IF_NONE_MATCH)

ravendb/documents/conventions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def __init__(self):
4040
self.throw_if_query_page_size_is_not_set = False
4141
self._send_application_identifier = True
4242
self._save_enums_as_integers: Optional[bool] = None
43+
self._disable_atomic_document_writes_in_cluster_wide_transaction: Optional[bool] = None
4344

4445
# Configuration
4546
self.json_default_method = DocumentConventions.json_default
@@ -198,6 +199,15 @@ def read_balance_behavior(self, value: ReadBalanceBehavior):
198199
def send_application_identifier(self) -> bool:
199200
return self._send_application_identifier
200201

202+
@property
203+
def disable_atomic_document_writes_in_cluster_wide_transaction(self) -> bool:
204+
return self._disable_atomic_document_writes_in_cluster_wide_transaction
205+
206+
@disable_atomic_document_writes_in_cluster_wide_transaction.setter
207+
def disable_atomic_document_writes_in_cluster_wide_transaction(self, value: bool):
208+
self.__assert_not_frozen()
209+
self._disable_atomic_document_writes_in_cluster_wide_transaction = value
210+
201211
@staticmethod
202212
def json_default(o):
203213
if o is None:

ravendb/documents/indexes/definitions.py

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -163,26 +163,49 @@ def to_json(self):
163163
}
164164

165165

166-
class IndexDefinition:
167-
def __init__(self, **kwargs):
168-
self.name: Union[None, str] = None
169-
self.priority: Union[None, IndexPriority] = None
170-
self.state: Union[None, IndexState] = None
171-
self.lock_mode: Union[None, IndexLockMode] = None
172-
self.additional_sources: Dict[str, str] = {}
173-
self.additional_assemblies: Set[AdditionalAssembly] = set()
174-
self.__maps: Union[None, Set[str]] = None
175-
self.fields: Union[None, Dict[str, IndexFieldOptions]] = {}
176-
self.reduce: Union[None, str] = None
177-
self.configuration: Dict[str, str] = {}
178-
self.__index_source_type: Union[None, IndexSourceType] = None
179-
self.__index_type: Union[None, IndexType] = None
180-
self.output_reduce_to_collection: Union[None, str] = None
181-
self.reduce_output_index: Union[None, int] = None
182-
self.pattern_for_output_reduce_to_collection_references: Union[None, str] = None
183-
self.pattern_references_collection_name: Union[None, str] = None
184-
self.deployment_mode: Union[None, IndexDeploymentMode] = None
185-
self.__dict__.update(kwargs)
166+
class IndexDefinitionBase:
167+
def __init__(self, name: str = None, priority: IndexPriority = None, state: IndexState = None):
168+
self.name = name
169+
self.priority = priority
170+
self.state = state
171+
172+
173+
class IndexDefinition(IndexDefinitionBase):
174+
def __init__(
175+
self,
176+
name: Optional[str] = None,
177+
priority: Optional[str] = None,
178+
state: Optional[str] = None,
179+
lock_mode: Optional[IndexLockMode] = None,
180+
additional_sources: Optional[Dict[str, str]] = None,
181+
additional_assemblies: Optional[Set[AdditionalAssembly]] = None,
182+
maps: Optional[Set[str]] = None,
183+
fields: Optional[Dict[str, IndexFieldOptions]] = None,
184+
reduce: Optional[str] = None,
185+
configuration: Optional[Dict[str, str]] = None,
186+
index_source_type: Optional[IndexSourceType] = None,
187+
index_type: Optional[IndexType] = None,
188+
output_reduce_to_collection: Optional[str] = None,
189+
reduce_output_index: Optional[int] = None,
190+
pattern_for_output_reduce_to_collection_references: Optional[str] = None,
191+
pattern_references_collection_name: Optional[str] = None,
192+
deployment_mode: Optional[IndexDeploymentMode] = None,
193+
):
194+
super(IndexDefinition, self).__init__(name, priority, state)
195+
self.lock_mode = lock_mode
196+
self.additional_sources = additional_sources
197+
self.additional_assemblies = additional_assemblies
198+
self.__maps = maps or set()
199+
self.fields = fields or {}
200+
self.reduce = reduce
201+
self.configuration = configuration or {}
202+
self.__index_source_type = index_source_type
203+
self.__index_type = index_type
204+
self.output_reduce_to_collection = output_reduce_to_collection
205+
self.reduce_output_index = reduce_output_index
206+
self.pattern_for_output_reduce_to_collection_references = pattern_for_output_reduce_to_collection_references
207+
self.pattern_references_collection_name = pattern_references_collection_name
208+
self.deployment_mode = deployment_mode
186209

187210
@classmethod
188211
def from_json(cls, json_dict: dict) -> IndexDefinition:
@@ -297,21 +320,19 @@ def detect_static_index_type(self) -> IndexType:
297320
return None # todo: IndexDefinitionHelper.detect_Static_index_type(first_map, self.reduce)
298321

299322

300-
class AutoIndexDefinition:
323+
class AutoIndexDefinition(IndexDefinitionBase):
301324
def __init__(
302325
self,
303-
type: Optional[IndexType] = None,
326+
index_type: Optional[IndexType] = None,
304327
name: Optional[str] = None,
305328
priority: Optional[IndexPriority] = None,
306329
state: Optional[IndexState] = None,
307330
collection: Optional[str] = None,
308331
map_fields: Optional[Dict[str, AutoIndexFieldOptions]] = None,
309332
group_by_fields: Optional[Dict[str, AutoIndexFieldOptions]] = None,
310333
):
311-
self.type = type
312-
self.name = name
313-
self.priority = priority
314-
self.state = state
334+
super(AutoIndexDefinition, self).__init__(name, priority, state)
335+
self.index_type = index_type
315336
self.collection = collection
316337
self.map_fields = map_fields
317338
self.group_by_fields = group_by_fields
@@ -330,7 +351,7 @@ def from_json(cls, json_dict: Dict) -> AutoIndexDefinition:
330351

331352
def to_json(self) -> Dict:
332353
return {
333-
"Type": self.type.value,
354+
"Type": self.index_type.value,
334355
"Name": self.name,
335356
"Priority": self.priority.value,
336357
"State": self.state.value if self.state is not None else None,
@@ -451,9 +472,9 @@ def from_NuGet(
451472

452473
class AbstractCommonApiForIndexes(ABC):
453474
def __init__(self):
454-
self.__additional_sources: Union[None, Dict[str, str]] = None
455-
self.__additional_assemblies: Union[None, Set[AdditionalAssembly]] = None
456-
self.__configuration: Union[None, Dict[str, str]] = None
475+
self.__additional_sources: Optional[Dict[str, str]] = None
476+
self.__additional_assemblies: Optional[Set[AdditionalAssembly]] = None
477+
self.__configuration: Optional[Dict[str, str]] = None
457478

458479
@property
459480
def is_map_reduce(self) -> bool:

ravendb/documents/session/in_memory_document_session_operations.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ def delete(self, key_or_entity: Union[str, object], expected_change_vector: Opti
784784
if key is None:
785785
raise ValueError("Id cannot be None")
786786
change_vector = None
787-
document_info = self._documents_by_id.get(key)
787+
document_info = self._documents_by_id.get_value(key)
788788
if document_info is not None:
789789
new_obj = self.entity_to_json.convert_entity_to_json(document_info.entity, document_info)
790790
if document_info.entity is not None and self._entity_changed(new_obj, document_info, None):
@@ -801,7 +801,13 @@ def delete(self, key_or_entity: Union[str, object], expected_change_vector: Opti
801801
change_vector = change_vector if self.__use_optimistic_concurrency else None
802802
if self._counters_by_doc_id:
803803
self._counters_by_doc_id.pop(key, None)
804-
self.defer(DeleteCommandData(key, expected_change_vector if expected_change_vector else change_vector))
804+
self.defer(
805+
DeleteCommandData(
806+
key,
807+
expected_change_vector or change_vector,
808+
expected_change_vector or (document_info.change_vector if document_info is not None else None),
809+
)
810+
)
805811
return
806812

807813
entity = key_or_entity
@@ -1030,7 +1036,9 @@ def __prepare_for_entities_deletion(
10301036

10311037
change_vector = change_vector if self.__use_optimistic_concurrency else None
10321038
self.before_delete_invoke(BeforeDeleteEventArgs(self, document_info.key, document_info.entity))
1033-
result.session_commands.append(DeleteCommandData(document_info.key, document_info.change_vector))
1039+
result.session_commands.append(
1040+
DeleteCommandData(document_info.key, change_vector, document_info.change_vector)
1041+
)
10341042

10351043
if changes is None:
10361044
result.on_success.clear_deleted_entities()

ravendb/documents/store/definition.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,13 @@ def close(self):
403403
def open_session(
404404
self, database: Optional[str] = None, session_options: Optional[SessionOptions] = None
405405
) -> DocumentSession:
406-
if not database and not session_options:
406+
if not session_options:
407407
session_options = SessionOptions()
408-
if not ((session_options is not None) ^ (database is not None)):
409-
raise ValueError("Pass either database str or session_options object")
410-
if database:
411-
session_options = SessionOptions(database=database)
408+
session_options.database = database
409+
session_options.disable_atomic_document_writes_in_cluster_wide_transaction = (
410+
self.conventions.disable_atomic_document_writes_in_cluster_wide_transaction
411+
)
412+
412413
self.assert_initialized()
413414
self._ensure_not_closed()
414415

ravendb/tests/jvm_migrated_tests/server_tests/test_databases.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_can_get_info_auto_index_info(self):
3131
auto_index_definition = record.auto_indexes.get("Auto/Genres/Byname")
3232
self.assertIsNotNone(auto_index_definition)
3333

34-
self.assertEqual(IndexType.AUTO_MAP, auto_index_definition.type)
34+
self.assertEqual(IndexType.AUTO_MAP, auto_index_definition.index_type)
3535
self.assertEqual("Auto/Genres/Byname", auto_index_definition.name)
3636
self.assertEqual(IndexPriority.NORMAL, auto_index_definition.priority)
3737
self.assertEqual("Genres", auto_index_definition.collection)

0 commit comments

Comments
 (0)