Skip to content

Commit bade777

Browse files
fredrikhlGitHub Enterprise
authored andcommitted
Merge pull request #37 from IT-CEREBRUM/CRB-3996-greg-import-setting
CRB-3996: GREG_IMPORT setting
2 parents 274bdb5 + 7a2d01e commit bade777

File tree

8 files changed

+140
-58
lines changed

8 files changed

+140
-58
lines changed

Cerebrum/modules/greg/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright 2021 University of Oslo, Norway
3+
# Copyright 2021-2023 University of Oslo, Norway
44
#
55
# This file is part of Cerebrum.
66
#
@@ -43,7 +43,11 @@
4343
Configuration
4444
-------------
4545
46-
cereconf.CLASS_CONSTANTS
46+
``cereconf.CLASS_CONSTANTS``
4747
Must include ``Cerebrum.modules.greg.constants/GregConstants``, to provide
4848
Greg-related constants.
49+
50+
``cereconf.GREG_IMPORT``
51+
Can be used to override the default
52+
``Cerebrum.modules.greg.importer/GregImporter`` class in scripts.
4953
"""

Cerebrum/modules/greg/importer.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright 2021 University of Oslo, Norway
3+
# Copyright 2021-2023 University of Oslo, Norway
44
#
55
# This file is part of Cerebrum.
66
#
@@ -17,7 +17,9 @@
1717
# You should have received a copy of the GNU General Public License
1818
# along with Cerebrum; if not, write to the Free Software Foundation,
1919
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20-
""" Greg person import/update. """
20+
"""
21+
Greg person import/update.
22+
"""
2123
from __future__ import (
2224
absolute_import,
2325
division,
@@ -27,6 +29,8 @@
2729
import logging
2830
import datetime
2931

32+
import cereconf
33+
3034
from Cerebrum.Utils import Factory
3135
from Cerebrum.modules.import_utils.matcher import (
3236
OuMatcher,
@@ -39,14 +43,30 @@
3943
PersonNameSync,
4044
)
4145
from Cerebrum.utils import date_compat
46+
from Cerebrum.utils.module import resolve
4247

43-
from .consent import sync_greg_consent
4448
from .datasource import GregDatasource
4549
from .mapper import GregMapper
4650

4751
logger = logging.getLogger(__name__)
4852

4953

54+
def get_import_class(cereconf=cereconf):
55+
"""
56+
Get preferred import class from config module/object *cereconf*.
57+
58+
TODO: Or should we re-factor the greg client config into a full greg
59+
config, with import class and everything?
60+
"""
61+
import_spec = getattr(cereconf, 'GREG_IMPORT', None)
62+
if import_spec:
63+
cls = resolve(import_spec)
64+
else:
65+
cls = GregImporter
66+
logger.info("greg import class=%s", repr(cls))
67+
return cls
68+
69+
5070
class GregImporter(object):
5171

5272
REQUIRED_PERSON_ID = (
@@ -58,9 +78,9 @@ class GregImporter(object):
5878
'GREG_PID',
5979
)
6080

61-
CONSENT_GROUPS = {
62-
'greg-publish': sync_greg_consent,
63-
}
81+
# Map consent name to
82+
# `Cerebrum.modules.import_utils.group.GroupMembershipSetter`
83+
CONSENT_GROUPS = {}
6484

6585
mapper = GregMapper()
6686

Cerebrum/modules/greg/tasks.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright 2021 University of Oslo, Norway
3+
# Copyright 2021-2023 University of Oslo, Norway
44
#
55
# This file is part of Cerebrum.
66
#
@@ -19,7 +19,6 @@
1919
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
2020
"""
2121
Tasks related to the Greg guest import.
22-
2322
"""
2423
import logging
2524

@@ -33,12 +32,32 @@
3332

3433

3534
class GregImportTasks(queue_handler.QueueHandler):
36-
""" This object defines the 'greg-guest' tasks queue. """
35+
""" This object defines the 'greg-person' task queues. """
3736

3837
queue = 'greg-person'
3938
manual_sub = 'manual'
4039
max_attempts = 20
4140

41+
def __init__(self, client, import_class):
42+
self._client = client
43+
self._import_class = import_class
44+
45+
def _callback(self, db, task):
46+
greg_id = task.key
47+
logger.info('Updating greg_id=%s', greg_id)
48+
importer = self._import_class(db, client=self._client)
49+
importer.handle_reference(greg_id)
50+
logger.info('Updated greg_id=%s', greg_id)
51+
52+
# TODO: Should we have the importer return potential new tasks? If so,
53+
# we could rely on the default *handle_task* implementation for
54+
# re-queueing.
55+
#
56+
# *Or* should the import itself add potential tasks to the queue? It
57+
# kind of depends on whether we want the option to run the importer
58+
# *without* adding new tasks to the queue...
59+
return []
60+
4261
@classmethod
4362
def create_manual_task(cls, reference, sub=manual_sub, nbf=None):
4463
""" Create a manual task. """
Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright 2021 University of Oslo, Norway
3+
# Copyright 2021-2023 University of Oslo, Norway
44
#
55
# This file is part of Cerebrum.
66
#
@@ -18,24 +18,13 @@
1818
# along with Cerebrum; if not, write to the Free Software Foundation,
1919
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
2020
"""
21-
Greg consent functionality.
21+
Sync group membership for a given entity.
2222
"""
2323
import logging
2424

25-
from Cerebrum.group.template import GroupTemplate
26-
2725
logger = logging.getLogger(__name__)
2826

2927

30-
GREG_CONSENT_GROUP = GroupTemplate(
31-
group_name='greg-aktivt-samtykke',
32-
group_description='Guests who consents to electronic publication',
33-
group_type='internal-group',
34-
group_visibility='A',
35-
)
36-
37-
38-
# TODO: Should this be a 'generic' import_utils class?
3928
class GroupMembershipSetter(object):
4029
"""
4130
Set membership for a single entity in a given group.
@@ -60,9 +49,8 @@ def __init__(self, get_group):
6049
connection/transaction to use, and should return the
6150
Cerebrum.Group.Group object to update.
6251
63-
Would typically be a
64-
py:class:`Cerebrum.group.template.GroupTemplate` or similar
65-
callable object.
52+
Would typically be a :class:`Cerebrum.group.template.GroupTemplate`
53+
or similar callable object.
6654
"""
6755
self.get_group = get_group
6856

@@ -73,17 +61,28 @@ def __repr__(self):
7361
)
7462

7563
def __call__(self, db, entity_id, set_member):
64+
"""
65+
Ensure entity_id is or isn't a member of this group.
66+
67+
:type db: Cerebrum.database.Database
68+
:param int entity_id: member id to sync
69+
:param bool set_member: if entity_id should be a member
70+
71+
:returns bool: True if membership was changed
72+
"""
7673
group = self.get_group(db)
7774
is_member = group.has_member(entity_id)
7875

7976
if set_member and not is_member:
8077
logger.info('adding entity_id=%d to group %s (%d)',
8178
entity_id, group.group_name, group.entity_id)
8279
group.add_member(entity_id)
83-
elif not set_member and is_member:
80+
return True
81+
82+
if not set_member and is_member:
8483
logger.info('removing entity_id=%d from group %s (%d)',
8584
entity_id, group.group_name, group.entity_id)
8685
group.remove_member(entity_id)
86+
return True
8787

88-
89-
sync_greg_consent = GroupMembershipSetter(GREG_CONSENT_GROUP)
88+
return False
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright 2023 University of Oslo, Norway
4+
#
5+
# This file is part of Cerebrum.
6+
#
7+
# Cerebrum is free software; you can redistribute it and/or modify it
8+
# under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation; either version 2 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# Cerebrum is distributed in the hope that it will be useful, but
13+
# WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with Cerebrum; if not, write to the Free Software Foundation,
19+
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20+
"""
21+
UiO-specific Greg import logic.
22+
"""
23+
from Cerebrum.group.template import GroupTemplate
24+
from Cerebrum.modules.greg import mapper
25+
from Cerebrum.modules.greg import importer
26+
from Cerebrum.modules.import_utils.groups import GroupMembershipSetter
27+
28+
29+
GREG_CONSENT_GROUP = GroupTemplate(
30+
group_name='greg-aktivt-samtykke',
31+
group_description='Guests who consents to electronic publication',
32+
group_type='internal-group',
33+
group_visibility='A',
34+
)
35+
36+
sync_greg_consent = GroupMembershipSetter(GREG_CONSENT_GROUP)
37+
38+
39+
class UioGregMapper(mapper.GregMapper):
40+
pass
41+
42+
43+
class UioGregImporter(importer.GregImporter):
44+
45+
CONSENT_GROUPS = {
46+
'greg-publish': sync_greg_consent,
47+
}
48+
49+
mapper = UioGregMapper()

Cerebrum/modules/tasks/queue_handler.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright 2021 University of Oslo, Norway
3+
# Copyright 2021-2023 University of Oslo, Norway
44
#
55
# This file is part of Cerebrum.
66
#
@@ -29,7 +29,10 @@
2929
logger = logging.getLogger(__name__)
3030

3131

32-
delay_on_error = backoff.Backoff(
32+
# Default backoff for errors/retries in QueueHandler. This backoff yields
33+
# time deltas 03:45, 07:30, 15:00, 30:00, 1:00:00, ... - before truncating at
34+
# 12:00:00 after 10 attempts. This should be a good backoff for most tasks.
35+
default_retry_delay = backoff.Backoff(
3336
backoff.Exponential(2),
3437
backoff.Factor(datetime.timedelta(hours=1) / 16),
3538
backoff.Truncate(datetime.timedelta(hours=12)),
@@ -60,16 +63,19 @@ class QueueHandler(object):
6063
# when to give up on a task
6164
max_attempts = 20
6265

66+
# next delay (timedelta) after *n* failed attempts
67+
get_retry_delay = default_retry_delay
68+
6369
def __init__(self, callback):
6470
self._callback = callback
6571

6672
def get_retry_task(self, task, error):
6773
""" Create a retry task from a failed task. """
6874
retry = task_models.copy_task(task)
6975
retry.queue = self.queue
70-
retry.sub = self.retry_sub or ""
76+
retry.sub = self.retry_sub or task.sub
7177
retry.attempts = task.attempts + 1
72-
retry.nbf = now() + delay_on_error(task.attempts + 1)
78+
retry.nbf = now() + self.get_retry_delay(task.attempts + 1)
7379
retry.reason = 'retry: failed_at={} error={}'.format(now(), error)
7480
return retry
7581

contrib/greg/greg-manual-import.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33
#
4-
# Copyright 2021 University of Oslo, Norway
4+
# Copyright 2021-2023 University of Oslo, Norway
55
#
66
# This file is part of Cerebrum.
77
#
@@ -31,15 +31,14 @@
3131
unicode_literals,
3232
)
3333
import argparse
34-
import functools
3534
import logging
3635

3736
import Cerebrum.logutils
3837
import Cerebrum.logutils.options
3938
from Cerebrum.Utils import Factory
4039
from Cerebrum.database.ctx import db_context
4140
from Cerebrum.modules.greg.client import get_client
42-
from Cerebrum.modules.greg.importer import GregImporter
41+
from Cerebrum.modules.greg.importer import get_import_class
4342
from Cerebrum.utils.argutils import add_commit_args
4443

4544
logger = logging.getLogger(__name__)
@@ -81,13 +80,11 @@ def main(inargs=None):
8180
logger.info("start %s", parser.prog)
8281
logger.debug("args: %r", args)
8382

84-
# we don't really need the full TaskImportConfig here, but it's easier to
85-
# re-use the existing config.
8683
client = get_client(args.config)
87-
get_import = functools.partial(GregImporter, client=client)
84+
import_class = get_import_class()
8885

8986
with db_context(get_db(), not args.commit) as db:
90-
greg_import = get_import(db)
87+
greg_import = import_class(db, client=client)
9188

9289
logger.info('handle reference=%r', args.reference)
9390
greg_import.handle_reference(args.reference)

0 commit comments

Comments
 (0)