Skip to content

Commit 544fa6c

Browse files
committed
introduce sync_in_migration
1 parent ee00199 commit 544fa6c

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

validity/migrations/0004_netbox35_scripts.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ def forward_func(apps, schema_editor):
1515
if config.netbox_version < "3.5.0":
1616
return
1717

18-
from core.models import DataSource
18+
from validity.models import VDataSource
1919
from extras.models import ScriptModule
2020

2121
db_alias = schema_editor.connection.alias
22-
data_source = DataSource.objects.using(db_alias).create(
22+
data_source = VDataSource.objects.using(db_alias).create(
2323
name=DATASOURCE_NAME, type="local", source_url="file://" + SCRIPTS_FOLDER, description=_("Required by Validity")
2424
)
25-
data_source.sync()
25+
DataFile = apps.get_model("core", "DataFile")
26+
data_source.sync_in_migration(DataFile)
2627
for data_file in data_source.datafiles.using(db_alias).all():
2728
if data_file.path.endswith("__init__.py") or data_file.path.endswith(".pyc"):
2829
continue

validity/migrations/0008_script_change.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212

1313
def forward_func(apps, schema_editor):
14-
from core.models import DataSource
14+
from validity.models import VDataSource
1515
from extras.models import ScriptModule
1616

17-
datasource, _ = DataSource.objects.get_or_create(
17+
DataFile = apps.get_model("core", "DataFile")
18+
datasource, _ = VDataSource.objects.get_or_create(
1819
name=DATASOURCE_NAME,
1920
type="local",
2021
defaults={"source_url": f"file://{SCRIPTS_INSTALL_FOLDER.parent}", "description": __("Required by Validity")},
@@ -23,7 +24,7 @@ def forward_func(apps, schema_editor):
2324
ScriptModule.objects.filter(data_source=datasource).delete()
2425
datasource.source_url = f"file://{SCRIPTS_INSTALL_FOLDER}"
2526
datasource.save()
26-
datasource.sync()
27+
datasource.sync_in_migration(DataFile)
2728
module = ScriptModule(
2829
data_source=datasource,
2930
data_file=datasource.datafiles.get(path=SCRIPT_NAME),

validity/models/data.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,43 @@ def _sync_status(self):
7272
DataSource.objects.filter(pk=self.pk).update(status=self.status, last_synced=self.last_synced)
7373
post_sync.send(sender=self.__class__, instance=self)
7474

75-
def partial_sync(self, device_filter: Q, batch_size: int = 1000) -> None:
75+
def partial_sync(self, device_filter: Q, batch_size: int = 1000) -> set[str]:
7676
def update_batch(batch):
7777
for datafile in self.datafiles.filter(path__in=batch).iterator():
7878
if datafile.refresh_from_disk(local_path):
7979
yield datafile
80-
paths.discard(datafile.path)
80+
updated_paths.add(datafile.path)
8181

8282
def new_data_file(path):
8383
df = DataFile(source=self, path=path)
8484
df.refresh_from_disk(local_path)
8585
df.full_clean()
8686
return df
8787

88-
if self.type != "device_polling":
89-
raise SyncError("Partial sync is available only for Data Source with type Device Polling")
9088
backend = self.get_backend()
91-
with backend.fetch(device_filter) as local_path, self._sync_status():
92-
paths = self._walk(local_path)
89+
fetch = backend.fetch(device_filter) if self.type == "device_polling" else backend.fetch()
90+
with fetch as local_path, self._sync_status():
91+
all_new_paths = self._walk(local_path)
92+
updated_paths = set()
9393
datafiles_to_update = chain.from_iterable(
94-
update_batch(path_batch) for path_batch in batched(paths, batch_size)
94+
update_batch(path_batch) for path_batch in batched(all_new_paths, batch_size)
9595
)
9696
updated = DataFile.objects.bulk_update(
9797
datafiles_to_update, batch_size=batch_size, fields=("last_updated", "size", "hash", "data")
9898
)
99-
new_datafiles = (new_data_file(path) for path in paths)
99+
new_datafiles = (new_data_file(path) for path in all_new_paths - updated_paths)
100100
created = len(DataFile.objects.bulk_create(new_datafiles, batch_size=batch_size))
101101
logger.debug("%s new files were created and %s existing files were updated during sync", created, updated)
102+
return all_new_paths
102103

103104
def sync(self, device_filter: Q | None = None):
104-
if device_filter is not None and self.type == "device_polling":
105-
return self.partial_sync(device_filter)
106-
return super().sync()
105+
if device_filter is None or self.type != "device_polling":
106+
return super().sync()
107+
self.partial_sync(device_filter)
108+
109+
def sync_in_migration(self, datafile_model: type):
110+
"""
111+
This method performs sync and avoids problems with historical models which have reference to DataFile
112+
"""
113+
new_paths = self.partial_sync(Q())
114+
datafile_model.objects.exclude(path__in=new_paths).delete()

0 commit comments

Comments
 (0)