Skip to content

Commit d469b76

Browse files
authored
Merge pull request #222 from poissoncorp/RDBC-844
RDBC-844 Implement database settings operations
2 parents 0c5a856 + 7349311 commit d469b76

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

ravendb/serverwide/operations/common.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ class DatabaseSettings:
371371
def __init__(self, settings: Dict[str, str] = None):
372372
self.settings = settings
373373

374+
@classmethod
375+
def from_json(cls, json_dict: Dict) -> DatabaseSettings:
376+
return cls(json_dict["Settings"])
377+
374378

375379
class ReorderDatabaseMembersOperation(VoidServerOperation):
376380
class Parameters:

ravendb/serverwide/operations/configuration.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
from __future__ import annotations
22

33
import json
4-
from typing import Optional, List, TYPE_CHECKING
4+
from typing import Optional, List, TYPE_CHECKING, Dict
55

66
import requests
77

88
from ravendb import ServerNode
9+
from ravendb.documents.operations.definitions import MaintenanceOperation, VoidMaintenanceOperation
910
from ravendb.documents.operations.ongoing_tasks import OngoingTaskType
1011
from ravendb.http.raven_command import RavenCommand, VoidRavenCommand
1112
from ravendb.http.topology import RaftCommand
1213
from ravendb.documents.operations.backups.settings import PeriodicBackupConfiguration
13-
from ravendb.serverwide.operations.common import ServerOperation, T, VoidServerOperation
14+
from ravendb.serverwide.operations.common import ServerOperation, T, VoidServerOperation, DatabaseSettings
1415
from ravendb.serverwide.operations.ongoing_tasks import IServerWideTask, ServerWideTaskResponse
1516
from ravendb.tools.utils import Utils
1617
from ravendb.util.util import RaftIdGenerator
@@ -163,3 +164,72 @@ def get_raft_unique_request_id(self) -> str:
163164
def create_request(self, node: ServerNode) -> requests.Request:
164165
url = f"{node.url}/admin/configuration/server-wide/task?type={self._type.value}&name={Utils.quote_key(self._name)}"
165166
return requests.Request(method="DELETE", url=url)
167+
168+
169+
class GetDatabaseSettingsOperation(MaintenanceOperation[DatabaseSettings]):
170+
def __init__(self, database_name: str = None):
171+
if database_name is None:
172+
raise ValueError("Database name cannot be None")
173+
self._database_name = database_name
174+
175+
def get_command(self, conventions: "DocumentConventions") -> "RavenCommand[DatabaseSettings]":
176+
return self.GetDatabaseSettingsCommand(self._database_name)
177+
178+
class GetDatabaseSettingsCommand(RavenCommand[DatabaseSettings]):
179+
def __init__(self, database_name: str = None):
180+
super().__init__(DatabaseSettings)
181+
182+
if database_name is None:
183+
raise ValueError("Database name cannot be None")
184+
185+
self._database_name = database_name
186+
187+
def is_read_request(self) -> bool:
188+
return False
189+
190+
def create_request(self, node: ServerNode) -> requests.Request:
191+
url = f"{node.url}/databases/{self._database_name}/admin/record"
192+
return requests.Request(method="GET", url=url)
193+
194+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
195+
if response is None:
196+
self.result = None
197+
return
198+
199+
self.result = DatabaseSettings.from_json(json.loads(response))
200+
201+
202+
class PutDatabaseSettingsOperation(VoidMaintenanceOperation):
203+
def __init__(self, database_name: str, configuration_settings: Dict[str, str]):
204+
if database_name is None:
205+
raise ValueError("Database name cannot be None")
206+
self._database_name = database_name
207+
208+
if configuration_settings is None:
209+
raise ValueError("Configuration settings cannot be None")
210+
self._configuration_settings = configuration_settings
211+
212+
def get_command(self, conventions: "DocumentConventions") -> "VoidRavenCommand":
213+
return self.PutDatabaseSettingsCommand(self._configuration_settings, self._database_name)
214+
215+
class PutDatabaseSettingsCommand(VoidRavenCommand, RaftCommand):
216+
def __init__(self, configuration_settings: Dict[str, str], database_name: str):
217+
super().__init__()
218+
if database_name is None:
219+
raise ValueError("Database name cannot be None.")
220+
self._database_name = database_name
221+
222+
if configuration_settings is None:
223+
raise ValueError("Configuration settings cannot be None.")
224+
self._configuration_settings = configuration_settings
225+
226+
def is_read_request(self) -> bool:
227+
return False
228+
229+
def get_raft_unique_request_id(self) -> str:
230+
return RaftIdGenerator.new_id()
231+
232+
def create_request(self, node: ServerNode) -> requests.Request:
233+
url = f"{node.url}/databases/{self._database_name}/admin/configuration/settings"
234+
235+
return requests.Request(method="PUT", url=url, data=self._configuration_settings)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from typing import Dict
2+
3+
from ravendb.serverwide.operations.common import DatabaseSettings
4+
5+
from ravendb import DocumentStore
6+
from ravendb.documents.operations.server_misc import ToggleDatabasesStateOperation
7+
from ravendb.serverwide.operations.configuration import GetDatabaseSettingsOperation, PutDatabaseSettingsOperation
8+
from ravendb.tests.test_base import TestBase
9+
10+
11+
class TestDatabaseSettingsOperation(TestBase):
12+
def test_check_if_configuration_settings_is_empty(self):
13+
self.check_if_values_got_saved(self.store, {})
14+
15+
def test_change_single_setting_key_on_server(self):
16+
name = "Storage.PrefetchResetThresholdInGb"
17+
value = "10"
18+
19+
settings = {name: value}
20+
self.put_configuration_settings(self.store, settings)
21+
self.check_if_values_got_saved(self.store, settings)
22+
23+
def test_change_multiple_settings_keys_on_server(self):
24+
settings = {
25+
"Storage.PrefetchResetThresholdInGb": "10",
26+
"Storage.TimeToSyncAfterFlushInSec": "35",
27+
"Tombstones.CleanupIntervalInMin": "10",
28+
}
29+
30+
self.put_configuration_settings(self.store, settings)
31+
self.check_if_values_got_saved(self.store, settings)
32+
33+
@staticmethod
34+
def put_configuration_settings(store: DocumentStore, settings: Dict[str, str]) -> None:
35+
store.maintenance.send(PutDatabaseSettingsOperation(store.database, settings))
36+
store.maintenance.server.send(ToggleDatabasesStateOperation(store.database, True))
37+
store.maintenance.server.send(ToggleDatabasesStateOperation(store.database, False))
38+
39+
def check_if_values_got_saved(self, store: DocumentStore, data: Dict[str, str]):
40+
settings = self.get_configuration_settings(store)
41+
for key, value in data.items():
42+
configuration_value = settings.settings.get(key)
43+
self.assertIsNotNone(configuration_value)
44+
self.assertEqual(configuration_value, value)
45+
46+
def get_configuration_settings(self, store: DocumentStore) -> DatabaseSettings:
47+
settings = store.maintenance.send(GetDatabaseSettingsOperation(store.database))
48+
self.assertIsNotNone(settings)
49+
return settings

0 commit comments

Comments
 (0)