R: Refactoring caches pt3

This commit is contained in:
Ivan 2025-11-09 13:47:16 +03:00
parent 0242cd5c20
commit 9e409c14f0
7 changed files with 52 additions and 49 deletions

View File

@ -55,7 +55,7 @@ class OperationSchemaCached:
inheritance_to_delete: list[Inheritance] = []
for child_id in children:
child_operation = self.cache.operation_by_id[child_id]
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
if child_schema is None:
continue
self.engine.undo_substitutions_cst(ids, child_operation, child_schema)
@ -72,7 +72,7 @@ class OperationSchemaCached:
''' Set input schema for operation. '''
operation = self.cache.operation_by_id[target]
has_children = bool(self.cache.extend_graph.outputs[target])
old_schema = self.cache.get_schema(operation)
old_schema = self.cache.get_result(operation)
if schema is None and old_schema is None or \
(schema is not None and old_schema is not None and schema.pk == old_schema.pk):
return
@ -90,8 +90,8 @@ class OperationSchemaCached:
operation.save(update_fields=['alias', 'title', 'description'])
if schema is not None and has_children:
rsform = self.context.get_schema(schema.pk)
self.after_create_cst(rsform, list(rsform.constituentsQ().order_by('order')))
cst_list = list(Constituenta.objects.filter(schema_id=schema.pk).order_by('order'))
self.after_create_cst(schema.pk, cst_list)
def set_arguments(self, target: int, arguments: list[Operation]) -> None:
''' Set arguments of target Operation. '''
@ -128,7 +128,7 @@ class OperationSchemaCached:
''' Clear all arguments for target Operation. '''
self.cache.ensure_loaded_subs()
operation = self.cache.operation_by_id[target]
schema = self.cache.get_schema(operation)
schema = self.cache.get_result(operation)
processed: list[dict] = []
deleted: list[Substitution] = []
for current in operation.getQ_substitutions():
@ -207,26 +207,30 @@ class OperationSchemaCached:
if self.cache.extend_graph.outputs[operation.pk]:
receiver_items = list(Constituenta.objects.filter(schema_id=receiver.pk).order_by('order'))
self.after_create_cst(receiver, receiver_items)
self.after_create_cst(receiver.pk, receiver_items)
return True
def relocate_down(self, destination: RSFormCached, items: list[int]):
def relocate_down(self, destinationID: int, items: list[int]):
''' Move list of Constituents to destination Schema inheritor. '''
self.cache.ensure_loaded_subs()
operation = self.cache.get_operation(destination.pk)
operation = self.cache.get_operation(destinationID)
destination = self.context.get_schema(destinationID)
self.engine.undo_substitutions_cst(items, operation, destination)
inheritance_to_delete = [item for item in self.cache.inheritance[operation.pk] if item.parent_id in items]
for item in inheritance_to_delete:
self.cache.remove_inheritance(item)
Inheritance.objects.filter(operation_id=operation.pk, parent_id__in=items).delete()
def relocate_up(self, source: RSFormCached, destination: RSFormCached,
def relocate_up(self, sourceID: int, destinationID: int,
item_ids: list[int]) -> list[Constituenta]:
''' Move list of Constituents upstream to destination Schema. '''
self.cache.ensure_loaded_subs()
operation = self.cache.get_operation(source.pk)
source = self.context.get_schema(sourceID)
destination = self.context.get_schema(destinationID)
operation = self.cache.get_operation(sourceID)
alias_mapping: dict[str, str] = {}
for item in self.cache.inheritance[operation.pk]:
if item.parent_id in destination.cache.by_id:
@ -234,7 +238,7 @@ class OperationSchemaCached:
destination_cst = destination.cache.by_id[item.parent_id]
alias_mapping[source_cst.alias] = destination_cst.alias
new_items = destination.insert_from(source.pk, item_ids, alias_mapping)
new_items = destination.insert_from(sourceID, item_ids, alias_mapping)
for (cst, new_cst) in new_items:
new_inheritance = Inheritance.objects.create(
operation=operation,
@ -243,15 +247,16 @@ class OperationSchemaCached:
)
self.cache.insert_inheritance(new_inheritance)
new_constituents = [item[1] for item in new_items]
self.after_create_cst(destination, new_constituents, exclude=[operation.pk])
self.after_create_cst(destinationID, new_constituents, exclude=[operation.pk])
return new_constituents
def after_create_cst(
self, source: RSFormCached,
self, sourceID: int,
cst_list: list[Constituenta],
exclude: Optional[list[int]] = None
) -> None:
''' Trigger cascade resolutions when new Constituenta is created. '''
source = self.context.get_schema(sourceID)
alias_mapping = create_dependant_mapping(source, cst_list)
operation = self.cache.get_operation(source.pk)
self.engine.on_inherit_cst(operation.pk, source, cst_list, alias_mapping, exclude)
@ -261,9 +266,10 @@ class OperationSchemaCached:
operation = self.cache.get_operation(schemaID)
self.engine.on_change_cst_type(operation.pk, target, new_type)
def after_update_cst(self, source: RSFormCached, target: int, data: dict, old_data: dict) -> None:
def after_update_cst(self, sourceID: int, target: int, data: dict, old_data: dict) -> None:
''' Trigger cascade resolutions when Constituenta data is changed. '''
operation = self.cache.get_operation(source.pk)
operation = self.cache.get_operation(sourceID)
source = self.context.get_schema(sourceID)
depend_aliases = extract_data_references(data, old_data)
alias_mapping: CstMapping = {}
for alias in depend_aliases:
@ -293,18 +299,18 @@ class OperationSchemaCached:
if target.result_id is None:
return
for argument in arguments:
parent_schema = self.cache.get_schema(argument)
if parent_schema is not None:
parent_schema = self.cache.get_result(argument)
if parent_schema:
self.engine.delete_inherited(target.pk, [cst.pk for cst in parent_schema.cache.constituents])
def after_create_arguments(self, target: Operation, arguments: list[Operation]) -> None:
''' Trigger cascade resolutions after arguments are created. '''
schema = self.cache.get_schema(target)
if schema is None:
schema = self.cache.get_result(target)
if not schema:
return
for argument in arguments:
parent_schema = self.cache.get_schema(argument)
if parent_schema is None:
parent_schema = self.cache.get_result(argument)
if not parent_schema:
continue
self.engine.inherit_cst(
target_operation=target.pk,

View File

@ -60,7 +60,7 @@ class OssCache:
'operation_id', 'parent_id', 'child_id'):
self.inheritance[item.operation_id].append(item)
def get_schema(self, operation: Operation) -> Optional[RSFormCached]:
def get_result(self, operation: Operation) -> Optional[RSFormCached]:
''' Get schema by Operation. '''
if operation.result_id is None:
return None

View File

@ -37,7 +37,7 @@ class PropagationEngine:
successor_id = self.cache.get_inheritor(cst_id, child_id)
if successor_id is None:
continue
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
if child_schema is None:
continue
if child_schema.change_cst_type(successor_id, ctype):
@ -69,7 +69,7 @@ class PropagationEngine:
) -> None:
''' Execute inheritance of Constituenta. '''
operation = self.cache.operation_by_id[target_operation]
destination = self.cache.get_schema(operation)
destination = self.cache.get_result(operation)
if destination is None:
return
@ -106,7 +106,7 @@ class PropagationEngine:
successor_id = self.cache.get_inheritor(cst_id, child_id)
if successor_id is None:
continue
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
assert child_schema is not None
new_mapping = self._transform_mapping(mapping, child_operation, child_schema)
alias_mapping = cst_mapping_to_alias(new_mapping)
@ -178,7 +178,7 @@ class PropagationEngine:
self.cache.ensure_loaded_subs()
for child_id in children:
child_operation = self.cache.operation_by_id[child_id]
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
if child_schema is None:
continue
new_substitutions = self._transform_substitutions(substitutions, child_id, child_schema)
@ -195,7 +195,7 @@ class PropagationEngine:
self.cache.ensure_loaded_subs()
for child_id in children:
child_operation = self.cache.operation_by_id[child_id]
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
if child_schema is None:
continue
@ -227,7 +227,7 @@ class PropagationEngine:
def delete_inherited(self, operationID: int, parents: list[int]) -> None:
''' Execute deletion of Constituenta inheritance. '''
operation = self.cache.operation_by_id[operationID]
schema = self.cache.get_schema(operation)
schema = self.cache.get_result(operation)
if schema is None:
return
self.undo_substitutions_cst(parents, operation, schema)
@ -376,7 +376,7 @@ class PropagationEngine:
self.cache.ensure_loaded_subs()
for child_id in children:
child_operation = self.cache.operation_by_id[child_id]
child_schema = self.cache.get_schema(child_operation)
child_schema = self.cache.get_result(child_operation)
if child_schema is None:
continue
new_mapping = self._transform_mapping(mapping, child_operation, child_schema)

