edu-rdm-integration 3.7.0__py3-none-any.whl → 3.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ NOT_SPECIFIED_QUEUE_TO_MODEL_ERROR = 'Для переданной модели {} не указана очередь для сохранения!'
2
+
3
+ CACHED_OBJECTS_TYPE_MISMATCH_ERROR = 'Тип сравниваемого объекта не соответствует типу объекта в кеше'
@@ -1,3 +1,10 @@
1
+ from abc import (
2
+ ABCMeta,
3
+ abstractmethod,
4
+ )
5
+ from copy import (
6
+ deepcopy,
7
+ )
1
8
  from typing import (
2
9
  TYPE_CHECKING,
3
10
  Any,
@@ -25,10 +32,17 @@ from educommon.integration_entities.consts import (
25
32
  from educommon.integration_entities.enums import (
26
33
  EntityLogOperation,
27
34
  )
35
+ from educommon.integration_entities.helpers import (
36
+ EntitySaver,
37
+ )
28
38
 
29
39
  from edu_rdm_integration.collect_data.base.caches import (
30
40
  LogChange,
31
41
  )
42
+ from edu_rdm_integration.collect_data.base.consts import (
43
+ CACHED_OBJECTS_TYPE_MISMATCH_ERROR,
44
+ NOT_SPECIFIED_QUEUE_TO_MODEL_ERROR,
45
+ )
32
46
  from edu_rdm_integration.helpers import (
33
47
  Graph,
34
48
  )
@@ -41,8 +55,15 @@ from edu_rdm_integration.utils import (
41
55
 
42
56
 
43
57
  if TYPE_CHECKING:
58
+ from edu_rdm_integration.adapters.caches import (
59
+ WebEduEntityCache,
60
+ )
44
61
  from edu_rdm_integration.collect_data.base.caches import (
45
62
  IgnoreLogDependency,
63
+ LogChange,
64
+ )
65
+ from edu_rdm_integration.models import (
66
+ BaseEntityModel,
46
67
  )
47
68
 
48
69
 
@@ -216,3 +237,189 @@ class BaseIgnoreLogMixin:
216
237
  id__in=self.logs[log_model._meta.label],
217
238
  ).values_list('pk', flat=True)
218
239
  self._exclude_logs(log_model._meta.label, ignore_model_ids)
240
+
241
+
242
+ class FilteredSaveEntitiesFunctionMixin(metaclass=ABCMeta):
243
+ """
244
+ Миксин, реализующий фильтрацию объектов перед сохранением.
245
+
246
+ Предназначен для использования в классах, которые занимаются сохранением сущностей, но при этом хотят исключить
247
+ неизменённые объекты из операции записи, чтобы избежать лишних действий или запросов к базе данных.
248
+ Для работы требует реализации абстрактного свойства `_model_to_cache_map` и `_model_to_save_queue_map`, которое
249
+ определяет, какие сущности и с каким кешем нужно обработать.
250
+
251
+ Attributes:
252
+ _filtered_operations (tuple[EntityLogOperation]): : Операции, подлежащие фильтрации (по умолчанию только UPDATE).
253
+ _saved_entities_to_cache_map (dict[type[BaseEntityModel], WebEduEntityCache]): Копия маппинга моделей на кэши,
254
+ используемая для сравнения изменений.
255
+ _ignored_fields (dict[EntityLogOperation, tuple[str]]): Словарь полей, которые следует игнорировать при
256
+ сравнении для каждой операции.
257
+ """
258
+
259
+ _filtered_operations: tuple[EntityLogOperation, ...] = (EntityLogOperation.UPDATE,)
260
+ _saved_entities_to_cache_map: dict[type['BaseEntityModel'], 'WebEduEntityCache'] = {}
261
+ _ignored_fields = {
262
+ EntityLogOperation.UPDATE: ('modified', 'operation', 'collecting_sub_stage', 'exporting_sub_stage'),
263
+ }
264
+
265
+ def _is_object_to_save(
266
+ self,
267
+ saved_object: 'BaseEntityModel',
268
+ ignore_fields: Optional[Iterable[str]] = None
269
+ ) -> bool:
270
+ """
271
+ Проверяет, должен ли объект быть добавлен в очередь на сохранение.
272
+
273
+ Args:
274
+ saved_object ('BaseEntityModel'): Объект, который предполагается сохранить.
275
+ ignore_fields (Optional[Iterable[str]]): Дополнительные поля, которые нужно игнорировать.
276
+
277
+ Returns:
278
+ bool: True, если объект был изменён и его нужно сохранить, иначе False.
279
+ """
280
+ save_object_type = type(saved_object)
281
+ cache = self._saved_entities_to_cache_map.get(save_object_type)
282
+
283
+ modified = True
284
+
285
+ if cache and saved_object.pk:
286
+ original_object = cache.get(id=saved_object.pk)
287
+
288
+ if original_object:
289
+ modified = self._is_save_object_modified(saved_object, original_object, ignore_fields)
290
+
291
+ return modified
292
+
293
+ def _is_save_object_modified(
294
+ self,
295
+ saved_object: 'BaseEntityModel',
296
+ original_object: 'BaseEntityModel',
297
+ ignore_fields: Optional[Iterable[str]] = None
298
+ ) -> bool:
299
+ """
300
+ Проверяет, были ли изменения в указанном объекте относительно оригинала.
301
+
302
+ Args:
303
+ saved_object ('BaseEntityModel'): Объект, который предполагается сохранить.
304
+ original_object ('BaseEntityModel'): Оригинальное значение из кэша.
305
+ ignore_fields (Optional[Iterable[str]]): Поля, которые следует игнорировать при сравнении.
306
+
307
+ Returns:
308
+ bool: True, если объект был изменён, иначе False.
309
+ """
310
+ if not isinstance(saved_object, type(original_object)):
311
+ raise ValueError(CACHED_OBJECTS_TYPE_MISMATCH_ERROR)
312
+
313
+ if saved_object.operation == EntityLogOperation.DELETE:
314
+ return True
315
+
316
+ if ignore_fields is None:
317
+ ignore_fields = []
318
+
319
+ # Сравниваем поля объектов
320
+ for field in original_object._meta.fields:
321
+ field_name = field.name
322
+
323
+ # Пропускаем игнорируемые поля
324
+ if field_name in ignore_fields:
325
+ continue
326
+
327
+ # Получаем текущее значение поля из измененного объекта
328
+ current_value = getattr(saved_object, field_name)
329
+
330
+ # Получаем оригинальное значение поля из кеша
331
+ original_value = getattr(original_object, field_name)
332
+
333
+ # Сравниваем значения
334
+ if current_value != original_value:
335
+ return True
336
+
337
+ # Если все поля совпадают, объект не изменился
338
+ return False
339
+
340
+ def _before_prepare(self, *args, **kwargs):
341
+ """
342
+ Подготовительный этап перед началом обработки объектов.
343
+
344
+ Сохраняет копию текущих сопоставлений объектов и кэшей, чтобы обеспечить чистое состояние для последующего
345
+ сравнения.
346
+ """
347
+ self._saved_entities_to_cache_map = {
348
+ model: deepcopy(cache)
349
+ for model, cache in self._model_to_cache_map.items()
350
+ }
351
+
352
+ super()._before_prepare(*args, **kwargs)
353
+
354
+ @property
355
+ @abstractmethod
356
+ def _model_to_cache_map(self) -> dict[type['BaseEntityModel'], 'WebEduEntityCache']:
357
+ """
358
+ Абстрактное свойство, возвращающее соответствие между типами моделей и их кэшами.
359
+
360
+ Должно быть реализовано в дочернем классе. Используется для получения оригинальных данных объектов
361
+ перед сравнением.
362
+
363
+ Returns:
364
+ dict[type[BaseEntityModel], WebEduEntityCache]: Словарь, где ключ — это тип модели, а значение —
365
+ соответствующий кэш этой модели.
366
+ """
367
+
368
+ @property
369
+ @abstractmethod
370
+ def _model_to_save_queue_map(self) -> dict[type['BaseEntityModel'], dict]:
371
+ """
372
+ Абстрактное свойство, возвращающее соответствие между типами моделей и очередями сохранения.
373
+
374
+ Должно быть реализовано в дочернем классе. Используется для определения, в какую очередь будет добавляться
375
+ объект для сохранения.
376
+
377
+ Returns:
378
+ dict[type[BaseEntityModel], dict]: Словарь, где ключ — это тип модели, а значение — словарь, представляющий
379
+ очередь сохранения для этой модели.
380
+ """
381
+
382
+ def _add_to_save_entities(
383
+ self,
384
+ save_object: 'BaseEntityModel',
385
+ operation: EntityLogOperation,
386
+ ):
387
+ """Добавление в очередь сущности на сохранение."""
388
+ try:
389
+ to_save_queue: dict[
390
+ EntityLogOperation, dict[int, 'BaseEntityModel']
391
+ ] = self._model_to_save_queue_map[type(save_object)]
392
+ except KeyError:
393
+ raise KeyError(NOT_SPECIFIED_QUEUE_TO_MODEL_ERROR.format(save_object._meta.model_name))
394
+
395
+ save_object.operation = operation
396
+ save_object.collecting_sub_stage = self._sub_stage
397
+
398
+ if operation == EntityLogOperation.CREATE:
399
+ to_save_queue[EntityLogOperation.CREATE][save_object.id] = save_object
400
+ elif operation in {EntityLogOperation.UPDATE, EntityLogOperation.DELETE}:
401
+ if self._is_object_to_save(save_object, self._ignored_fields.get(operation)):
402
+ to_save_queue[EntityLogOperation.UPDATE][save_object.id] = save_object
403
+
404
+ def _get_entity_saver(self, model: 'BaseEntityModel') -> EntitySaver:
405
+ """
406
+ Возвращает экземпляр saver'а для указанной модели.
407
+
408
+ Args:
409
+ model (BaseEntityModel): Тип модели, для которой требуется получить saver.
410
+
411
+ Returns:
412
+ EntitySaver: Объект, отвечающий за сохранение сущностей указанного типа.
413
+ """
414
+ to_save_queue = self._model_to_save_queue_map[model]
415
+ return EntitySaver(to_save_entities=to_save_queue, model=model)
416
+
417
+ def _save_entities(self):
418
+ """
419
+ Выполняет сохранение всех отфильтрованных и подготовленных объектов.
420
+
421
+ Перебирает все модели из `_model_to_save_queue_map` и вызывает соответствующий `EntitySaver`.
422
+ """
423
+ for model in self._model_to_save_queue_map:
424
+ entity_saver = self._get_entity_saver(model)
425
+ entity_saver()
@@ -9,6 +9,10 @@ from typing import (
9
9
  Optional,
10
10
  )
11
11
 
12
+ from edu_rdm_integration.uploader_log.enums import (
13
+ RequestResultStatus,
14
+ )
15
+
12
16
  from django.db.models import (
13
17
  CASCADE,
14
18
  PROTECT,
@@ -917,6 +921,13 @@ class UploaderClientLog(Entry):
917
921
  """Ошибка запроса."""
918
922
  return self.error
919
923
 
924
+ @property
925
+ def result_status_display(self) -> str:
926
+ """Результат запроса."""
927
+ result_status = getattr(self, 'result_status', RequestResultStatus.ERROR)
928
+
929
+ return RequestResultStatus.values.get(result_status) or RequestResultStatus.values[RequestResultStatus.ERROR]
930
+
920
931
  class Meta:
921
932
  proxy = True
922
933
 
@@ -11,6 +11,13 @@ from typing import (
11
11
  Optional,
12
12
  )
13
13
 
14
+ from django.conf import (
15
+ settings,
16
+ )
17
+ from edu_rdm_integration.uploader_log.enums import (
18
+ RequestResultStatus,
19
+ )
20
+
14
21
  from django.db.models import (
15
22
  Q,
16
23
  )
@@ -42,7 +49,9 @@ from edu_rdm_integration.models import (
42
49
  )
43
50
  from edu_rdm_integration.uploader_log.ui import (
44
51
  UploaderLogInfoWindow,
45
- UploaderLogListWindow,
52
+ )
53
+ from objectpack.filters import (
54
+ CustomFilter,
46
55
  )
47
56
 
48
57
 
@@ -54,7 +63,6 @@ class UploaderLogPack(ObjectPack):
54
63
  title = 'Журнал логов РВД'
55
64
  model = UploaderClientLog
56
65
 
57
- list_window = UploaderLogListWindow
58
66
  edit_window = UploaderLogInfoWindow
59
67
 
60
68
  _is_primary_for_model = False
@@ -108,8 +116,13 @@ class UploaderLogPack(ObjectPack):
108
116
  },
109
117
  {
110
118
  'header': 'Результат',
111
- 'data_index': 'http_response_status',
119
+ 'data_index': 'result_status_display',
112
120
  'sortable': False,
121
+ 'filter': ChoicesFilter(
122
+ choices=RequestResultStatus.get_choices(),
123
+ parser=int,
124
+ lookup='result_status',
125
+ ),
113
126
  'width': 5,
114
127
  },
115
128
  {
@@ -129,8 +142,13 @@ class UploaderLogPack(ObjectPack):
129
142
  {
130
143
  'header': 'Код статуса загрузки',
131
144
  'data_index': 'status_code',
132
- 'sortable': False,
145
+ 'sortable': True,
133
146
  'searchable': True,
147
+ 'filter': CustomFilter(
148
+ xtype='field',
149
+ parser=str,
150
+ lookup=lambda v: Q(response__icontains=f'"code": {v}'),
151
+ ),
134
152
  'width': 10,
135
153
  },
136
154
  {
@@ -151,7 +169,7 @@ class UploaderLogPack(ObjectPack):
151
169
  ),
152
170
  'column_renderer': boolean_column_renderer(),
153
171
  'width': 5,
154
- }
172
+ },
155
173
  ]
