archive: importing domains.yaml keeps domains which have archives

Archives create their domain (e.g. one uploaded, or found by a refresh, while WROLPi starts, before domains.yaml is
imported).  The import deleted every domain missing from the config, and the database deleted that domain's Archives
with it.  A domain with Archives is now kept (and saved to the config with the next change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Roland 2026-10-07 13:32:55 -06:00
parent 87d6d42136
commit f758191495
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
2 changed files with 46 additions and 4 deletions

View file

@ -153,12 +153,19 @@ class DomainsConfig(ConfigFile):
collections = Collection.batch_from_config(session, valid_data_list)
imported_domains = {c.name for c in collections}
# Delete domain collections that are no longer in config
# Delete domain collections that are no longer in config. A domain with Archives is kept: Archives
# create their domain (e.g. one downloaded before this import), and deleting it would delete them.
with_archives = {i for i, in session.query(Archive.collection_id).distinct()}
all_domain_collections = session.query(Collection).filter_by(kind='domain').all()
for collection in all_domain_collections:
if collection.name not in imported_domains:
logger.info(f'Deleting domain collection {repr(collection.name)} (no longer in config)')
session.delete(collection)
if collection.name in imported_domains:
continue
if collection.id in with_archives:
logger.warning(f'Keeping domain collection {repr(collection.name)} which is not in config,'
f' because it has archives')
continue
logger.info(f'Deleting domain collection {repr(collection.name)} (no longer in config)')
session.delete(collection)
logger.info(f'Successfully imported {len(imported_domains)} domain collections from {file_str}')
self.successful_import = True

View file

@ -296,3 +296,38 @@ async def test_domain_changes_wait_for_config_import(test_session: Session, test
domains_config.import_config()
request, response = await async_client.put(f'/api/collections/{did}', content=json.dumps(dict(description='x')))
assert response.status_code == HTTPStatus.OK, response.json
@pytest.mark.asyncio
async def test_import_keeps_domains_with_archives(test_session: Session, test_directory: pathlib.Path, async_client,
archive_factory):
"""A domain missing from domains.yaml is deleted by the import, unless it has Archives. Archives create their
domain (e.g. an upload or refresh while WROLPi starts, before domains.yaml is imported), and deleting it would
delete its Archives."""
from modules.archive.models import Archive
archive_factory(domain='kept.com', url='https://kept.com/1')
Collection.from_config(test_session, {'name': 'empty.com', 'kind': 'domain'})
test_session.commit()
domains_config.dump_config()
domains_config.successful_import = False
# Created before the import.
archive_factory(domain='new.com', url='https://new.com/1')
Collection.from_config(test_session, {'name': 'unused.com', 'kind': 'domain'})
test_session.commit()
assert test_session.query(Archive).count() == 2
domains_config.import_config()
test_session.expire_all()
assert {i.name for i in test_session.query(Collection)} == {'kept.com', 'empty.com', 'new.com'}
assert {i.collection.name for i in test_session.query(Archive)} == {'kept.com', 'new.com'}
assert domains_config.successful_import
# A domain with Archives which was removed from the config (by hand) is kept too.
config = yaml.safe_load(domains_config.get_file().read_text())
config['collections'] = [i for i in config['collections'] if i['name'] != 'kept.com']
domains_config.get_file().write_text(yaml.dump(config))
domains_config.import_config()
test_session.expire_all()
assert {i.name for i in test_session.query(Collection)} == {'kept.com', 'empty.com', 'new.com'}
assert test_session.query(Archive).count() == 2