Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve harvesting scheduler #8184

Merged
merged 107 commits into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
f654111
Merge pull request #626 from geosolutions-it/merge_from_upsteram
giohappy Jan 20, 2021
0df9357
Merge branch 'master' of https://github.com/GeoNode/geonode
allyoucanmap Feb 1, 2021
2a11ead
Bump urllib3 from 1.26.2 to 1.26.3 (#6908)
dependabot[bot] Feb 2, 2021
040772e
[Fixes #6880] Circle CI upload tests fail irregulary (#6881)
t-book Feb 2, 2021
65c6267
[Fixes #6914] Remove "add to basket" tool for documents and maps (#6915)
Feb 2, 2021
158511a
Added malnajdi as contributor
t-book Feb 2, 2021
e9efc3d
[Fixes #6910] meaningful filename for document download (#6911)
gannebamm Feb 2, 2021
91f1a4e
- CircleCI Upload Tests: trying to reduce more the risk of infinite …
afabiani Feb 2, 2021
5e77b39
[Fixes #6916] gsimporter.api.NotFound caused by missing trailing slas…
malnajdi Feb 3, 2021
ec6d728
Bump django-cors-headers from 3.6.0 to 3.7.0 (#6901)
dependabot[bot] Feb 3, 2021
c5432b5
Bump amqp from 5.0.3 to 5.0.5 (#6905)
dependabot[bot] Feb 3, 2021
28424ca
Bump pip from 21.0 to 21.0.1 (#6900)
dependabot[bot] Feb 3, 2021
be313d5
Bump coverage from 5.3.1 to 5.4 (#6903)
dependabot[bot] Feb 3, 2021
f073274
Bump pytest from 6.2.1 to 6.2.2 (#6907)
dependabot[bot] Feb 3, 2021
9a3913e
Bump djangorestframework-gis from 0.16 to 0.17 (#6902)
dependabot[bot] Feb 3, 2021
ae6f6c1
- Algin setup.cfg to requirements.txt
afabiani Feb 3, 2021
0dad216
[Fixes #6922][REST API v2] Expose the curated thumbnail URL if it has…
Feb 3, 2021
30910b2
[Fixes #6918] Removal of QGIS support (#6919)
Feb 3, 2021
dbb4ac0
Merge branch 'master' of https://github.com/GeoNode/geonode
Feb 4, 2021
0bcf2fb
allow Basic authenticated requests in LOCKDOWN mode
bieganowski Feb 5, 2021
af22a3c
fix to avoid circular import
bieganowski Feb 5, 2021
c7ede4f
flake8 check fix
bieganowski Feb 5, 2021
b557f6d
added tests
bieganowski Feb 5, 2021
0a82a14
Merge pull request #652 from geosolutions-it/feature#650_basic_auth_m…
Feb 5, 2021
11f40ba
Merge pull request #678 from geosolutions-it/upstream_master
Feb 23, 2021
482080a
Merge remote-tracking branch 'upstream/master'
giohappy Mar 1, 2021
2f70532
Merge remote-tracking branch 'upstream/master'
giohappy Mar 2, 2021
de43e90
Merge branch 'master' of https://github.com/geosolutions-it/geonode
Mar 4, 2021
40408a3
Merge remote-tracking branch 'origin/master' into geosolutions-master
giohappy Mar 9, 2021
4ce20ab
Merge branch 'master' of https://github.com/GeoNode/geonode into geos…
afabiani Mar 12, 2021
2fd3272
[Fixes #6880] Circle CI upload tests fail irregulary (#6881)
t-book Feb 2, 2021
4539658
[Fixes #6914] Remove "add to basket" tool for documents and maps (#6915)
Feb 2, 2021
ba85f23
Added malnajdi as contributor
t-book Feb 2, 2021
e47daa6
Bump pip from 21.0 to 21.0.1 (#6900)
dependabot[bot] Feb 3, 2021
1346aeb
- Algin setup.cfg to requirements.txt
afabiani Feb 3, 2021
8ed0f4d
[Fixes #6922][REST API v2] Expose the curated thumbnail URL if it has…
Feb 3, 2021
65c7605
[Fixes #6918] Removal of QGIS support (#6919)
Feb 3, 2021
9af1c3b
allow Basic authenticated requests in LOCKDOWN mode
bieganowski Feb 5, 2021
97ed2c5
fix to avoid circular import
bieganowski Feb 5, 2021
ee282a2
- Align to upstream master branch
afabiani Mar 12, 2021
706ea43
Merge remote-tracking branch 'upstream/master'
giohappy Apr 22, 2021
711a619
Merge remote-tracking branch 'origin/master' into geosolutions-master
giohappy Apr 30, 2021
354764e
Merge remote-tracking branch 'origin/master' into geosolutions-master
giohappy May 11, 2021
e18bc6f
Merge branch 'master' of github.com:geosolutions-it/geonode
Jun 23, 2021
e5cf581
Merge branch 'master' of github.com:GeoNode/geonode
Jul 21, 2021
06d2930
Merge branch 'master' of github.com:GeoNode/geonode
Jul 22, 2021
3db74fc
Merge branch 'master' of github.com:GeoNode/geonode
Jul 28, 2021
5a65e39
Merge branch 'master' of github.com:GeoNode/geonode
Jul 28, 2021
dd6073e
Merge branch 'master' of github.com:GeoNode/geonode
Jul 29, 2021
0e4c038
Merge branch 'master' of github.com:GeoNode/geonode
Sep 7, 2021
a12c12b
Merge branch 'master' of github.com:GeoNode/geonode
Sep 28, 2021
43edc47
Merge branch 'master' of github.com:GeoNode/geonode
Sep 29, 2021
bd8de19
Merge branch 'master' of github.com:GeoNode/geonode
Sep 30, 2021
4fa8283
[Fixes #7945] Ingest harvested layer data to geonode
meomancer Aug 13, 2021
dd43d6c
Improve harvesting session and the admin
Sep 17, 2021
4edd83d
fix migration files conflict
Sep 21, 2021
51eb810
Initial work for implementing stoppable harvesting sessions
Sep 24, 2021
31f9370
Implement aborting of harvesting celery tasks
Sep 27, 2021
4f3c228
fix tests
Sep 29, 2021
28e25e9
fix conflicts
Sep 30, 2021
aa39ffd
Remove accidental duplication of code that crept in during conflict r…
Sep 30, 2021
9e1f59e
Add a couple more tests
Sep 30, 2021
e091f05
Update signature of get_resource method in WMS harvester worker
Sep 30, 2021
67eeb78
Add harvesting scheduler task
Sep 30, 2021
dd7ac84
Improving support for the harvesting scheduler task
Sep 30, 2021
6169cfe
Continue implementation of the harvesting scheduler task
Sep 30, 2021
4c1af01
Remove the dependency on `django-celery-beat`, as the harvesting does…
Sep 30, 2021
8359065
Uncomment `settings.py` line that designates the GeoNode test runner …
Sep 30, 2021
1b96d3b
Add harvesting scheduler task
Sep 30, 2021
8b30370
Improving support for the harvesting scheduler task
Sep 30, 2021
4107a13
Continue implementation of the harvesting scheduler task
Sep 30, 2021
8d50cf2
Remove the dependency on `django-celery-beat`, as the harvesting does…
Sep 30, 2021
c7b42c0
Revert "Remove the dependency on `django-celery-beat`, as the harvest…
Sep 30, 2021
822429e
Remove reference to the django-celery-beat app in the harvesting mode…
Sep 30, 2021
e0a4704
Implement different strategy for the harvesting scheduler
Oct 1, 2021
34a627c
Merge remote-tracking branch 'origin/improve-harvesting-scheduler' in…
Oct 1, 2021
ea6eaf7
Merge branch 'master' of github.com:GeoNode/geonode
Oct 1, 2021
9fa4131
[Fixes #7945] Ingest harvested layer data to geonode
meomancer Aug 13, 2021
194abcc
Improve harvesting session and the admin
Sep 17, 2021
f2c4df0
fix migration files conflict
Sep 21, 2021
64c7f7e
Initial work for implementing stoppable harvesting sessions
Sep 24, 2021
e4b417e
Implement aborting of harvesting celery tasks
Sep 27, 2021
5949e9f
fix tests
Sep 29, 2021
14f3e74
fix conflicts
Sep 30, 2021
1596fff
Remove accidental duplication of code that crept in during conflict r…
Sep 30, 2021
4998ddc
Add a couple more tests
Sep 30, 2021
5f37393
Uncomment `settings.py` line that designates the GeoNode test runner …
Sep 30, 2021
2eec96d
Add harvesting scheduler task
Sep 30, 2021
ecd279f
Improving support for the harvesting scheduler task
Sep 30, 2021
57c4b79
Continue implementation of the harvesting scheduler task
Sep 30, 2021
270d65e
Remove the dependency on `django-celery-beat`, as the harvesting does…
Sep 30, 2021
c981a85
Revert "Remove the dependency on `django-celery-beat`, as the harvest…
Sep 30, 2021
e4d960f
Remove reference to the django-celery-beat app in the harvesting mode…
Sep 30, 2021
b73b27a
Implement different strategy for the harvesting scheduler
Oct 1, 2021
39ee8ff
Add harvesting scheduler task
Sep 30, 2021
c8fcc6f
Improving support for the harvesting scheduler task
Sep 30, 2021
9360b9d
Continue implementation of the harvesting scheduler task
Sep 30, 2021
4b4433f
Remove the dependency on `django-celery-beat`, as the harvesting does…
Sep 30, 2021
d53f778
Rebase on top of master and fix some conflicts
Oct 1, 2021
80bd028
Merge branch 'master' into improve-harvesting-scheduler
ricardogsilva Oct 8, 2021
9715e2a
fix migration conflicts
Oct 8, 2021
6962b09
Fix broken pavement.py
Oct 8, 2021
b24f8a7
Fix invalid tiemporal computation after creating a new harvester
Oct 8, 2021
a049fdc
Merge branch 'master' into improve-harvesting-scheduler
ricardogsilva Oct 11, 2021
a553823
Add more tests
Oct 11, 2021
a1c4c20
Merge branch 'master' into improve-harvesting-scheduler
Oct 15, 2021
2a34de5
- Just making the tasks initialization coherent with the other modules
Oct 15, 2021
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
79 changes: 53 additions & 26 deletions geonode/harvesting/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
admin,
messages,
)
from django.contrib.humanize.templatetags import humanize
from django.urls import reverse
from django.utils.html import (
format_html,
Expand All @@ -50,11 +51,13 @@ class HarvesterAdmin(admin.ModelAdmin):
"scheduling_enabled",
"remote_available",
"get_num_harvestable_resources",
"get_num_harvestable_resources_selected",
"show_link_to_selected_harvestable_resources",
"show_link_to_latest_harvesting_session",
"show_link_to_latest_refresh_session",
"get_worker_specific_configuration",
"get_time_until_next_availability_update",
"get_time_until_next_refresh",
"get_time_until_next_harvesting",
)
list_filter = (
"status",
Expand Down Expand Up @@ -82,6 +85,7 @@ class HarvesterAdmin(admin.ModelAdmin):
"initiate_abort_update_harvestable_resources",
"initiate_perform_harvesting",
"initiate_abort_perform_harvesting",
"reset_harvester_status",
]

def save_model(self, request, harvester: models.Harvester, form, change):
Expand Down Expand Up @@ -208,15 +212,34 @@ def initiate_abort_perform_harvesting(self, request, queryset):
message = _("No active harvesting sessions have been found for the selected harvesters. Skipping...")
self.message_user(request, message)

@admin.display(description="Number of selected resources to harvest")
def get_num_harvestable_resources_selected(self, harvester: models.Harvester):
return harvester.harvestable_resources.filter(should_be_harvested=True).count()
@admin.action(description="Reset harvester status")
def reset_harvester_status(self, request, queryset):
for harvester in queryset:
if harvester.status != models.Harvester.STATUS_READY:
harvester.status = models.Harvester.STATUS_READY
harvester.save()
self.message_user(
request,
_("Resetting status for harvester %(name)s...") % {"name": harvester.name}
)

@admin.display(description="Updating availability in")
def get_time_until_next_availability_update(self, harvester: models.Harvester):
return humanize.naturaltime(harvester.get_next_check_availability_dispatch_time())

@admin.display(description="Refreshing harvestable resources in")
def get_time_until_next_refresh(self, harvester: models.Harvester):
return humanize.naturaltime(harvester.get_next_refresh_session_dispatch_time())

@admin.display(description="Performing harvesting in")
def get_time_until_next_harvesting(self, harvester: models.Harvester):
return humanize.naturaltime(harvester.get_next_harvesting_session_dispatch_time())

@admin.display(description="Number of existing harvestable resources")
@admin.display(description=_("Harvestable resources"))
def get_num_harvestable_resources(self, harvester: models.Harvester):
return harvester.num_harvestable_resources

@admin.display(description="current worker-specific configuration")
@admin.display(description="Worker-specific configuration")
def get_worker_specific_configuration(self, harvester: models.Harvester):
worker = harvester.get_harvester_worker()
worker_config = worker.get_current_config()
Expand All @@ -226,44 +249,48 @@ def get_worker_specific_configuration(self, harvester: models.Harvester):
result += "</ul>"
return mark_safe(result)

@admin.display(description="Go to selected harvestable resources")
@admin.display(description="Selected harvestable resources")
def show_link_to_selected_harvestable_resources(self, harvester: models.Harvester):
num_selected = models.HarvestableResource.objects.filter(
harvester=harvester, should_be_harvested=True).count()
if num_selected > 0:
changelist_uri = reverse("admin:harvesting_harvestableresource_changelist")
result = mark_safe(
format_html(
f'<a class="button grp-button" href="{changelist_uri}?harvester__id__exact={harvester.id}&should_be_harvested__exact=1">Go</a>'
f'<a class="button grp-button" href="{changelist_uri}?harvester__id__exact={harvester.id}&should_be_harvested__exact=1">({num_selected}) Go</a>'
)
)
else:
result = None
return result

@admin.display(description="Go to latest harvesting session")
@admin.display(description="Latest harvesting session")
def show_link_to_latest_harvesting_session(self, harvester: models.Harvester):
changelist_uri = reverse(
"admin:harvesting_asynchronousharvestingsession_change",
args=(harvester.latest_harvesting_session.id,)
)
return mark_safe(
format_html(
f'<a class="button grp-button" href="{changelist_uri}">Go</a>'
session = harvester.latest_harvesting_session
if session is not None:
changelist_uri = reverse(
"admin:harvesting_asynchronousharvestingsession_change",
args=(harvester.latest_harvesting_session.id,)
)
return mark_safe(
format_html(
f'<a class="button grp-button" href="{changelist_uri}">Go</a>'
)
)
)

@admin.display(description="Go to latest refresh session")
@admin.display(description="Latest refresh session")
def show_link_to_latest_refresh_session(self, harvester: models.Harvester):
changelist_uri = reverse(
"admin:harvesting_asynchronousharvestingsession_change",
args=(harvester.latest_refresh_session.id,)
)
return mark_safe(
format_html(
f'<a class="button grp-button" href="{changelist_uri}">Go</a>'
session = harvester.latest_refresh_session
if session is not None:
changelist_uri = reverse(
"admin:harvesting_asynchronousharvestingsession_change",
args=(harvester.latest_refresh_session.id,)
)
return mark_safe(
format_html(
f'<a class="button grp-button" href="{changelist_uri}">Go</a>'
)
)
)


@admin.register(models.AsynchronousHarvestingSession)
Expand Down
10 changes: 6 additions & 4 deletions geonode/harvesting/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ class Meta:
"remote_url",
"remote_available",
"scheduling_enabled",
"update_frequency",
"harvesting_session_update_frequency",
"refresh_harvestable_resources_update_frequency",
"check_availability_frequency",
"default_owner",
"links",
)
Expand Down Expand Up @@ -102,12 +104,12 @@ class Meta:
"remote_url",
"remote_available",
"scheduling_enabled",
"update_frequency",
"check_availability_frequency",
"harvesting_session_update_frequency",
"refresh_harvestable_resources_update_frequency",
"default_owner",
"harvester_type",
"harvester_type_specific_configuration",
"update_frequency",
"check_availability_frequency",
"last_checked_availability",
"last_checked_harvestable_resources",
"last_check_harvestable_resources_message",
Expand Down
42 changes: 41 additions & 1 deletion geonode/harvesting/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,57 @@
#########################################################################

from django.apps import AppConfig
from django.conf import settings
from django.conf.urls import url, include
from django.db.models.signals import post_migrate

from . import config


def run_setup_hooks(sender, **kwargs):
from django.utils import timezone

# Initialize periodic tasks
if 'django_celery_beat' in settings.INSTALLED_APPS and \
getattr(settings, 'CELERY_BEAT_SCHEDULER', None) == 'django_celery_beat.schedulers:DatabaseScheduler':
from django_celery_beat.models import (
IntervalSchedule,
PeriodicTask,
)

secs = config.get_setting("HARVESTER_SCHEDULER_FREQUENCY_MINUTES") * 60
check_intervals = IntervalSchedule.objects.filter(every=secs, period="seconds")
if not check_intervals.exists():
check_interval, _ = IntervalSchedule.objects.get_or_create(
every=secs,
period="seconds"
)
else:
check_interval = check_intervals.first()

PeriodicTask.objects.update_or_create(
name="harvesting-scheduler",
defaults=dict(
task="geonode.harvesting.tasks.harvesting_scheduler",
interval=check_interval,
args='',
start_time=timezone.now()
)
)


class HarvestingAppConfig(AppConfig):

name = "geonode.harvesting"

def ready(self):
from . import signals # noqa
from geonode.urls import urlpatterns

urlpatterns += [
url(r'^api/v2/', include('geonode.harvesting.api.urls'))
]
post_migrate.connect(run_setup_hooks, sender=self)
settings.CELERY_BEAT_SCHEDULE['harvesting-scheduler'] = {
"task": "geonode.harvesting.tasks.harvesting_scheduler",
"schedule": config.get_setting("HARVESTER_SCHEDULER_FREQUENCY_MINUTES") * 60,
}
3 changes: 2 additions & 1 deletion geonode/harvesting/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def get_setting(setting_key: str) -> typing.Any:
getattr(settings, "HARVESTER_CLASSES", [])
),
"HARVESTED_RESOURCE_FILE_MAX_MEMORY_SIZE": getattr(
settings, "HARVESTED_RESOURCE_MAX_MEMORY_SIZE", settings.FILE_UPLOAD_MAX_MEMORY_SIZE)
settings, "HARVESTED_RESOURCE_MAX_MEMORY_SIZE", settings.FILE_UPLOAD_MAX_MEMORY_SIZE),
"HARVESTER_SCHEDULER_FREQUENCY_MINUTES": getattr(settings, "HARVESTER_SCHEDULER_FREQUENCY_MINUTES", 0.5)
}.get(setting_key, getattr(settings, setting_key, None))
return result
2 changes: 0 additions & 2 deletions geonode/harvesting/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class Migration(migrations.Migration):
initial = True

dependencies = [
('django_celery_beat', '0015_edit_solarschedule_events_choices'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

Expand All @@ -27,7 +26,6 @@ class Migration(migrations.Migration):
('harvester_type', models.CharField(choices=[('geonode.harvesting.harvesters.geonode.GeonodeHarvester', 'geonode.harvesting.harvesters.geonode.GeonodeHarvester')], default='geonode.harvesting.harvesters.geonode.GeonodeHarvester', help_text='Harvester class used to perform harvesting sessions', max_length=255)),
('harvester_type_specific_configuration', models.JSONField(default=dict, help_text='Configuration specific to each harvester type. Please consult GeoNode documentation on harvesting for more info.')),
('default_owner', models.ForeignKey(help_text='Default owner of harvested resources', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('periodic_task', models.OneToOneField(blank=True, help_text='Periodic task used to configure harvest scheduling', null=True, on_delete=django.db.models.deletion.CASCADE, to='django_celery_beat.PeriodicTask')),
],
),
migrations.CreateModel(
Expand Down
5 changes: 0 additions & 5 deletions geonode/harvesting/migrations/0002_auto_20210415_1719.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ class Migration(migrations.Migration):
name='harvester_type',
field=models.CharField(choices=[('geonode.harvesting.harvesters.geonode.GeonodeHarvester', 'geonode.harvesting.harvesters.geonode.GeonodeHarvester')], default='geonode.harvesting.harvesters.geonode.GeonodeHarvester', help_text='Harvester class used to perform harvesting sessions. New harvester types can be added by an admin by changing the main GeoNode `settings.py` file', max_length=255),
),
migrations.AlterField(
model_name='harvester',
name='periodic_task',
field=models.OneToOneField(blank=True, editable=False, help_text='Periodic task used to configure harvest scheduling', null=True, on_delete=django.db.models.deletion.CASCADE, to='django_celery_beat.PeriodicTask'),
),
migrations.AlterField(
model_name='harvestingsession',
name='harvester',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@
class Migration(migrations.Migration):

dependencies = [
('django_celery_beat', '0015_edit_solarschedule_events_choices'),
('harvesting', '0005_auto_20210428_1100'),
]

operations = [
migrations.AddField(
model_name='harvester',
name='availability_check_task',
field=models.OneToOneField(blank=True, editable=False, help_text='Periodic task used to check availability of the remote', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checked_harvester', to='django_celery_beat.PeriodicTask'),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class Migration(migrations.Migration):

dependencies = [
('harvesting', '0036_alter_harvester_harvester_type'),
('harvesting', '0037_alter_harvester_name'),
]

operations = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class Migration(migrations.Migration):

dependencies = [
('harvesting', '0040_merge_20211001_0832'),
('harvesting', '0038_alter_harvester_status'),
]

operations = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class Migration(migrations.Migration):

dependencies = [
('harvesting', '0037_alter_harvester_status'),
('harvesting', '0039_harvestableresource_abstract'),
]

operations = [
Expand Down
14 changes: 0 additions & 14 deletions geonode/harvesting/migrations/0040_merge_20211001_0832.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class Migration(migrations.Migration):

dependencies = [
('harvesting', '0038_auto_20210927_1455'),
('harvesting', '0040_auto_20210927_1455'),
]

operations = [
Expand Down
28 changes: 28 additions & 0 deletions geonode/harvesting/migrations/0042_auto_20210930_1155.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.2.4 on 2021-09-30 11:55

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('harvesting', '0041_delete_harvestingsession'),
]

operations = [
migrations.AddField(
model_name='harvester',
name='refresh_harvestable_resources_update_frequency',
field=models.PositiveIntegerField(default=30, help_text='How often (in minutes) should new refresh sessions be automatically scheduled?'),
),
migrations.AlterField(
model_name='harvester',
name='check_availability_frequency',
field=models.PositiveIntegerField(default=10, help_text='How often (in minutes) should the remote service be checked for availability?'),
),
migrations.AlterField(
model_name='harvester',
name='update_frequency',
field=models.PositiveIntegerField(default=60, help_text='How often (in minutes) should new harvesting sessions be automatically scheduled?'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.4 on 2021-09-30 11:58

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('harvesting', '0042_auto_20210930_1155'),
]

operations = [
migrations.AddField(
model_name='harvester',
name='harvesting_session_update_frequency',
field=models.PositiveIntegerField(default=60, help_text='How often (in minutes) should new harvesting sessions be automatically scheduled?'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.2.4 on 2021-09-30 12:01

from django.db import migrations


def migrate_harvesting_session_update_frequency(apps, schema_editor):
harvester_model = apps.get_model("harvesting", "Harvester")
for harvester in harvester_model.objects.all():
harvester.harvesting_session_update_frequency = harvester.update_frequency
harvester.save()


class Migration(migrations.Migration):

dependencies = [
('harvesting', '0043_harvester_harvesting_session_update_frequency'),
]

operations = [
migrations.RunPython(migrate_harvesting_session_update_frequency, reverse_code=migrations.RunPython.noop),
]
Loading