156
174
 
157
175
  def __init__(self):
@@ -204,6 +222,10 @@ class UploaderLogPack(ObjectPack):
204
222
  """Конфигурирование грида окна списка."""
205
223
  super().configure_grid(grid, *args, **kwargs)
206
224
 
225
+ if self.allow_paging:
226
+ grid.allow_paging = self.allow_paging
227
+ grid.paging_bar.page_size = self._DEFAULT_PAGING_LIMIT
228
+
207
229
  grid.url_edit = None
208
230
  add_one_row_button(
209
231
  'Просмотр',
@@ -224,11 +246,24 @@ class UploaderLogPack(ObjectPack):
224
246
 
225
247
  return params
226
248
 
227
- def extend_menu(self, menu): # noqa D102
228
- return menu.SubMenu(
229
- 'Администрирование', menu.SubMenu(
230
- 'Региональная витрина данных', menu.Item(
231
- self.title, self.list_window_action
232
- )
249
+ def extend_menu(self, menu):
250
+ """Размещение в меню подменю "Администрирование -> Региональная витрина данных -> Журнал логов РВД".
251
+
252
+ Args:
253
+ menu: Объект меню.
254
+ Returns:
255
+ Подменю "Администрирование -> Региональная витрина данных -> Журнал логов РВД".
256
+ """
257
+
258
+ if settings.RDM_MENU_ITEM:
259
+ return menu.SubMenu(
260
+ 'Администрирование',
261
+ menu.SubMenu(
262
+ 'Региональная витрина данных',
263
+ menu.Item(
264
+ self.title,
265
+ self.list_window_action,
266
+ ),
267
+ icon='menu-dicts-16',
268
+ ),
233
269
  )
234
- )
@@ -3,7 +3,6 @@ from m3_ext.ui.fields import (
3
3
  )
4
4
  from objectpack.ui import (
5
5
  BaseEditWindow,
6
- BaseListWindow,
7
6
  )
8
7
 
9
8
  from educommon.utils.ui import (
@@ -62,13 +61,3 @@ class UploaderLogInfoWindow(BaseEditWindow):
62
61
 
63
62
  switch_window_in_read_only_mode(self)
64
63
  self.make_read_only()
65
-
66
-
67
- class UploaderLogListWindow(BaseListWindow):
68
- """Окно для списка логов Загрузчика данных в витрину."""
69
-
70
- def _init_components(self):
71
- super()._init_components()
72
-
73
- self.grid.allow_paging = True
74
- self.grid.paging_bar.page_size = 35
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edu-rdm-integration
3
- Version: 3.7.0
3
+ Version: 3.8.1
4
4
  Summary: Интеграция с Региональной витриной данных
5
5
  Author-email: BARS Group <education_dev@bars.group>
6
6
  Project-URL: Homepage, https://stash.bars-open.ru/projects/EDUBASE/repos/edu_rdm_integration/browse
@@ -79,7 +79,7 @@ Dynamic: license-file
79
79
  Стоит обратить внимание, что сущности РВД могут содержать в себе данные из нескольких моделей РВД.
80
80
 
81
81
  Очереди для периодических задач сборки и выгрузки данных
82
- : Важно учитывать, что с версии пакета 3.6 вводится две новые очереди и соответсвущие этим очередям периодические задачи
82
+ : Важно учитывать, что с версии пакета 3.6 вводится две новые очереди и соответствущие этим очередям периодические задачи
83
83
  сбора и выгрузки данных. Очередь для сущности указывается в реестре "Сущности для сбора и экспорта данных" - по умолчанию все
84
84
  сущности относятся к основной очереди.
85
85
  Итого - нужно настроить три очереди для работы.
@@ -142,8 +142,36 @@ Dynamic: license-file
142
142
  ('uploader_client', 'ENABLE_REQUEST_EMULATION'): False,
143
143
  })
144
144
  ```
145
- С версии пакета 3.6 добавляются новые настройки для двух периодических задач разных очередей сбора и выгрузки данных
146
- ```
145
+ Дополнительные настройки с версии 3.4.2
146
+ ```
147
+ PROJECT_DEFAULT_CONFIG.update({
148
+ # Настройки РВД
149
+ ('rdm_general', 'EXPORT_ENTITY_ID_PREFIX'): '', # Дефолтное значение нужно изменить на специфическое системе
150
+ ('rdm_general', 'COLLECT_CHUNK_SIZE'): 500,
151
+ ('rdm_general', 'EXPORT_CHUNK_SIZE'): 500,
152
+ ('rdm_transfer_task', 'MINUTE'): '0',
153
+ ('rdm_transfer_task', 'HOUR'): '*/4',
154
+ ('rdm_transfer_task', 'DAY_OF_WEEK'): '*',
155
+ ('rdm_transfer_task', 'LOCK_EXPIRE_SECONDS'): 21600,
156
+ ('rdm_transfer_task', 'TIMEDELTA'): 3600,
157
+ ('rdm_transfer_task', 'ENTITIES'): '',
158
+ ('rdm_upload_status_task', 'MINUTE'): '*/30',
159
+ ('rdm_upload_status_task', 'HOUR'): '*',
160
+ ('rdm_upload_status_task', 'DAY_OF_WEEK'): '*',
161
+ ('rdm_upload_status_task', 'LOCK_EXPIRE_SECONDS'): 7200,
162
+ ('rdm_upload_data_task', 'MINUTE'): '0',
163
+ ('rdm_upload_data_task', 'HOUR'): '*/2',
164
+ ('rdm_upload_data_task', 'DAY_OF_WEEK'): '*',
165
+ ('rdm_upload_data_task', 'LOCK_EXPIRE_SECONDS'): 7200,
166
+ ('uploader_client', 'URL'): 'http://localhost:8090',
167
+ ('uploader_client', 'DATAMART_NAME'): '',
168
+ ('uploader_client', 'REQUEST_RETRIES'): 10,
169
+ ('uploader_client', 'REQUEST_TIMEOUT'): 10,
170
+ ('uploader_client', 'ENABLE_REQUEST_EMULATION'): False,
171
+ })
172
+ ```
173
+ С версии пакета 3.6 добавляются новые настройки для двух периодических задач разных очередей сбора и выгрузки данных
174
+ ```
147
175
  PROJECT_DEFAULT_CONFIG.update({
148
176
  # Настройки РВД
149
177
  ('rdm_general', 'EXPORT_ENTITY_ID_PREFIX'): '', # Дефолтное значение нужно изменить на специфическое системе
@@ -167,14 +195,18 @@ Dynamic: license-file
167
195
  ('rdm_upload_status_task', 'HOUR'): '*',
168
196
  ('rdm_upload_status_task', 'DAY_OF_WEEK'): '*',
169
197
  ('rdm_upload_status_task', 'LOCK_EXPIRE_SECONDS'): 7200,
198
+ ('rdm_upload_data_task', 'MINUTE'): '0',
199
+ ('rdm_upload_data_task', 'HOUR'): '*/2',
200
+ ('rdm_upload_data_task', 'DAY_OF_WEEK'): '*',
201
+ ('rdm_upload_data_task', 'LOCK_EXPIRE_SECONDS'): 7200,
170
202
  ('uploader_client', 'URL'): 'http://localhost:8090',
171
203
  ('uploader_client', 'DATAMART_NAME'): '',
172
204
  ('uploader_client', 'REQUEST_RETRIES'): 10,
173
205
  ('uploader_client', 'REQUEST_TIMEOUT'): 10,
174
206
  ('uploader_client', 'ENABLE_REQUEST_EMULATION'): False,
175
207
  })
176
-
177
- ```
208
+
209
+ ```
178
210
  - Получение значений настроек из конфигурационного файла в settings.py:
179
211
 
180
212
  ```
@@ -233,21 +265,48 @@ Dynamic: license-file
233
265
  RDM_UPLOADER_CLIENT_ENABLE_REQUEST_EMULATION = conf.get_bool('uploader_client', 'ENABLE_REQUEST_EMULATION')
234
266
 
235
267
  ```
236
- С версии пакета 3.6 добавляются настройки для двух новых периодических задач
237
- ```
238
- # Настройка запуска периодической задачи выгрузки данных - быстрая очередь:
239
- RDM_FAST_TRANSFER_TASK_MINUTE = conf.get('rdm_transfer_task_fast', 'MINUTE')
240
- RDM_FAST_TRANSFER_TASK_HOUR = conf.get('rdm_transfer_task_fast', 'HOUR')
241
- RDM_FAST_TRANSFER_TASK_DAY_OF_WEEK = conf.get('rdm_transfer_task_fast', 'DAY_OF_WEEK')
242
- RDM_FAST_TRANSFER_TASK_LOCK_EXPIRE_SECONDS = conf.get_int('rdm_transfer_task_fast', 'LOCK_EXPIRE_SECONDS')
243
-
244
- # Настройка запуска периодической задачи выгрузки данных - долгая очередь расчетных моделей:
245
- RDM_LONG_TRANSFER_TASK_MINUTE = conf.get('rdm_transfer_task_long', 'MINUTE')
246
- RDM_LONG_TRANSFER_TASK_HOUR = conf.get('rdm_transfer_task_long', 'HOUR')
247
- RDM_LONG_TRANSFER_TASK_DAY_OF_WEEK = conf.get('rdm_transfer_task_long', 'DAY_OF_WEEK')
248
- RDM_LONG_TRANSFER_TASK_LOCK_EXPIRE_SECONDS = conf.get_int('rdm_transfer_task_long', 'LOCK_EXPIRE_SECONDS')
249
-
250
- ```
268
+ Дополнительные настройки с версии 3.3.0
269
+ ```
270
+ # Объем очереди файлов в витрину байтах) - по умолчанию 512 Мбайт.
271
+ RDM_UPLOAD_QUEUE_MAX_SIZE = conf.get_int('rdm_general', 'UPLOAD_QUEUE_MAX_SIZE') or 500_000_000
272
+
273
+ # Настройка очереди Redis для формирования файлов РВД.
274
+ RDM_REDIS_HOST = conf.get('rdm_redis', 'REDIS_HOST')
275
+ RDM_REDIS_PORT = conf.get('rdm_redis', 'REDIS_PORT')
276
+ RDM_REDIS_DB = conf.get('rdm_redis', 'REDIS_DB')
277
+ RDM_REDIS_PASSWORD = conf.get('rdm_redis', 'REDIS_PASSWORD')
278
+
279
+ ```
280
+ Дополнительные настройки с версии 3.3.1
281
+ ```
282
+ # Таймаут для сохранения параметров в общем кеш.
283
+ RDM_REDIS_CACHE_TIMEOUT_SECONDS = conf.get_int('rdm_redis', 'REDIS_CACHE_TIMEOUT_SECONDS') or 60 * 60 * 2
284
+
285
+ ```
286
+ Дополнительные настройки с версии 3.4.2
287
+ ```
288
+ # Настройка запуска периодической задачи отправки файлов с данными РВД
289
+ RDM_UPLOAD_DATA_TASK_MINUTE = conf.get('rdm_upload_data_task', 'MINUTE')
290
+ RDM_UPLOAD_DATA_TASK_HOUR = conf.get('rdm_upload_data_task', 'HOUR')
291
+ RDM_UPLOAD_DATA_TASK_DAY_OF_WEEK = conf.get('rdm_upload_data_task', 'DAY_OF_WEEK')
292
+ RDM_UPLOAD_DATA_TASK_LOCK_EXPIRE_SECONDS = conf.get_int('rdm_upload_data_task', 'LOCK_EXPIRE_SECONDS') or 60 * 60 * 2
293
+
294
+ ```
295
+ С версии пакета 3.6 добавляются настройки для двух новых периодических задач
296
+ ```
297
+ # Настройка запуска периодической задачи выгрузки данных - быстрая очередь:
298
+ RDM_FAST_TRANSFER_TASK_MINUTE = conf.get('rdm_transfer_task_fast', 'MINUTE')
299
+ RDM_FAST_TRANSFER_TASK_HOUR = conf.get('rdm_transfer_task_fast', 'HOUR')
300
+ RDM_FAST_TRANSFER_TASK_DAY_OF_WEEK = conf.get('rdm_transfer_task_fast', 'DAY_OF_WEEK')
301
+ RDM_FAST_TRANSFER_TASK_LOCK_EXPIRE_SECONDS = conf.get_int('rdm_transfer_task_fast', 'LOCK_EXPIRE_SECONDS')
302
+
303
+ # Настройка запуска периодической задачи выгрузки данных - долгая очередь расчетных моделей:
304
+ RDM_LONG_TRANSFER_TASK_MINUTE = conf.get('rdm_transfer_task_long', 'MINUTE')
305
+ RDM_LONG_TRANSFER_TASK_HOUR = conf.get('rdm_transfer_task_long', 'HOUR')
306
+ RDM_LONG_TRANSFER_TASK_DAY_OF_WEEK = conf.get('rdm_transfer_task_long', 'DAY_OF_WEEK')
307
+ RDM_LONG_TRANSFER_TASK_LOCK_EXPIRE_SECONDS = conf.get_int('rdm_transfer_task_long', 'LOCK_EXPIRE_SECONDS')
308
+
309
+ ```
251
310
  Перечень настроек в settings.py указан в таблице ниже.
252
311
 
253
312
  | Название настройки в settings | Описание | Значение по умолчанию |
@@ -264,12 +323,37 @@ Dynamic: license-file
264
323
  | RDM_TRANSFER_TASK_MINUTE | Настройка запуска периодической задачи выгрузки данных. Минута | '0' |
265
324
  | RDM_TRANSFER_TASK_HOUR | Настройка запуска периодической задачи выгрузки данных. Час | '*/4' |
266
325
  | RDM_TRANSFER_TASK_DAY_OF_WEEK | Настройка запуска периодической задачи выгрузки данных. День недели | '*' |
267
- | RDM_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секунадх) | 21600 |
326
+ | RDM_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секундах) | 21600 |
268
327
  | RDM_UPLOAD_STATUS_TASK_MINUTE | Настройка запуска периодической задачи статуса загрузки данных в витрину. Минута | '*/30' |
269
328
  | RDM_UPLOAD_STATUS_TASK_HOUR | Настройка запуска периодической задачи статуса загрузки данных в витрину. Час | '*' |
270
329
  | RDM_UPLOAD_STATUS_TASK_DAY_OF_WEEK | Настройка запуска периодической задачи статуса загрузки данных в витрину. День недели | '*' |
271
- | RDM_UPLOAD_STATUS_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секунадх) | 3600 |
330
+ | RDM_UPLOAD_STATUS_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секундах) | 3600 |
272
331
  | RDM_CHECK_SUSPEND_TASK_STAGE_TIMEOUT | Дельта для определения зависшего подэтапа. Минута | 120 |
332
+
333
+ С версии пакета 3.3.0 добавляются новые настройки
334
+
335
+ | Название настройки в settings | Описание | Значение по умолчанию |
336
+ |--------------------------------------------|----------------------------------------------------------------------------------------|-----------------------|
337
+ | RDM_UPLOAD_QUEUE_MAX_SIZE | Объем очереди файлов в витрину (в байтах). | 500_000_000 |
338
+ | RDM_REDIS_HOST | Настройка очереди Redis для формирования файлов РВД (хост). | |
339
+ | RDM_REDIS_PORT | Настройка очереди Redis для формирования файлов РВД (порт). | |
340
+ | RDM_REDIS_DB | Настройка очереди Redis для формирования файлов РВД (номер бд). | |
341
+ | RDM_REDIS_PASSWORD | Настройка очереди Redis для формирования файлов РВД (пароль). | |
342
+
343
+ С версии пакета 3.3.1 добавляются новые настройки
344
+
345
+ | Название настройки в settings | Описание | Значение по умолчанию |
346
+ |--------------------------------------------|----------------------------------------------------------------------------------------|-----------------------|
347
+ | RDM_REDIS_CACHE_TIMEOUT_SECONDS | Таймаут для сохранения параметров в общем кеш (секунды). | 7200 |
348
+
349
+ С версии пакета 3.4.2 добавляются новые настройки
350
+
351
+ | Название настройки в settings | Описание | Значение по умолчанию |
352
+ |--------------------------------------------|----------------------------------------------------------------------------------------|-----------------------|
353
+ | RDM_UPLOAD_DATA_TASK_MINUTE | Настройка запуска периодической задачи отправки файлов с данными РВД (минута). | '0' |
354
+ | RDM_UPLOAD_DATA_TASK_HOUR | Настройка запуска периодической задачи отправки файлов с данными РВД (час). | '*/2' |
355
+ | RDM_UPLOAD_DATA_TASK_DAY_OF_WEEK | Настройка запуска периодической задачи отправки файлов с данными РВД (день недели). | '*' |
356
+ | RDM_UPLOAD_DATA_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секундах). | 7200 |
273
357
 
274
358
  С версии пакета 3.6 добавляются новые настройки
275
359
 
@@ -278,11 +362,11 @@ Dynamic: license-file
278
362
  | RDM_FAST_TRANSFER_TASK_MINUTE | Настройка запуска периодической задачи (быстрая очередь) выгрузки данных. Минута | '*/5' |
279
363
  | RDM_FAST_TRANSFER_TASK_HOUR | Настройка запуска периодической задачи (быстрая очередь) выгрузки данных. Час | '*' |
280
364
  | RDM_FAST_TRANSFER_TASK_DAY_OF_WEEK | Настройка запуска периодической задачи (быстрая очередь) выгрузки данных. День недели | '*' |
281
- | RDM_FAST_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секунадх) | 1800 |
365
+ | RDM_FAST_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секундах) | 1800 |
282
366
  | RDM_LONG_TRANSFER_TASK_MINUTE | Настройка запуска периодической задачи (долгая очередь) выгрузки данных. Минута | 0 |
283
367
  | RDM_LONG_TRANSFER_TASK_HOUR | Настройка запуска периодической задачи (долгая очередь) выгрузки данных. Час | '*/6' |
284
368
  | RDM_LONG_TRANSFER_TASK_DAY_OF_WEEK | Настройка запуска периодической задачи (долгая очередь) выгрузки данных. День недели | '*' |
285
- | RDM_LONG_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секунадх) | 28800 |
369
+ | RDM_LONG_TRANSFER_TASK_LOCK_EXPIRE_SECONDS | Время по истечении которого, блокировка может быть снята (в секундах) | 28800 |
286
370
 
287
371
  - В дефолтный конфиг проекта необходимо добавить:
288
372
 
@@ -338,8 +422,38 @@ Dynamic: license-file
338
422
  # Включить эмуляцию отправки запросов
339
423
  ENABLE_REQUEST_EMULATION = True
340
424
  ```
341
- - С версии 3.6 в деволтный конфиг также нужно добавить два дополнительных раздела
342
- ```
425
+ - С версии 3.3.0 в дефолтный конфиг нужно добавить
426
+ ```
427
+ [rdm_general]
428
+ ...
429
+ # Объем очереди файлов в витрину (в байтах) - по умолчанию 512 Мбайт.
430
+ UPLOAD_QUEUE_MAX_SIZE = 500_000_000
431
+
432
+ # Настройка очереди Redis для формирования файлов РВД.
433
+ [rdm_redis]
434
+ REDIS_HOST = localhost
435
+ REDIS_PORT = 6379
436
+ REDIS_DB = 1
437
+ REDIS_PASSWORD =
438
+ ```
439
+ - С версии 3.3.1 в дефолтный конфиг нужно добавить
440
+ ```
441
+ [rdm_redis]
442
+ ...
443
+ # Таймаут для сохранения параметров в общем кеш.
444
+ REDIS_CACHE_TIMEOUT_SECONDS = 7200
445
+ ```
446
+ - С версии 3.4.2 в дефолтный конфиг нужно добавить
447
+ ```
448
+ # Настройка запуска периодической задачи отправки csv-файлов в витрину.
449
+ [rdm_upload_data_task]
450
+ MINUTE=*/2
451
+ HOUR=*
452
+ DAY_OF_WEEK=*
453
+ LOCK_EXPIRE_SECONDS = 60 * 60 * 2
454
+ ```
455
+ - С версии 3.6 в дефолтный конфиг также нужно добавить два дополнительных раздела
456
+ ```
343
457
 
344
458
  [rdm_transfer_task_fast]
345
459
  MINUTE=*/2
@@ -352,7 +466,7 @@ Dynamic: license-file
352
466
  HOUR=*
353
467
  DAY_OF_WEEK=*
354
468
  LOCK_EXPIRE_SECONDS = 21600
355
- ```
469
+ ```
356
470
  На основе дефолтного конфига произвести конфигурирование приложений.
357
471
 
358
472
  ## Сборка и распространение
@@ -8,7 +8,7 @@ edu_rdm_integration/entities.py,sha256=mhVeB88A-VD5IAzZCNeI1qnkvNoZ8LPiLBdqk1yA3
8
8
  edu_rdm_integration/enums.py,sha256=RpQIZM1iSgFbYDHfwrbT-BwgRf-N9ZZnJgx8UyRFQ2o,4978
9
9
  edu_rdm_integration/helpers.py,sha256=qwSyeIDBVEhdYG9raf3uLZPd1_2eXuNAaosSR7bLa50,14759
10
10
  edu_rdm_integration/mapping.py,sha256=1B6TsC4Os9wiM8L8BChnCNv_iWqjeWu3bdDsqKVsId0,616
11
- edu_rdm_integration/models.py,sha256=lrlJUAJJr29rrNwNdyCkswyRGmnm8XVDQDArWVO2ivc,31907
11
+ edu_rdm_integration/models.py,sha256=4IR5gdNX6YVvGysQQeixcjIOCrMQ37RVhmyvSwucLdc,32297
12
12
  edu_rdm_integration/redis_cache.py,sha256=SP_rcL5t6PTVLOnEYn_NTX0Z666VdZT4By2pyED24Z4,1537
13
13
  edu_rdm_integration/signals.py,sha256=3eRlpkDcFCF6TN80-QM8yBYLcyozzcmoPjz6r4_ApWg,73
14
14
  edu_rdm_integration/storages.py,sha256=G4Q4tIyJdEyb9ka551PADCFIm66bpsJe9VBRcvQhLMI,6745
@@ -46,10 +46,11 @@ edu_rdm_integration/collect_data/helpers.py,sha256=wi1TECBFwur0LyREUwGLNXqQG731e
46
46
  edu_rdm_integration/collect_data/tests.py,sha256=_Inf8v_TS_LorBb702qykzc1Syj_tsPVRLJREcJ-XmY,5515
47
47
  edu_rdm_integration/collect_data/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  edu_rdm_integration/collect_data/base/caches.py,sha256=_Ja0q3hPSE_Mq-MCZN-1jr0WvpOqUr1-CkoBf1B7qKc,2141
49
+ edu_rdm_integration/collect_data/base/consts.py,sha256=nzP7973d-YG29l-JxJcq7dF81QDLP7FRtTq0dSq46GM,304
49
50
  edu_rdm_integration/collect_data/base/functions.py,sha256=E1vYmC8F8NM5cBB5SGQEpluHrMynpjf3Ek3s0HsbxwY,2998
50
51
  edu_rdm_integration/collect_data/base/helpers.py,sha256=MsHEzkUl1KVMIxGfDkhcItXLxQNuNNOhN5tzTcPm0NQ,982
51
52
  edu_rdm_integration/collect_data/base/managers.py,sha256=hza8kugR9hbLK3LU8DBfF61ul7mPPl5pPm530QMjj0k,6143
52
- edu_rdm_integration/collect_data/base/mixins.py,sha256=kwZ77dc5dCmHVGCN6JMslpyfXfEEoks7vmXH-CzezJc,8538
53
+ edu_rdm_integration/collect_data/base/mixins.py,sha256=miAXhXdkTr6MJh_qlsGMWW4gBgcAI2gsxmmu3VFaUYw,18402
53
54
  edu_rdm_integration/collect_data/base/runners.py,sha256=Mf5Lux6IWWqKd798v149OjqfBWiDtigeFd701HSRBGg,1565
54
55
  edu_rdm_integration/collect_data/calculated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
56
  edu_rdm_integration/collect_data/calculated/strategies.py,sha256=nppmheuzhF8H7JcfEhEZCmHI0eeRj8BbrLGNF0nsoa0,7619
@@ -175,14 +176,14 @@ edu_rdm_integration/registry/actions.py,sha256=-CHe95jbxO9JAEaOx6nV6Avn75ynppvZR
175
176
  edu_rdm_integration/registry/ui.py,sha256=v4GqbQUcoeHxfUPUYORuj4DfzIp49diY-F1hyL3TCPo,2592
176
177
  edu_rdm_integration/templates/ui-js/transferred-entity-list.js,sha256=IWEZ9JoTxD5-CLic5v07XHWW0iGRWk-cjeGVSzU4yKg,1117
177
178
  edu_rdm_integration/uploader_log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
178
- edu_rdm_integration/uploader_log/actions.py,sha256=2ckgI1PKgVcLYkbhtbK_bfv_6lDxpiIRSk1uPCIL-gg,6755
179
+ edu_rdm_integration/uploader_log/actions.py,sha256=K06pkaWGjPnt6cpPYdSk8X7nqQEfW-vXXvNVORRbDCs,7957
179
180
  edu_rdm_integration/uploader_log/apps.py,sha256=tYJj4-sDlq8fLOSvw18L_yys7SILpTKWNmE2Qug6GnE,265
180
181
  edu_rdm_integration/uploader_log/enums.py,sha256=rgSO3BL2rh2xpfm0Pt4waQW8fB1VMJLdsGmr3SXwH_U,266
181
182
  edu_rdm_integration/uploader_log/managers.py,sha256=OFdToWV8qhdfeGNpd-UWAmSEISzixmVQ6LF75EW7gzA,3248
182
- edu_rdm_integration/uploader_log/ui.py,sha256=YM9Buqp2wxE95Wf5gvAATBzuYzDOossK1sEmvFk07cI,2110
183
+ edu_rdm_integration/uploader_log/ui.py,sha256=7O63XJJYnJBLVU9aGuSyMOxFYtcj_Kyf5u6HIiuxl9A,1788
183
184
  edu_rdm_integration/uploader_log/templates/ui-js/object-grid-buttons.js,sha256=2xyGe0wdVokM0RhpzRzcRvJPBkBmPe3SlZry4oP4Nzs,6201
184
- edu_rdm_integration-3.7.0.dist-info/licenses/LICENSE,sha256=uw43Gjjj-1vXWCItfSrNDpbejnOwZMrNerUh8oWbq8Q,3458
185
- edu_rdm_integration-3.7.0.dist-info/METADATA,sha256=_tvMmulyEcH3b2JdqqSmgMvmK-JWvZbfs17iFBCvF1w,27415
186
- edu_rdm_integration-3.7.0.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
187
- edu_rdm_integration-3.7.0.dist-info/top_level.txt,sha256=nRJV0O14UtNE-jGIYG03sohgFnZClvf57H5m6VBXe9Y,20
188
- edu_rdm_integration-3.7.0.dist-info/RECORD,,
185
+ edu_rdm_integration-3.8.1.dist-info/licenses/LICENSE,sha256=uw43Gjjj-1vXWCItfSrNDpbejnOwZMrNerUh8oWbq8Q,3458
186
+ edu_rdm_integration-3.8.1.dist-info/METADATA,sha256=dEub92knjtp-P5cvuOvD1Fvfx9ZDv_Uwg7eR6JSW6_c,35263
187
+ edu_rdm_integration-3.8.1.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
188
+ edu_rdm_integration-3.8.1.dist-info/top_level.txt,sha256=nRJV0O14UtNE-jGIYG03sohgFnZClvf57H5m6VBXe9Y,20
189
+ edu_rdm_integration-3.8.1.dist-info/RECORD,,