edu-rdm-integration 3.3.6__py3-none-any.whl → 3.3.8__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.
@@ -15,6 +15,7 @@ from typing import (
15
15
  List,
16
16
  Set,
17
17
  Type,
18
+ Union,
18
19
  )
19
20
 
20
21
  from django.conf import (
@@ -69,6 +70,13 @@ from edu_rdm_integration.consts import (
69
70
  from edu_rdm_integration.enums import (
70
71
  FileUploadStatusEnum,
71
72
  )
73
+ from edu_rdm_integration.export_data.export_manger import (
74
+ ExportEntityQueueSender,
75
+ WorkerSender,
76
+ )
77
+ from edu_rdm_integration.export_data.queue import (
78
+ Queue,
79
+ )
72
80
  from edu_rdm_integration.helpers import (
73
81
  get_exporting_managers_max_period_ended_dates,
74
82
  )
@@ -77,6 +85,9 @@ from edu_rdm_integration.models import (
77
85
  ExportingDataSubStageStatus,
78
86
  RegionalDataMartEntityEnum,
79
87
  )
88
+ from edu_rdm_integration.redis_cache import (
89
+ AbstractCache,
90
+ )
80
91
  from edu_rdm_integration.signals import (
81
92
  manager_created,
82
93
  )
@@ -121,8 +132,6 @@ class BaseExportEntitiesData(BaseOperationData):
121
132
  # Карта соответствия manager_id сущности и его основной модели
122
133
  self.manager_main_model_map: Dict[str, ModelBase] = {}
123
134
 
124
- self._configure_agent_client()
125
-
126
135
  @property
127
136
  def _log_file_path(self) -> str:
128
137
  """
@@ -130,57 +139,6 @@ class BaseExportEntitiesData(BaseOperationData):
130
139
  """
131
140
  return os.path.join(settings.MEDIA_ROOT, settings.RDM_EXPORT_LOG_DIR, f'{self.command_id}.log')
132
141
 
133
- def _configure_agent_client(self):
134
- """
135
- Конфигурирование клиента загрузчика данных в Витрину.
136
-
137
- #TODO Вынужденная мера, т.к. при запуске команды не производится проверка готовности конфигов приложений.
138
- # Нужно переработать механизм конфигурирования клиента загрузчика.
139
- """
140
- import uploader_client
141
- from django.core.cache import (
142
- DEFAULT_CACHE_ALIAS,
143
- caches,
144
- )
145
- from uploader_client.contrib.rdm.interfaces.configurations import (
146
- RegionalDataMartUploaderConfig,
147
- )
148
- if settings.RDM_UPLOADER_CLIENT_ENABLE_REQUEST_EMULATION:
149
- uploader_client.set_config(
150
- RegionalDataMartUploaderConfig(
151
- interface='uploader_client.contrib.rdm.interfaces.rest.OpenAPIInterfaceEmulation',
152
- url=settings.RDM_UPLOADER_CLIENT_URL,
153
- datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
154
- timeout=1,
155
- request_retries=1,
156
- )
157
- )
158
- elif settings.RDM_UPLOADER_CLIENT_USE_PROXY_API:
159
- uploader_client.set_config(
160
- RegionalDataMartUploaderConfig(
161
- interface='uploader_client.contrib.rdm.interfaces.rest.ProxyAPIInterface',
162
- cache=caches[DEFAULT_CACHE_ALIAS],
163
- url=settings.RDM_UPLOADER_CLIENT_URL,
164
- datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
165
- timeout=settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT,
166
- request_retries=settings.RDM_UPLOADER_CLIENT_REQUEST_RETRIES,
167
- organization_ogrn=settings.RDM_UPLOADER_CLIENT_ORGANIZATION_OGRN,
168
- installation_name=settings.RDM_UPLOADER_CLIENT_INSTALLATION_NAME,
169
- installation_id=settings.RDM_UPLOADER_CLIENT_INSTALLATION_ID,
170
- username=settings.RDM_UPLOADER_CLIENT_USERNAME,
171
- password=settings.RDM_UPLOADER_CLIENT_PASSWORD,
172
- )
173
- )
174
- else:
175
- uploader_client.set_config(
176
- RegionalDataMartUploaderConfig(
177
- url=settings.RDM_UPLOADER_CLIENT_URL,
178
- datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
179
- timeout=settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT,
180
- request_retries=settings.RDM_UPLOADER_CLIENT_REQUEST_RETRIES,
181
- )
182
- )
183
-
184
142
  def _has_stage_created_or_in_progress(self, manager_id: str, entity: str) -> bool:
185
143
  """Проверяет есть ли готовый к работе stage или в работе для данной сущности."""
186
144
  stage_created_or_in_progress = ExportingDataStage.objects.filter(
@@ -414,3 +372,105 @@ class ExportLatestEntitiesData(BaseExportLatestEntitiesData):
414
372
  def _get_async_task(self) -> Model:
415
373
  """Возвращает модель асинхронной задачи."""
416
374
  return RunningTask
375
+
376
+
377
+ class UploadEntitiesData(BaseOperationData):
378
+ """Класс отправки файлов с сущностями в витрину."""
379
+
380
+ def __init__(
381
+ self,
382
+ entities: Iterable[str],
383
+ data_cache: AbstractCache,
384
+ queue: Queue,
385
+ **kwargs,
386
+ ):
387
+ super().__init__(**kwargs)
388
+
389
+ # Если сущности не указаны, берется значение по умолчанию - все сущности:
390
+ self.entities = entities if entities else RegionalDataMartEntityEnum.get_enum_data().keys()
391
+
392
+ self.data_cache = data_cache
393
+ self.queue = queue
394
+
395
+ self.task_id = kwargs.get('task_id')
396
+
397
+ self._configure_agent_client()
398
+
399
+ @property
400
+ def _log_file_path(self) -> Union[str, bytes]:
401
+ """
402
+ Путь до лог файла.
403
+ """
404
+ if self.command_id:
405
+ log_file_path = os.path.join(settings.MEDIA_ROOT, settings.RDM_UPLOAD_LOG_DIR, f'{self.command_id}.log')
406
+ else:
407
+ log_file_path = os.path.join(settings.MEDIA_ROOT, settings.RDM_UPLOAD_LOG_DIR, 'upload_entity.log')
408
+
409
+ return log_file_path
410
+
411
+ # TODO https://jira.bars.group/browse/EDUSCHL-22492. Вынужденная мера, т.к. при запуске команды не производится
412
+ # проверка готовности конфигов приложений. Нужно переработать механизм конфигурирования клиента загрузчика.
413
+ def _configure_agent_client(self):
414
+ """
415
+ Конфигурирование клиента загрузчика данных в Витрину.
416
+ """
417
+ import uploader_client
418
+ from django.core.cache import (
419
+ DEFAULT_CACHE_ALIAS,
420
+ caches,
421
+ )
422
+ from uploader_client.contrib.rdm.interfaces.configurations import (
423
+ RegionalDataMartUploaderConfig,
424
+ )
425
+ if settings.RDM_UPLOADER_CLIENT_ENABLE_REQUEST_EMULATION:
426
+ uploader_client.set_config(
427
+ RegionalDataMartUploaderConfig(
428
+ interface='uploader_client.contrib.rdm.interfaces.rest.OpenAPIInterfaceEmulation',
429
+ url=settings.RDM_UPLOADER_CLIENT_URL,
430
+ datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
431
+ timeout=1,
432
+ request_retries=1,
433
+ )
434
+ )
435
+ elif settings.RDM_UPLOADER_CLIENT_USE_PROXY_API:
436
+ uploader_client.set_config(
437
+ RegionalDataMartUploaderConfig(
438
+ interface='uploader_client.contrib.rdm.interfaces.rest.ProxyAPIInterface',
439
+ cache=caches[DEFAULT_CACHE_ALIAS],
440
+ url=settings.RDM_UPLOADER_CLIENT_URL,
441
+ datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
442
+ timeout=settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT,
443
+ request_retries=settings.RDM_UPLOADER_CLIENT_REQUEST_RETRIES,
444
+ organization_ogrn=settings.RDM_UPLOADER_CLIENT_ORGANIZATION_OGRN,
445
+ installation_name=settings.RDM_UPLOADER_CLIENT_INSTALLATION_NAME,
446
+ installation_id=settings.RDM_UPLOADER_CLIENT_INSTALLATION_ID,
447
+ username=settings.RDM_UPLOADER_CLIENT_USERNAME,
448
+ password=settings.RDM_UPLOADER_CLIENT_PASSWORD,
449
+ )
450
+ )
451
+ else:
452
+ uploader_client.set_config(
453
+ RegionalDataMartUploaderConfig(
454
+ url=settings.RDM_UPLOADER_CLIENT_URL,
455
+ datamart_name=settings.RDM_UPLOADER_CLIENT_DATAMART_NAME,
456
+ timeout=settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT,
457
+ request_retries=settings.RDM_UPLOADER_CLIENT_REQUEST_RETRIES,
458
+ )
459
+ )
460
+
461
+ def upload_data(self, *args, **kwargs):
462
+ """
463
+ Запускает отправку данных в витрину.
464
+ """
465
+ try:
466
+ exporter = ExportEntityQueueSender(self.data_cache, self.queue, self.entities)
467
+ exporter.run()
468
+
469
+ sender = WorkerSender(self.queue)
470
+ sender.run()
471
+
472
+ except Exception as err:
473
+ logger.exception(err)
474
+ raise err
475
+ finally:
476
+ self._remove_file_handler()
@@ -1,10 +1,8 @@
1
- from datetime import (
2
- datetime,
3
- )
4
1
  from pathlib import (
5
2
  Path,
6
3
  )
7
4
  from typing import (
5
+ Iterable,
8
6
  List,
9
7
  )
10
8
 
@@ -13,6 +11,7 @@ from django.conf import (
13
11
  )
14
12
  from django.db.models import (
15
13
  F,
14
+ Q,
16
15
  Sum,
17
16
  )
18
17
  from django.db.transaction import (
@@ -83,10 +82,14 @@ class ExportQueueSender:
83
82
  return file_size or 0
84
83
 
85
84
  @staticmethod
86
- def get_sub_stages_attachments_to_export():
85
+ def _make_stage_filter(self) -> Q:
86
+ """Формирование фильтра для выборки подэтапов."""
87
+ return Q(status_id=ExportingDataSubStageStatus.READY_FOR_EXPORT.key)
88
+
89
+ def get_sub_stages_attachments_to_export(self):
87
90
  """Выборка готовых к экспорту подэтапов."""
88
91
  return ExportingDataSubStage.objects.filter(
89
- status_id=ExportingDataSubStageStatus.READY_FOR_EXPORT.key
92
+ self._make_stage_filter()
90
93
  ).annotate(
91
94
  attachment_id=F('exportingdatasubstageattachment__id'),
92
95
  attachment_name=F('exportingdatasubstageattachment__attachment'),
@@ -117,10 +120,14 @@ class ExportQueueSender:
117
120
  timeout=settings.RDM_REDIS_CACHE_TIMEOUT_SECONDS
118
121
  )
119
122
 
123
+ logger.info(
124
+ f'ExportedDataSubStage {sub_stage_id} {entity_name} added to the queue'
125
+ )
126
+
120
127
  return True
121
128
 
122
129
  def run(self):
123
- """Запуск работы менджера."""
130
+ """Запуск работы очереди."""
124
131
  if not self.queue_total_file_size:
125
132
  self.queue_total_file_size = self.get_exported_file_size()
126
133
 
@@ -133,9 +140,7 @@ class ExportQueueSender:
133
140
  if prev_sub_stage != stage_attachment['id']:
134
141
  if stage_files:
135
142
  to_cache = self.set_sub_stage_to_cache(prev_sub_stage, entity, stage_files)
136
- logger.info(
137
- f'ExportedDataSubStage {prev_sub_stage} {entity} added to the queue'
138
- )
143
+
139
144
  stage_files = []
140
145
 
141
146
  if not to_cache:
@@ -162,6 +167,25 @@ class ExportQueueSender:
162
167
  self.queue_total_file_size,
163
168
  timeout=settings.RDM_REDIS_CACHE_TIMEOUT_SECONDS
164
169
  )
170
+ logger.warning(
171
+ f'Total exported file size: {self.queue_total_file_size} - queue is full!!!'
172
+ )
173
+
174
+
175
+ class ExportEntityQueueSender(ExportQueueSender):
176
+ """Класс отправки данных по конкретной сущности в очередь РВД."""
177
+
178
+ def __init__(self, data_cache: AbstractCache, queue: Queue, entity: Iterable[str]):
179
+ super().__init__(data_cache, queue)
180
+
181
+ self.entity = entity
182
+
183
+ def _make_stage_filter(self) -> Q:
184
+ """Формирование фильтра для выборки подэтапов."""
185
+ return Q(
186
+ status_id=ExportingDataSubStageStatus.READY_FOR_EXPORT.key,
187
+ exportingdatasubstageentity__entity_id__in=self.entity
188
+ )
165
189
 
166
190
 
167
191
  class WorkerSender:
@@ -240,6 +264,9 @@ class WorkerSender:
240
264
  sub_stage.save()
241
265
 
242
266
  self.queue.delete_from_queue(sub_stage_id=sub_stage_id, entity_name=entity_key)
267
+ logger.info(
268
+ f'ExportedDataSubStage {sub_stage_id} {entity_key} sended from the queue'
269
+ )
243
270
 
244
271
  def run(self):
245
272
  """Запуск воркера отправки."""
@@ -10,8 +10,8 @@ from typing import (
10
10
  TYPE_CHECKING,
11
11
  Any,
12
12
  Dict,
13
- List,
14
13
  Iterable,
14
+ List,
15
15
  Optional,
16
16
  Tuple,
17
17
  Union,
@@ -33,16 +33,16 @@ from django.db.models.functions import (
33
33
  Cast,
34
34
  Least,
35
35
  )
36
+ from uploader_client.adapters import (
37
+ adapter,
38
+ )
36
39
 
37
40
  from educommon import (
38
41
  logger,
39
42
  )
40
- from uploader_client.adapters import (
41
- adapter,
42
- )
43
+
43
44
  from edu_rdm_integration.collect_and_export_data.models import (
44
- EduRdmCollectDataCommandProgress,
45
- EduRdmExportDataCommandProgress,
45
+ AbstractExportDataCommandProgress,
46
46
  )
47
47
  from edu_rdm_integration.enums import (
48
48
  FileUploadStatusEnum,
@@ -54,32 +54,35 @@ from edu_rdm_integration.export_data.consts import (
54
54
  TOTAL_ATTACHMENTS_SIZE_KEY,
55
55
  )
56
56
  from edu_rdm_integration.models import (
57
- DataMartRequestStatus,
58
- ExportingDataStage,
59
57
  CollectingDataStageStatus,
60
58
  CollectingExportedDataStage,
59
+ DataMartRequestStatus,
60
+ ExportingDataStage,
61
+ ExportingDataStageStatus,
61
62
  ExportingDataSubStageUploaderClientLog,
63
+ UploadDataCommand,
62
64
  UploadStatusRequestLog,
63
- ExportingDataStageStatus,
64
65
  )
65
66
  from edu_rdm_integration.redis_cache import (
66
67
  AbstractCache,
67
68
  )
68
69
 
70
+
69
71
  if TYPE_CHECKING:
70
72
  from datetime import (
71
73
  datetime,
72
74
  )
73
75
 
76
+ from uploader_client.models import (
77
+ Entry,
78
+ )
79
+
74
80
  from edu_rdm_integration.collect_data.non_calculated.base.managers import (
75
81
  BaseCollectingExportedDataRunnerManager,
76
82
  )
77
83
  from edu_rdm_integration.export_data.base.managers import (
78
84
  BaseExportDataRunnerManager,
79
85
  )
80
- from uploader_client.models import (
81
- Entry,
82
- )
83
86
 
84
87
 
85
88
  class UploadStatusHelper:
@@ -311,7 +314,7 @@ class Graph:
311
314
 
312
315
 
313
316
  def save_command_log_link(
314
- command: Union[EduRdmCollectDataCommandProgress, EduRdmExportDataCommandProgress],
317
+ command: Union[AbstractExportDataCommandProgress, UploadDataCommand],
315
318
  log_dir: str
316
319
  ) -> None:
317
320
  """Сохраняет ссылку на лог команды."""
@@ -0,0 +1,43 @@
1
+ # Generated by Django 3.1.14 on 2024-09-05 20:35
2
+
3
+ import uuid
4
+
5
+ import django.db.models.deletion
6
+ import django.utils.timezone
7
+ from django.db import (
8
+ migrations,
9
+ models,
10
+ )
11
+
12
+ import educommon.django.db.mixins
13
+
14
+ import edu_rdm_integration.utils
15
+
16
+
17
+ class Migration(migrations.Migration):
18
+
19
+ dependencies = [
20
+ ('async_task', '0002_task_type_and_status_data'),
21
+ ('edu_rdm_integration', '0013_set_attachment_size'),
22
+ ]
23
+
24
+ operations = [
25
+ migrations.CreateModel(
26
+ name='UploadDataCommand',
27
+ fields=[
28
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29
+ ('logs_link', models.FileField(max_length=255, upload_to=edu_rdm_integration.utils.get_data_command_progress_attachment_path, verbose_name='Ссылка на файл логов')),
30
+ ('type', models.PositiveSmallIntegerField(choices=[(1, 'Автоматический'), (2, 'Ручной')], verbose_name='Тип команды')),
31
+ ('created', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Дата создания')),
32
+ ('generation_id', models.UUIDField(default=uuid.uuid4, verbose_name='Идентификатор генерации')),
33
+ ('entity', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='edu_rdm_integration.regionaldatamartentityenum', verbose_name='Сущность РВД')),
34
+ ('task', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='async_task.runningtask', verbose_name='Асинхронная задача')),
35
+ ],
36
+ options={
37
+ 'verbose_name': 'Команда отправки данных в витрину',
38
+ 'verbose_name_plural': 'Команды отправки данных в витрину',
39
+ 'db_table': 'rdm_upload_data_command',
40
+ },
41
+ bases=(educommon.django.db.mixins.ReprStrPreModelMixin, models.Model),
42
+ ),
43
+ ]
@@ -26,6 +26,7 @@ from django.db.models import (
26
26
  Manager,
27
27
  OneToOneField,
28
28
  PositiveIntegerField,
29
+ PositiveSmallIntegerField,
29
30
  SmallIntegerField,
30
31
  UUIDField,
31
32
  )
@@ -65,12 +66,14 @@ from m3_db_utils.models import (
65
66
  )
66
67
 
67
68
  from edu_rdm_integration.enums import (
69
+ CommandType,
68
70
  FileUploadStatusEnum,
69
71
  )
70
72
  from edu_rdm_integration.uploader_log.managers import (
71
73
  UploaderClientLogManager,
72
74
  )
73
75
  from edu_rdm_integration.utils import (
76
+ get_data_command_progress_attachment_path,
74
77
  get_exporting_data_stage_attachment_path,
75
78
  )
76
79
 
@@ -150,6 +153,7 @@ class CollectingExportedDataStage(ReprStrPreModelMixin, BaseObjectModel):
150
153
 
151
154
  @property
152
155
  def attrs_for_repr_str(self):
156
+ """Список атрибутов для отображения экземпляра модели."""
153
157
  return ['manager_id', 'logs_period_started_at', 'logs_period_ended_at', 'started_at', 'ended_at', 'status_id']
154
158
 
155
159
  def save(self, *args, **kwargs):
@@ -245,6 +249,7 @@ class CollectingExportedDataSubStage(ReprStrPreModelMixin, BaseObjectModel):
245
249
 
246
250
  @property
247
251
  def attrs_for_repr_str(self):
252
+ """Список атрибутов для отображения экземпляра модели."""
248
253
  return ['stage_id', 'function_id', 'started_at', 'ended_at', 'previous_id', 'status_id']
249
254
 
250
255
  def save(self, *args, **kwargs):
@@ -335,6 +340,7 @@ class ExportingDataStage(ReprStrPreModelMixin, BaseObjectModel):
335
340
 
336
341
  @property
337
342
  def attrs_for_repr_str(self):
343
+ """Список атрибутов для отображения экземпляра модели."""
338
344
  return ['manager_id', 'started_at', 'ended_at', 'status_id']
339
345
 
340
346
  def save(self, *args, **kwargs):
@@ -421,9 +427,11 @@ class ExportingDataSubStage(ReprStrPreModelMixin, BaseObjectModel):
421
427
 
422
428
  @property
423
429
  def attrs_for_repr_str(self):
430
+ """Список атрибутов для отображения экземпляра модели."""
424
431
  return ['function_id', 'collecting_data_sub_stage_id', 'stage_id', 'started_at', 'ended_at', 'status_id']
425
432
 
426
433
  def save(self, *args, **kwargs):
434
+ """Сохранение экземпляра модели."""
427
435
  if (
428
436
  self.status_id in {
429
437
  ExportingDataSubStageStatus.FAILED.key,
@@ -487,6 +495,7 @@ class ExportingDataSubStageAttachment(ReprStrPreModelMixin, BaseObjectModel):
487
495
 
488
496
  @property
489
497
  def attrs_for_repr_str(self):
498
+ """Список атрибутов для отображения экземпляра модели."""
490
499
  return ['exporting_data_sub_stage_id', 'attachment', 'operation', 'created', 'modified']
491
500
 
492
501
 
@@ -675,6 +684,7 @@ class BaseEntityModel(ReprStrPreModelMixin, BaseObjectModel):
675
684
 
676
685
  @property
677
686
  def attrs_for_repr_str(self):
687
+ """Список атрибутов для отображения экземпляра модели."""
678
688
  return ['collecting_sub_stage', 'exporting_sub_stage', 'operation', 'created', 'modified']
679
689
 
680
690
  class Meta:
@@ -931,6 +941,7 @@ class TransferredEntity(BaseObjectModel):
931
941
 
932
942
  @json_encode
933
943
  def no_export(self):
944
+ """Формирует отображение признака отключения экспорта."""
934
945
  return 'Нет' if self.export_enabled else 'Да'
935
946
 
936
947
 
@@ -953,3 +964,42 @@ class ExportingDataSubStageEntity(BaseObjectModel):
953
964
  db_table = 'rdm_exporting_data_sub_stage_entity'
954
965
  verbose_name = 'Связь сущности и подэтапа выгрузки'
955
966
  verbose_name_plural = 'Связи сущности и подэтапа выгрузки'
967
+
968
+
969
+ class UploadDataCommand(ReprStrPreModelMixin, BaseObjectModel):
970
+ """Модель, хранящая данные для формирования и отслеживания асинхронной задачи по отправке данных в витрину."""
971
+
972
+ task = ForeignKey(
973
+ to='async_task.RunningTask',
974
+ verbose_name='Асинхронная задача',
975
+ blank=True,
976
+ null=True,
977
+ on_delete=SET_NULL,
978
+ )
979
+ logs_link = FileField(
980
+ upload_to=get_data_command_progress_attachment_path,
981
+ max_length=255,
982
+ verbose_name='Ссылка на файл логов',
983
+ )
984
+ type = PositiveSmallIntegerField( # noqa: A003
985
+ verbose_name='Тип команды',
986
+ choices=CommandType.get_choices(),
987
+ )
988
+ entity = ForeignKey(
989
+ to=RegionalDataMartEntityEnum,
990
+ verbose_name='Сущность РВД',
991
+ on_delete=PROTECT,
992
+ )
993
+ created = DateTimeField(
994
+ verbose_name='Дата создания',
995
+ default=timezone.now,
996
+ )
997
+ generation_id = UUIDField(
998
+ 'Идентификатор генерации',
999
+ default=uuid.uuid4,
1000
+ )
1001
+
1002
+ class Meta:
1003
+ db_table = 'rdm_upload_data_command'
1004
+ verbose_name = 'Команда отправки данных в витрину'
1005
+ verbose_name_plural = 'Команды отправки данных в витрину'
@@ -9,9 +9,6 @@ from typing import (
9
9
  )
10
10
 
11
11
  import celery
12
- from celery.exceptions import (
13
- Ignore,
14
- )
15
12
  from celery.schedules import (
16
13
  crontab,
17
14
  )
@@ -25,9 +22,6 @@ from django.utils import (
25
22
  timezone,
26
23
  )
27
24
 
28
- from educommon.async_task.locker import (
29
- TaskLocker,
30
- )
31
25
  from educommon.async_task.models import (
32
26
  AsyncTaskType,
33
27
  RunningTask,
@@ -64,10 +58,7 @@ from edu_rdm_integration.enums import (
64
58
  )
65
59
  from edu_rdm_integration.export_data.export import (
66
60
  ExportLatestEntitiesData,
67
- )
68
- from edu_rdm_integration.export_data.export_manger import (
69
- ExportQueueSender,
70
- WorkerSender,
61
+ UploadEntitiesData,
71
62
  )
72
63
  from edu_rdm_integration.export_data.helpers import (
73
64
  set_failed_status_suspended_exporting_data_stages,
@@ -85,6 +76,7 @@ from edu_rdm_integration.models import (
85
76
  ExportingDataSubStageUploaderClientLog,
86
77
  RegionalDataMartEntityEnum,
87
78
  TransferredEntity,
79
+ UploadDataCommand,
88
80
  )
89
81
  from edu_rdm_integration.storages import (
90
82
  RegionalDataMartEntityStorage,
@@ -352,8 +344,9 @@ class TransferLatestEntitiesDataPeriodicTask(UniquePeriodicAsyncTask):
352
344
  )
353
345
 
354
346
 
355
- class UploadDataAsyncTask(PeriodicAsyncTask):
347
+ class UploadDataAsyncTask(UniquePeriodicAsyncTask):
356
348
  """Формирование очереди файлов и их отправка."""
349
+
357
350
  queue = TASK_QUEUE_NAME
358
351
  routing_key = TASK_QUEUE_NAME
359
352
  description = 'Отправка данных в витрину "Региональная витрина данных"'
@@ -369,11 +362,31 @@ class UploadDataAsyncTask(PeriodicAsyncTask):
369
362
  """Выполнение."""
370
363
  super().process(*args, **kwargs)
371
364
 
365
+ entity_ids_for_export = list(
366
+ TransferredEntity.objects.filter(export_enabled=True).values_list('entity_id', flat=True)
367
+ )
372
368
  queue = RdmRedisSubStageAttachmentQueue()
373
- exporter = ExportQueueSender(cache, queue)
374
- exporter.run()
375
- sender = WorkerSender(queue)
376
- sender.run()
369
+ task_id = RunningTask.objects.filter(
370
+ pk=self.request.id,
371
+ ).values_list('pk', flat=True).first()
372
+
373
+ if task_id:
374
+ for entity_id in entity_ids_for_export:
375
+ upload_data_command = UploadDataCommand.objects.create(
376
+ entity_id=entity_id,
377
+ task_id=task_id,
378
+ type=CommandType.AUTO,
379
+ )
380
+ if upload_data_command:
381
+ upload_data = UploadEntitiesData(
382
+ entities=[upload_data_command.entity_id],
383
+ data_cache=cache,
384
+ queue=queue,
385
+ task_id=task_id,
386
+ command_id=upload_data_command.id,
387
+ )
388
+ upload_data.upload_data()
389
+ save_command_log_link(upload_data_command, settings.RDM_UPLOAD_LOG_DIR)
377
390
 
378
391
 
379
392
  celery_app = celery.app.app_or_default()
@@ -381,4 +394,3 @@ celery_app.register_task(RDMCheckUploadStatus)
381
394
  celery_app.register_task(CheckSuspendedExportedStagePeriodicTask)
382
395
  celery_app.register_task(TransferLatestEntitiesDataPeriodicTask)
383
396
  celery_app.register_task(UploadDataAsyncTask)
384
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edu-rdm-integration
3
- Version: 3.3.6
3
+ Version: 3.3.8
4
4
  Summary: Интеграция с Региональной витриной данных
5
5
  Home-page:
6
6
  Download-URL:
@@ -301,6 +301,20 @@ Requires-Dist: uploader-client <1,>=0.2.1
301
301
 
302
302
  ### Удалено
303
303
 
304
+
305
+ ## 3.3.8 - 2024-10-14
306
+ Задача UploadDataAsyncTask изменена с PeriodicAsyncTask на UploadDataAsyncTask
307
+ - [EDUSCHL-22519]https://jira.bars.group/browse/EDUSCHL-22519
308
+ PATCH Задача UploadDataAsyncTask изменена с PeriodicAsyncTask на UploadDataAsyncTask
309
+
310
+
311
+ ## 3.3.7 - 2024-09-06
312
+ Добавлены команда (UploadEntitiesData) и модель (UploadDataCommand) для логирования и запуска выгрузки данных в витрину
313
+ - [EDUSCHL-22042](https://jira.bars.group/browse/EDUSCHL-22042)
314
+ PATCH Добавлены команда (UploadEntitiesData) и модель (UploadDataCommand) для логирования и запуска выгрузки данных
315
+ в витрину
316
+
317
+
304
318
  ## 3.3.6 - 2024-09-02
305
319
  Добавлена фильтрация по дате выгрузки при обновлении данных на экспорт в BaseExportLatestEntitiesData
306
320
 
@@ -309,7 +323,6 @@ Requires-Dist: uploader-client <1,>=0.2.1
309
323
  PATCH Добавлена фильтрация по дате выгрузки при обновлении данных на экспорт в BaseExportLatestEntitiesData
310
324
 
311
325
 
312
-
313
326
  ## 3.3.5 - 2024-08-26
314
327
  Классы UniquePeriodicAsyncTask, PeriodicTaskLocker перенесены в educommon.
315
328
 
@@ -6,13 +6,13 @@ edu_rdm_integration/base.py,sha256=_G0qPTAXe6bXfgDHNiZMSsYt3sMuUhLKnHuQCWSFttU,1
6
6
  edu_rdm_integration/consts.py,sha256=Qt52SOCQ-3wOet-_6inJih_W9nToORKXbkxb3jVSjEo,1079
7
7
  edu_rdm_integration/entities.py,sha256=qNVWUhjwvX298Ak86_AKmqBZioP0czGwBcAz_4dtUUE,14552
8
8
  edu_rdm_integration/enums.py,sha256=T3Mu5D-CbKO3BSg16MPPnIPlcc_YGLYR-ThS8dzl9gg,4246
9
- edu_rdm_integration/helpers.py,sha256=m98k8nichw5AIoPuXNPsI-ZFN9OYX5Wt2MU6ml_pg88,14615
9
+ edu_rdm_integration/helpers.py,sha256=_zQb3vuMrWClpUErshYTI1aVgdKjXf819pHfBjaIty4,14592
10
10
  edu_rdm_integration/mapping.py,sha256=bwa2fJCbV4YjQcAgRrgT3hgM6dJhr_uBtQgx3L3F2Ck,473
11
- edu_rdm_integration/models.py,sha256=Fwt2O2j_aPI9owRZprreGQ2t7op-YmIYpZoq5HHjL3M,30692
11
+ edu_rdm_integration/models.py,sha256=YP_vot6PbQ3jWv3NNW1wa0gScjOsT2lgdrj7z5V6NHw,33053
12
12
  edu_rdm_integration/redis_cache.py,sha256=GZhtM1d0cVr5TEqxh15K7dS371Msit6wRemIiYb2rzk,1548
13
13
  edu_rdm_integration/signals.py,sha256=3eRlpkDcFCF6TN80-QM8yBYLcyozzcmoPjz6r4_ApWg,73
14
14
  edu_rdm_integration/storages.py,sha256=o5WqUG7SnkeuMt-z8spUi-IraivST-7KHzfY-M3v7FA,6807
15
- edu_rdm_integration/tasks.py,sha256=WolNe2t3_NCOisZeg24HyPI3Y0ciOJbwaFprhWgt41Q,15282
15
+ edu_rdm_integration/tasks.py,sha256=-YVApvlXdke5IYEBppU7M5_3bBYgIUqzxtZF976qIxM,16052
16
16
  edu_rdm_integration/utils.py,sha256=NIOxlH4JiTOOxYgqcwtfqT5UAtNG24GLq_tsnBUtp8E,10370
17
17
  edu_rdm_integration/adapters/__init__.py,sha256=cU0swn4Ny5ZQz5buWRcWsT1mpWuUFJaUlHf2l7TtEBo,83
18
18
  edu_rdm_integration/adapters/apps.py,sha256=TyJTkSPs2qAHJ11fqbwLGk3Ea7ujtqWwbxqmvYNQxG8,363
@@ -87,8 +87,8 @@ edu_rdm_integration/enum_register/register.py,sha256=5OWOjK-M0Erd_5CENpBaXhVtfL0
87
87
  edu_rdm_integration/export_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
88
  edu_rdm_integration/export_data/consts.py,sha256=rmJ_18wHCE54j0VABxfo7Zu01EPFYSjYrj5L79hVW2Y,333
89
89
  edu_rdm_integration/export_data/dataclasses.py,sha256=IhftRopP4lS-m3ygdBU5Bz0HF71VSBP4JQ6-8VIVgtY,260
90
- edu_rdm_integration/export_data/export.py,sha256=JZAgT8K49buRb57Pvt7iRkKW_fm7P4luZ4_umbsoY_E,16609
91
- edu_rdm_integration/export_data/export_manger.py,sha256=_8gkFH380zZVJ9LVxqeZOXphS-RjeIoSbq0eUbXnIMA,9657
90
+ edu_rdm_integration/export_data/export.py,sha256=xR2QRRL_HLD9MUIoe98Krc4KN0itWCpEl3uDM2tcqeE,18513
91
+ edu_rdm_integration/export_data/export_manger.py,sha256=lbXK3aV0Te0ZfJHylvCBZ0bJ7vWwD-pMQBX4Du8gPro,10681
92
92
  edu_rdm_integration/export_data/generators.py,sha256=yLDOcHB1PoilJwXtKGxZQhDjpeKBzEWoosahbJJ4Ba4,4020
93
93
  edu_rdm_integration/export_data/helpers.py,sha256=hU346RmQ17Ra2etFvxXI7JQlLyp_0KxH1jm-eeCqejc,2933
94
94
  edu_rdm_integration/export_data/queue.py,sha256=NiWm7e59zOcGT8s87BxiyU4-nA02fH94oVKnhc8htQ4,6159
@@ -162,6 +162,7 @@ edu_rdm_integration/migrations/0010_transferredentity_export_enabled.py,sha256=L
162
162
  edu_rdm_integration/migrations/0011_exportingdatasubstageentity.py,sha256=2BfIif_hkFv1h6VEfe0Ys4J_uk6LR9YtO711ocDYPso,1263
163
163
  edu_rdm_integration/migrations/0012_exportingdatasubstageattachment_attachment_size.py,sha256=y_JQO69k9pEfrJyimaRiAOBmhaJmssIyepCGd-Sy9hs,511
164
164
  edu_rdm_integration/migrations/0013_set_attachment_size.py,sha256=Pj_n-ytsC0lhyU67qvH8UHHQ-c-TH5MZFfy-UF6y6M4,1809
165
+ edu_rdm_integration/migrations/0014_uploaddatacommand.py,sha256=Hh0vKKiGgKOvY1kBAcmway4dSYUXwVArHAc9YrsjCIU,2079
165
166
  edu_rdm_integration/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
167
  edu_rdm_integration/registry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
168
  edu_rdm_integration/registry/actions.py,sha256=YUtCkpcc3DedM_x8rwJ6Aos-8HKkDCrOUdKnGhztfUU,5223
@@ -174,9 +175,9 @@ edu_rdm_integration/uploader_log/enums.py,sha256=rgSO3BL2rh2xpfm0Pt4waQW8fB1VMJL
174
175
  edu_rdm_integration/uploader_log/managers.py,sha256=y5wTSMzF9hpOpIU_A7nIafL_LBU3QEie6LAYWoB-pBQ,3203
175
176
  edu_rdm_integration/uploader_log/ui.py,sha256=YM9Buqp2wxE95Wf5gvAATBzuYzDOossK1sEmvFk07cI,2110
176
177
  edu_rdm_integration/uploader_log/templates/ui-js/object-grid-buttons.js,sha256=2xyGe0wdVokM0RhpzRzcRvJPBkBmPe3SlZry4oP4Nzs,6201
177
- edu_rdm_integration-3.3.6.dist-info/LICENSE,sha256=uw43Gjjj-1vXWCItfSrNDpbejnOwZMrNerUh8oWbq8Q,3458
178
- edu_rdm_integration-3.3.6.dist-info/METADATA,sha256=GF0r7I7EfNUKBqQ4USLovvZRvmn4gAJzDxG8KPeN81I,72243
179
- edu_rdm_integration-3.3.6.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
180
- edu_rdm_integration-3.3.6.dist-info/namespace_packages.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
181
- edu_rdm_integration-3.3.6.dist-info/top_level.txt,sha256=nRJV0O14UtNE-jGIYG03sohgFnZClvf57H5m6VBXe9Y,20
182
- edu_rdm_integration-3.3.6.dist-info/RECORD,,
178
+ edu_rdm_integration-3.3.8.dist-info/LICENSE,sha256=uw43Gjjj-1vXWCItfSrNDpbejnOwZMrNerUh8oWbq8Q,3458
179
+ edu_rdm_integration-3.3.8.dist-info/METADATA,sha256=LV7V-Iqbz2EZVVQAsflLPWVD08Ta7rCw4y0bZzNkPq4,73000
180
+ edu_rdm_integration-3.3.8.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
181
+ edu_rdm_integration-3.3.8.dist-info/namespace_packages.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
182
+ edu_rdm_integration-3.3.8.dist-info/top_level.txt,sha256=nRJV0O14UtNE-jGIYG03sohgFnZClvf57H5m6VBXe9Y,20
183
+ edu_rdm_integration-3.3.8.dist-info/RECORD,,