Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ofrak_core/ofrak/model/resource_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ def __init__(
self.is_deleted = False
self._diff: Optional[ResourceModelDiff] = None

def __hash__(self):
return self.id.__hash__()

@property
def diff(self):
if not self._diff:
Expand Down
28 changes: 16 additions & 12 deletions ofrak_core/ofrak/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,12 @@ async def save(self):
self._resource_view_context,
)

def _save(
self,
resources_to_delete: List[bytes],
patches_to_apply: List[DataPatch],
resources_to_update: List[MutableResourceModel],
):
def _save(self) -> Tuple[List[bytes], List[DataPatch], List[MutableResourceModel]]:

resources_to_delete: List[bytes] = []
patches_to_apply: List[DataPatch] = []
resources_to_update: List[MutableResourceModel] = []

if self._resource.is_deleted:
resources_to_delete.append(self._resource.id)
elif self._resource.is_modified:
Expand All @@ -316,6 +316,8 @@ def _save(
resources_to_update.append(self._resource)
modification_tracker.data_patches.clear()

return resources_to_delete, patches_to_apply, resources_to_update

async def _fetch(self, resource: MutableResourceModel):
"""
Update the local model with the latest version from the resource service. This will fail
Expand Down Expand Up @@ -1543,19 +1545,21 @@ async def save_resources(
resources_to_update: List[MutableResourceModel] = []

for resource in resources:
resource._save(
resources_to_delete,
patches_to_apply,
resources_to_update,
)
_resources_to_delete, _patches_to_apply, _resources_to_update = resource._save()

resources_to_delete.extend(_resources_to_delete)
patches_to_apply.extend(_patches_to_apply)
resources_to_update.extend(_resources_to_update)

deleted_descendants = await resource_service.delete_resources(resources_to_delete)
data_ids_to_delete = [
resource_m.data_id for resource_m in deleted_descendants if resource_m.data_id is not None
]
await data_service.delete_models(data_ids_to_delete)
patch_results = await data_service.apply_patches(patches_to_apply)
await dependency_handler.handle_post_patch_dependencies(patch_results)
resources_to_update.extend(
await dependency_handler.handle_post_patch_dependencies(patch_results)
)
diffs = []
updated_ids = []
for resource_m in resources_to_update:
Expand Down
17 changes: 14 additions & 3 deletions ofrak_core/ofrak/service/dependency_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ async def map_data_ids_to_resources(

return resources_by_data_id

async def handle_post_patch_dependencies(self, patch_results: List[DataPatchesResult]):
async def handle_post_patch_dependencies(
self, patch_results: List[DataPatchesResult]
) -> Set[MutableResourceModel]:
modified_resources = set()

# Create look up maps for resources and dependencies
resources_by_data_id = await self.map_data_ids_to_resources(
patch_result.data_id for patch_result in patch_results
Expand All @@ -78,6 +82,7 @@ async def handle_post_patch_dependencies(self, patch_results: List[DataPatchesRe
resource_m = resources_by_data_id[data_patch_result.data_id]
data_m = models_by_data_id[data_patch_result.data_id]
resource_m.add_attributes(Data(data_m.range.start, data_m.range.length()))
modified_resources.add(resource_m)

unhandled_dependencies: Set[ResourceAttributeDependency] = set()
# Figure out which components results must be invalidated based on data changes
Expand Down Expand Up @@ -109,15 +114,17 @@ async def handle_post_patch_dependencies(self, patch_results: List[DataPatchesRe
break
for removed_data_dependency in removed_data_dependencies:
resource_m.remove_dependency(removed_data_dependency)
modified_resources.add(resource_m)

# Recursively invalidate component results based on other components that were invalidated
handled_dependencies: Set[ResourceAttributeDependency] = set()

await self._invalidate_dependencies(
handled_dependencies,
unhandled_dependencies,
handled_dependencies, unhandled_dependencies, modified_resources
)

return modified_resources

def create_component_dependencies(
self,
component_id: bytes,
Expand Down Expand Up @@ -224,6 +231,7 @@ async def _invalidate_dependencies(
self,
handled_dependencies: Set[ResourceAttributeDependency],
unhandled_dependencies: Set[ResourceAttributeDependency],
resources_modified: Set[MutableResourceModel],
):
"""
Invalidate the unhandled resource attribute dependencies.
Expand Down Expand Up @@ -282,6 +290,7 @@ async def _invalidate_dependencies(
if resource_m.get_component_id_by_attributes(dependency.attributes):
resource_m.remove_component(dependency.component_id, dependency.attributes)
self._component_context.mark_resource_modified(resource_m.id)
resources_modified.add(resource_m)

# Find other dependencies to invalidate due to the invalidation of the attributes
invalidated_dependencies = set()
Expand All @@ -301,11 +310,13 @@ async def _invalidate_dependencies(
for invalidated_dependency in invalidated_dependencies:
resource_m.remove_dependency(invalidated_dependency)
self._component_context.mark_resource_modified(resource_m.id)
resources_modified.add(resource_m)
next_unhandled_dependencies.update(invalidated_dependencies)

await self._invalidate_dependencies(
handled_dependencies,
next_unhandled_dependencies,
resources_modified,
)


Expand Down