View File

@ -10,7 +10,7 @@ from .PropagationContext import PropagationContext
def _get_oss_hosts(schemaID: int) -> list[int]:
''' Get all hosts for schema. '''
return list(LibraryItem.objects.filter(operations__result_id=schemaID).values_list('pk', flat=True))
return list(LibraryItem.objects.filter(operations__result_id=schemaID).distinct().values_list('pk', flat=True))
class PropagationFacade:
@ -30,14 +30,13 @@ class PropagationFacade:
''' Get RSFormCached for schemaID. '''
return self._context.get_schema(schemaID)
def reset_cache(self) -> None:
''' Reset cache. '''
self._oss = {}
def after_create_cst(self, source: RSFormCached, new_cst: list[Constituenta],
def after_create_cst(self, new_cst: list[Constituenta],
exclude: Optional[list[int]] = None) -> None:
''' Trigger cascade resolutions when new constituenta is created. '''
hosts = _get_oss_hosts(source.pk)
if not new_cst:
return
source = new_cst[0].schema_id
hosts = _get_oss_hosts(source)
for host in hosts:
if exclude is None or host not in exclude:
self.get_oss(host).after_create_cst(source, new_cst)
@ -52,15 +51,15 @@ class PropagationFacade:
# pylint: disable=too-many-arguments, too-many-positional-arguments
def after_update_cst(
self, source: RSFormCached, target: int,
self, sourceID: int, target: int,
data: dict, old_data: dict,
exclude: Optional[list[int]] = None
) -> None:
''' Trigger cascade resolutions when constituenta data is changed. '''
hosts = _get_oss_hosts(source.pk)
hosts = _get_oss_hosts(sourceID)
for host in hosts:
if exclude is None or host not in exclude:
self.get_oss(host).after_update_cst(source, target, data, old_data)
self.get_oss(host).after_update_cst(sourceID, target, data, old_data)
def before_delete_cst(self, sourceID: int, target: list[int],
exclude: Optional[list[int]] = None) -> None:

View File

@ -609,8 +609,6 @@ class RelocateConstituentsSerializer(StrictSerializer):
attrs['destination'] = attrs['destination'].id
attrs['source'] = attrs['items'][0].schema_id
# TODO: check permissions for editing source and destination
if attrs['source'] == attrs['destination']:
raise serializers.ValidationError({
'destination': msg.sourceEqualDestination()

View File

@ -837,19 +837,19 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
ids = [cst.pk for cst in data['items']]
destinationID = data['destination']
with transaction.atomic():
propagation = m.PropagationFacade()
oss = propagation.get_oss(item.pk)
source = propagation.get_schema(data['source'])
destination = propagation.get_schema(data['destination'])
if data['move_down']:
oss.relocate_down(destination, ids)
oss.relocate_down(destinationID, ids)
propagation.before_delete_cst(source.pk, ids)
source.delete_cst(ids)
else:
new_items = oss.relocate_up(source, destination, ids)
propagation.after_create_cst(destination, new_items, exclude=[oss.pk])
new_items = oss.relocate_up(source.pk, destinationID, ids)
propagation.after_create_cst(new_items, exclude=[oss.pk])
item.save(update_fields=['time_update'])
return Response(status=c.HTTP_200_OK)

View File

@ -94,7 +94,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
propagation = PropagationFacade()
schema = propagation.get_schema(item.pk)
new_cst = schema.create_cst(data, insert_after)
propagation.after_create_cst(schema, [new_cst])
propagation.after_create_cst([new_cst])
item.save(update_fields=['time_update'])
return Response(
@ -129,7 +129,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
propagation = PropagationFacade()
schema = propagation.get_schema(item.pk)
old_data = schema.update_cst(cst.pk, data)
propagation.after_update_cst(schema, cst.pk, data, old_data)
propagation.after_update_cst(item.pk, cst.pk, data, old_data)
if 'alias' in data and data['alias'] != cst.alias:
cst.refresh_from_db()
changed_type = 'cst_type' in data and cst.cst_type != data['cst_type']
@ -213,7 +213,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
propagation = PropagationFacade()
schema = propagation.get_schema(item.pk)
new_cst = schema.produce_structure(cst, cst_parse)
propagation.after_create_cst(schema, new_cst)
propagation.after_create_cst(new_cst)
item.save(update_fields=['time_update'])
return Response(
status=c.HTTP_200_OK,
@ -745,7 +745,7 @@ def inline_synthesis(request: Request) -> HttpResponse:
new_items = receiver.insert_from(source.pk, target_ids)
target_ids = [item[0].pk for item in new_items]
mapping_ids = {cst.pk: new_cst for (cst, new_cst) in new_items}
propagation.after_create_cst(receiver, [item[1] for item in new_items])
propagation.after_create_cst([item[1] for item in new_items])
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
for substitution in serializer.validated_data['substitutions']: