##// END OF EJS Templates
code: unified coverage notes to # pragma: no cover
marcink -
r3282:5c2818aa default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,106 +1,106 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Single source for redirection links.
22 Single source for redirection links.
23
23
24 Goal of this module is to provide a single source of truth regarding external
24 Goal of this module is to provide a single source of truth regarding external
25 links. The data inside this module is used to configure the routing
25 links. The data inside this module is used to configure the routing
26 system of Enterprise and it is used also as a base to check if this data
26 system of Enterprise and it is used also as a base to check if this data
27 and our server configuration are in sync.
27 and our server configuration are in sync.
28
28
29 .. py:data:: link_config
29 .. py:data:: link_config
30
30
31 Contains the configuration for external links. Each item is supposed to be
31 Contains the configuration for external links. Each item is supposed to be
32 a `dict` like this example::
32 a `dict` like this example::
33
33
34 {"name": "url_name",
34 {"name": "url_name",
35 "target": "https://rhodecode.com/r1/enterprise/keyword/",
35 "target": "https://rhodecode.com/r1/enterprise/keyword/",
36 "external_target": "https://example.com/some-page.html",
36 "external_target": "https://example.com/some-page.html",
37 }
37 }
38
38
39 then you can retrieve the url by simply calling the URL function:
39 then you can retrieve the url by simply calling the URL function:
40
40
41 `h.route_path('url_name')`
41 `h.route_path('url_name')`
42
42
43 The redirection must be first implemented in our servers before
43 The redirection must be first implemented in our servers before
44 you can see it working.
44 you can see it working.
45 """
45 """
46 # flake8: noqa
46 # pragma: no cover
47 from __future__ import unicode_literals
47 from __future__ import unicode_literals
48
48
49 link_config = [
49 link_config = [
50 {
50 {
51 "name": "enterprise_docs",
51 "name": "enterprise_docs",
52 "target": "https://rhodecode.com/r1/enterprise/docs/",
52 "target": "https://rhodecode.com/r1/enterprise/docs/",
53 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/",
53 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/",
54 },
54 },
55 {
55 {
56 "name": "enterprise_log_file_locations",
56 "name": "enterprise_log_file_locations",
57 "target": "https://rhodecode.com/r1/enterprise/docs/admin-system-overview/",
57 "target": "https://rhodecode.com/r1/enterprise/docs/admin-system-overview/",
58 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/admin/system-overview.html#log-files",
58 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/admin/system-overview.html#log-files",
59 },
59 },
60 {
60 {
61 "name": "enterprise_issue_tracker_settings",
61 "name": "enterprise_issue_tracker_settings",
62 "target": "https://rhodecode.com/r1/enterprise/docs/issue-trackers-overview/",
62 "target": "https://rhodecode.com/r1/enterprise/docs/issue-trackers-overview/",
63 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/issue-trackers/issue-trackers.html",
63 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/issue-trackers/issue-trackers.html",
64 },
64 },
65 {
65 {
66 "name": "enterprise_svn_setup",
66 "name": "enterprise_svn_setup",
67 "target": "https://rhodecode.com/r1/enterprise/docs/svn-setup/",
67 "target": "https://rhodecode.com/r1/enterprise/docs/svn-setup/",
68 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/admin/svn-http.html",
68 "external_target": "https://docs.rhodecode.com/RhodeCode-Enterprise/admin/svn-http.html",
69 },
69 },
70 {
70 {
71 "name": "enterprise_license_convert_from_old",
71 "name": "enterprise_license_convert_from_old",
72 "target": "https://rhodecode.com/r1/enterprise/convert-license/",
72 "target": "https://rhodecode.com/r1/enterprise/convert-license/",
73 "external_target": "https://rhodecode.com/u/license-upgrade",
73 "external_target": "https://rhodecode.com/u/license-upgrade",
74 },
74 },
75 {
75 {
76 "name": "rst_help",
76 "name": "rst_help",
77 "target": "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
77 "target": "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
78 "external_target": "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
78 "external_target": "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
79 },
79 },
80 {
80 {
81 "name": "markdown_help",
81 "name": "markdown_help",
82 "target": "https://daringfireball.net/projects/markdown/syntax",
82 "target": "https://daringfireball.net/projects/markdown/syntax",
83 "external_target": "https://daringfireball.net/projects/markdown/syntax",
83 "external_target": "https://daringfireball.net/projects/markdown/syntax",
84 },
84 },
85 {
85 {
86 "name": "rhodecode_official",
86 "name": "rhodecode_official",
87 "target": "https://rhodecode.com",
87 "target": "https://rhodecode.com",
88 "external_target": "https://rhodecode.com/",
88 "external_target": "https://rhodecode.com/",
89 },
89 },
90 {
90 {
91 "name": "rhodecode_support",
91 "name": "rhodecode_support",
92 "target": "https://rhodecode.com/help/",
92 "target": "https://rhodecode.com/help/",
93 "external_target": "https://rhodecode.com/support",
93 "external_target": "https://rhodecode.com/support",
94 },
94 },
95 {
95 {
96 "name": "rhodecode_translations",
96 "name": "rhodecode_translations",
97 "target": "https://rhodecode.com/translate/enterprise",
97 "target": "https://rhodecode.com/translate/enterprise",
98 "external_target": "https://www.transifex.com/rhodecode/RhodeCode/",
98 "external_target": "https://www.transifex.com/rhodecode/RhodeCode/",
99 },
99 },
100
100
101 ]
101 ]
102
102
103
103
104 def connect_redirection_links(config):
104 def connect_redirection_links(config):
105 for link in link_config:
105 for link in link_config:
106 config.add_route(link['name'], link['target'], static=True)
106 config.add_route(link['name'], link['target'], static=True)
@@ -1,78 +1,78 b''
1 # Copyright (C) 2016-2018 RhodeCode GmbH
1 # Copyright (C) 2016-2018 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20 from pyramid.threadlocal import get_current_registry
20 from pyramid.threadlocal import get_current_registry
21 from rhodecode.events.base import RhodeCodeIntegrationEvent
21 from rhodecode.events.base import RhodeCodeIntegrationEvent
22
22
23
23
24 log = logging.getLogger(__name__)
24 log = logging.getLogger(__name__)
25
25
26
26
27 def trigger(event, registry=None):
27 def trigger(event, registry=None):
28 """
28 """
29 Helper method to send an event. This wraps the pyramid logic to send an
29 Helper method to send an event. This wraps the pyramid logic to send an
30 event.
30 event.
31 """
31 """
32 # For the first step we are using pyramids thread locals here. If the
32 # For the first step we are using pyramids thread locals here. If the
33 # event mechanism works out as a good solution we should think about
33 # event mechanism works out as a good solution we should think about
34 # passing the registry as an argument to get rid of it.
34 # passing the registry as an argument to get rid of it.
35 event_name = event.__class__
35 event_name = event.__class__
36 log.debug('event %s sent for execution', event_name)
36 log.debug('event %s sent for execution', event_name)
37 registry = registry or get_current_registry()
37 registry = registry or get_current_registry()
38 registry.notify(event)
38 registry.notify(event)
39 log.debug('event %s triggered using registry %s', event_name, registry)
39 log.debug('event %s triggered using registry %s', event_name, registry)
40
40
41 # Send the events to integrations directly
41 # Send the events to integrations directly
42 from rhodecode.integrations import integrations_event_handler
42 from rhodecode.integrations import integrations_event_handler
43 if isinstance(event, RhodeCodeIntegrationEvent):
43 if isinstance(event, RhodeCodeIntegrationEvent):
44 integrations_event_handler(event)
44 integrations_event_handler(event)
45
45
46
46
47 from rhodecode.events.user import ( # noqa
47 from rhodecode.events.user import ( # pragma: no cover
48 UserPreCreate,
48 UserPreCreate,
49 UserPostCreate,
49 UserPostCreate,
50 UserPreUpdate,
50 UserPreUpdate,
51 UserRegistered,
51 UserRegistered,
52 UserPermissionsChange,
52 UserPermissionsChange,
53 )
53 )
54
54
55 from rhodecode.events.repo import ( # noqa
55 from rhodecode.events.repo import ( # pragma: no cover
56 RepoEvent,
56 RepoEvent,
57 RepoPreCreateEvent, RepoCreateEvent,
57 RepoPreCreateEvent, RepoCreateEvent,
58 RepoPreDeleteEvent, RepoDeleteEvent,
58 RepoPreDeleteEvent, RepoDeleteEvent,
59 RepoPrePushEvent, RepoPushEvent,
59 RepoPrePushEvent, RepoPushEvent,
60 RepoPrePullEvent, RepoPullEvent,
60 RepoPrePullEvent, RepoPullEvent,
61 )
61 )
62
62
63 from rhodecode.events.repo_group import ( # noqa
63 from rhodecode.events.repo_group import ( # pragma: no cover
64 RepoGroupEvent,
64 RepoGroupEvent,
65 RepoGroupCreateEvent,
65 RepoGroupCreateEvent,
66 RepoGroupUpdateEvent,
66 RepoGroupUpdateEvent,
67 RepoGroupDeleteEvent,
67 RepoGroupDeleteEvent,
68 )
68 )
69
69
70 from rhodecode.events.pullrequest import ( # noqa
70 from rhodecode.events.pullrequest import ( # pragma: no cover
71 PullRequestEvent,
71 PullRequestEvent,
72 PullRequestCreateEvent,
72 PullRequestCreateEvent,
73 PullRequestUpdateEvent,
73 PullRequestUpdateEvent,
74 PullRequestCommentEvent,
74 PullRequestCommentEvent,
75 PullRequestReviewEvent,
75 PullRequestReviewEvent,
76 PullRequestMergeEvent,
76 PullRequestMergeEvent,
77 PullRequestCloseEvent,
77 PullRequestCloseEvent,
78 )
78 )
@@ -1,302 +1,302 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 """
20 """
21 Celery loader, run with::
21 Celery loader, run with::
22
22
23 celery worker \
23 celery worker \
24 --beat \
24 --beat \
25 --app rhodecode.lib.celerylib.loader \
25 --app rhodecode.lib.celerylib.loader \
26 --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler \
26 --scheduler rhodecode.lib.celerylib.scheduler.RcScheduler \
27 --loglevel DEBUG --ini=._dev/dev.ini
27 --loglevel DEBUG --ini=._dev/dev.ini
28 """
28 """
29 import os
29 import os
30 import logging
30 import logging
31 import importlib
31 import importlib
32
32
33 from celery import Celery
33 from celery import Celery
34 from celery import signals
34 from celery import signals
35 from celery import Task
35 from celery import Task
36 from celery import exceptions # noqa
36 from celery import exceptions # pragma: no cover
37 from kombu.serialization import register
37 from kombu.serialization import register
38 from pyramid.threadlocal import get_current_request
38 from pyramid.threadlocal import get_current_request
39
39
40 import rhodecode
40 import rhodecode
41
41
42 from rhodecode.lib.auth import AuthUser
42 from rhodecode.lib.auth import AuthUser
43 from rhodecode.lib.celerylib.utils import get_ini_config, parse_ini_vars
43 from rhodecode.lib.celerylib.utils import get_ini_config, parse_ini_vars
44 from rhodecode.lib.ext_json import json
44 from rhodecode.lib.ext_json import json
45 from rhodecode.lib.pyramid_utils import bootstrap, setup_logging, prepare_request
45 from rhodecode.lib.pyramid_utils import bootstrap, setup_logging, prepare_request
46 from rhodecode.lib.utils2 import str2bool
46 from rhodecode.lib.utils2 import str2bool
47 from rhodecode.model import meta
47 from rhodecode.model import meta
48
48
49
49
50 register('json_ext', json.dumps, json.loads,
50 register('json_ext', json.dumps, json.loads,
51 content_type='application/x-json-ext',
51 content_type='application/x-json-ext',
52 content_encoding='utf-8')
52 content_encoding='utf-8')
53
53
54 log = logging.getLogger('celery.rhodecode.loader')
54 log = logging.getLogger('celery.rhodecode.loader')
55
55
56
56
57 def add_preload_arguments(parser):
57 def add_preload_arguments(parser):
58 parser.add_argument(
58 parser.add_argument(
59 '--ini', default=None,
59 '--ini', default=None,
60 help='Path to ini configuration file.'
60 help='Path to ini configuration file.'
61 )
61 )
62 parser.add_argument(
62 parser.add_argument(
63 '--ini-var', default=None,
63 '--ini-var', default=None,
64 help='Comma separated list of key=value to pass to ini.'
64 help='Comma separated list of key=value to pass to ini.'
65 )
65 )
66
66
67
67
68 def get_logger(obj):
68 def get_logger(obj):
69 custom_log = logging.getLogger(
69 custom_log = logging.getLogger(
70 'rhodecode.task.{}'.format(obj.__class__.__name__))
70 'rhodecode.task.{}'.format(obj.__class__.__name__))
71
71
72 if rhodecode.CELERY_ENABLED:
72 if rhodecode.CELERY_ENABLED:
73 try:
73 try:
74 custom_log = obj.get_logger()
74 custom_log = obj.get_logger()
75 except Exception:
75 except Exception:
76 pass
76 pass
77
77
78 return custom_log
78 return custom_log
79
79
80
80
81 imports = ['rhodecode.lib.celerylib.tasks']
81 imports = ['rhodecode.lib.celerylib.tasks']
82
82
83 try:
83 try:
84 # try if we have EE tasks available
84 # try if we have EE tasks available
85 importlib.import_module('rc_ee')
85 importlib.import_module('rc_ee')
86 imports.append('rc_ee.lib.celerylib.tasks')
86 imports.append('rc_ee.lib.celerylib.tasks')
87 except ImportError:
87 except ImportError:
88 pass
88 pass
89
89
90
90
91 base_celery_config = {
91 base_celery_config = {
92 'result_backend': 'rpc://',
92 'result_backend': 'rpc://',
93 'result_expires': 60 * 60 * 24,
93 'result_expires': 60 * 60 * 24,
94 'result_persistent': True,
94 'result_persistent': True,
95 'imports': imports,
95 'imports': imports,
96 'worker_max_tasks_per_child': 100,
96 'worker_max_tasks_per_child': 100,
97 'accept_content': ['json_ext'],
97 'accept_content': ['json_ext'],
98 'task_serializer': 'json_ext',
98 'task_serializer': 'json_ext',
99 'result_serializer': 'json_ext',
99 'result_serializer': 'json_ext',
100 'worker_hijack_root_logger': False,
100 'worker_hijack_root_logger': False,
101 'database_table_names': {
101 'database_table_names': {
102 'task': 'beat_taskmeta',
102 'task': 'beat_taskmeta',
103 'group': 'beat_groupmeta',
103 'group': 'beat_groupmeta',
104 }
104 }
105 }
105 }
106 # init main celery app
106 # init main celery app
107 celery_app = Celery()
107 celery_app = Celery()
108 celery_app.user_options['preload'].add(add_preload_arguments)
108 celery_app.user_options['preload'].add(add_preload_arguments)
109 ini_file_glob = None
109 ini_file_glob = None
110
110
111
111
112 @signals.setup_logging.connect
112 @signals.setup_logging.connect
113 def setup_logging_callback(**kwargs):
113 def setup_logging_callback(**kwargs):
114 setup_logging(ini_file_glob)
114 setup_logging(ini_file_glob)
115
115
116
116
117 @signals.user_preload_options.connect
117 @signals.user_preload_options.connect
118 def on_preload_parsed(options, **kwargs):
118 def on_preload_parsed(options, **kwargs):
119 ini_location = options['ini']
119 ini_location = options['ini']
120 ini_vars = options['ini_var']
120 ini_vars = options['ini_var']
121 celery_app.conf['INI_PYRAMID'] = options['ini']
121 celery_app.conf['INI_PYRAMID'] = options['ini']
122
122
123 if ini_location is None:
123 if ini_location is None:
124 print('You must provide the paste --ini argument')
124 print('You must provide the paste --ini argument')
125 exit(-1)
125 exit(-1)
126
126
127 options = None
127 options = None
128 if ini_vars is not None:
128 if ini_vars is not None:
129 options = parse_ini_vars(ini_vars)
129 options = parse_ini_vars(ini_vars)
130
130
131 global ini_file_glob
131 global ini_file_glob
132 ini_file_glob = ini_location
132 ini_file_glob = ini_location
133
133
134 log.debug('Bootstrapping RhodeCode application...')
134 log.debug('Bootstrapping RhodeCode application...')
135 env = bootstrap(ini_location, options=options)
135 env = bootstrap(ini_location, options=options)
136
136
137 setup_celery_app(
137 setup_celery_app(
138 app=env['app'], root=env['root'], request=env['request'],
138 app=env['app'], root=env['root'], request=env['request'],
139 registry=env['registry'], closer=env['closer'],
139 registry=env['registry'], closer=env['closer'],
140 ini_location=ini_location)
140 ini_location=ini_location)
141
141
142 # fix the global flag even if it's disabled via .ini file because this
142 # fix the global flag even if it's disabled via .ini file because this
143 # is a worker code that doesn't need this to be disabled.
143 # is a worker code that doesn't need this to be disabled.
144 rhodecode.CELERY_ENABLED = True
144 rhodecode.CELERY_ENABLED = True
145
145
146
146
147 @signals.task_success.connect
147 @signals.task_success.connect
148 def task_success_signal(result, **kwargs):
148 def task_success_signal(result, **kwargs):
149 meta.Session.commit()
149 meta.Session.commit()
150 closer = celery_app.conf['PYRAMID_CLOSER']
150 closer = celery_app.conf['PYRAMID_CLOSER']
151 if closer:
151 if closer:
152 closer()
152 closer()
153
153
154
154
155 @signals.task_retry.connect
155 @signals.task_retry.connect
156 def task_retry_signal(
156 def task_retry_signal(
157 request, reason, einfo, **kwargs):
157 request, reason, einfo, **kwargs):
158 meta.Session.remove()
158 meta.Session.remove()
159 closer = celery_app.conf['PYRAMID_CLOSER']
159 closer = celery_app.conf['PYRAMID_CLOSER']
160 if closer:
160 if closer:
161 closer()
161 closer()
162
162
163
163
164 @signals.task_failure.connect
164 @signals.task_failure.connect
165 def task_failure_signal(
165 def task_failure_signal(
166 task_id, exception, args, kwargs, traceback, einfo, **kargs):
166 task_id, exception, args, kwargs, traceback, einfo, **kargs):
167 from rhodecode.lib.exc_tracking import store_exception
167 from rhodecode.lib.exc_tracking import store_exception
168
168
169 meta.Session.remove()
169 meta.Session.remove()
170
170
171 # simulate sys.exc_info()
171 # simulate sys.exc_info()
172 exc_info = (einfo.type, einfo.exception, einfo.tb)
172 exc_info = (einfo.type, einfo.exception, einfo.tb)
173 store_exception(id(exc_info), exc_info, prefix='celery_rhodecode')
173 store_exception(id(exc_info), exc_info, prefix='celery_rhodecode')
174
174
175 closer = celery_app.conf['PYRAMID_CLOSER']
175 closer = celery_app.conf['PYRAMID_CLOSER']
176 if closer:
176 if closer:
177 closer()
177 closer()
178
178
179
179
180 @signals.task_revoked.connect
180 @signals.task_revoked.connect
181 def task_revoked_signal(
181 def task_revoked_signal(
182 request, terminated, signum, expired, **kwargs):
182 request, terminated, signum, expired, **kwargs):
183 closer = celery_app.conf['PYRAMID_CLOSER']
183 closer = celery_app.conf['PYRAMID_CLOSER']
184 if closer:
184 if closer:
185 closer()
185 closer()
186
186
187
187
188 def setup_celery_app(app, root, request, registry, closer, ini_location):
188 def setup_celery_app(app, root, request, registry, closer, ini_location):
189 ini_dir = os.path.dirname(os.path.abspath(ini_location))
189 ini_dir = os.path.dirname(os.path.abspath(ini_location))
190 celery_config = base_celery_config
190 celery_config = base_celery_config
191 celery_config.update({
191 celery_config.update({
192 # store celerybeat scheduler db where the .ini file is
192 # store celerybeat scheduler db where the .ini file is
193 'beat_schedule_filename': os.path.join(ini_dir, 'celerybeat-schedule'),
193 'beat_schedule_filename': os.path.join(ini_dir, 'celerybeat-schedule'),
194 })
194 })
195 ini_settings = get_ini_config(ini_location)
195 ini_settings = get_ini_config(ini_location)
196 log.debug('Got custom celery conf: %s', ini_settings)
196 log.debug('Got custom celery conf: %s', ini_settings)
197
197
198 celery_config.update(ini_settings)
198 celery_config.update(ini_settings)
199 celery_app.config_from_object(celery_config)
199 celery_app.config_from_object(celery_config)
200
200
201 celery_app.conf.update({'PYRAMID_APP': app})
201 celery_app.conf.update({'PYRAMID_APP': app})
202 celery_app.conf.update({'PYRAMID_ROOT': root})
202 celery_app.conf.update({'PYRAMID_ROOT': root})
203 celery_app.conf.update({'PYRAMID_REQUEST': request})
203 celery_app.conf.update({'PYRAMID_REQUEST': request})
204 celery_app.conf.update({'PYRAMID_REGISTRY': registry})
204 celery_app.conf.update({'PYRAMID_REGISTRY': registry})
205 celery_app.conf.update({'PYRAMID_CLOSER': closer})
205 celery_app.conf.update({'PYRAMID_CLOSER': closer})
206
206
207
207
208 def configure_celery(config, ini_location):
208 def configure_celery(config, ini_location):
209 """
209 """
210 Helper that is called from our application creation logic. It gives
210 Helper that is called from our application creation logic. It gives
211 connection info into running webapp and allows execution of tasks from
211 connection info into running webapp and allows execution of tasks from
212 RhodeCode itself
212 RhodeCode itself
213 """
213 """
214 # store some globals into rhodecode
214 # store some globals into rhodecode
215 rhodecode.CELERY_ENABLED = str2bool(
215 rhodecode.CELERY_ENABLED = str2bool(
216 config.registry.settings.get('use_celery'))
216 config.registry.settings.get('use_celery'))
217 if rhodecode.CELERY_ENABLED:
217 if rhodecode.CELERY_ENABLED:
218 log.info('Configuring celery based on `%s` file', ini_location)
218 log.info('Configuring celery based on `%s` file', ini_location)
219 setup_celery_app(
219 setup_celery_app(
220 app=None, root=None, request=None, registry=config.registry,
220 app=None, root=None, request=None, registry=config.registry,
221 closer=None, ini_location=ini_location)
221 closer=None, ini_location=ini_location)
222
222
223
223
224 def maybe_prepare_env(req):
224 def maybe_prepare_env(req):
225 environ = {}
225 environ = {}
226 try:
226 try:
227 environ.update({
227 environ.update({
228 'PATH_INFO': req.environ['PATH_INFO'],
228 'PATH_INFO': req.environ['PATH_INFO'],
229 'SCRIPT_NAME': req.environ['SCRIPT_NAME'],
229 'SCRIPT_NAME': req.environ['SCRIPT_NAME'],
230 'HTTP_HOST':
230 'HTTP_HOST':
231 req.environ.get('HTTP_HOST', req.environ['SERVER_NAME']),
231 req.environ.get('HTTP_HOST', req.environ['SERVER_NAME']),
232 'SERVER_NAME': req.environ['SERVER_NAME'],
232 'SERVER_NAME': req.environ['SERVER_NAME'],
233 'SERVER_PORT': req.environ['SERVER_PORT'],
233 'SERVER_PORT': req.environ['SERVER_PORT'],
234 'wsgi.url_scheme': req.environ['wsgi.url_scheme'],
234 'wsgi.url_scheme': req.environ['wsgi.url_scheme'],
235 })
235 })
236 except Exception:
236 except Exception:
237 pass
237 pass
238
238
239 return environ
239 return environ
240
240
241
241
242 class RequestContextTask(Task):
242 class RequestContextTask(Task):
243 """
243 """
244 This is a celery task which will create a rhodecode app instance context
244 This is a celery task which will create a rhodecode app instance context
245 for the task, patch pyramid with the original request
245 for the task, patch pyramid with the original request
246 that created the task and also add the user to the context.
246 that created the task and also add the user to the context.
247 """
247 """
248
248
249 def apply_async(self, args=None, kwargs=None, task_id=None, producer=None,
249 def apply_async(self, args=None, kwargs=None, task_id=None, producer=None,
250 link=None, link_error=None, shadow=None, **options):
250 link=None, link_error=None, shadow=None, **options):
251 """ queue the job to run (we are in web request context here) """
251 """ queue the job to run (we are in web request context here) """
252
252
253 req = get_current_request()
253 req = get_current_request()
254
254
255 # web case
255 # web case
256 if hasattr(req, 'user'):
256 if hasattr(req, 'user'):
257 ip_addr = req.user.ip_addr
257 ip_addr = req.user.ip_addr
258 user_id = req.user.user_id
258 user_id = req.user.user_id
259
259
260 # api case
260 # api case
261 elif hasattr(req, 'rpc_user'):
261 elif hasattr(req, 'rpc_user'):
262 ip_addr = req.rpc_user.ip_addr
262 ip_addr = req.rpc_user.ip_addr
263 user_id = req.rpc_user.user_id
263 user_id = req.rpc_user.user_id
264 else:
264 else:
265 raise Exception(
265 raise Exception(
266 'Unable to fetch required data from request: {}. \n'
266 'Unable to fetch required data from request: {}. \n'
267 'This task is required to be executed from context of '
267 'This task is required to be executed from context of '
268 'request in a webapp'.format(repr(req)))
268 'request in a webapp'.format(repr(req)))
269
269
270 if req:
270 if req:
271 # we hook into kwargs since it is the only way to pass our data to
271 # we hook into kwargs since it is the only way to pass our data to
272 # the celery worker
272 # the celery worker
273 environ = maybe_prepare_env(req)
273 environ = maybe_prepare_env(req)
274 options['headers'] = options.get('headers', {})
274 options['headers'] = options.get('headers', {})
275 options['headers'].update({
275 options['headers'].update({
276 'rhodecode_proxy_data': {
276 'rhodecode_proxy_data': {
277 'environ': environ,
277 'environ': environ,
278 'auth_user': {
278 'auth_user': {
279 'ip_addr': ip_addr,
279 'ip_addr': ip_addr,
280 'user_id': user_id
280 'user_id': user_id
281 },
281 },
282 }
282 }
283 })
283 })
284
284
285 return super(RequestContextTask, self).apply_async(
285 return super(RequestContextTask, self).apply_async(
286 args, kwargs, task_id, producer, link, link_error, shadow, **options)
286 args, kwargs, task_id, producer, link, link_error, shadow, **options)
287
287
288 def __call__(self, *args, **kwargs):
288 def __call__(self, *args, **kwargs):
289 """ rebuild the context and then run task on celery worker """
289 """ rebuild the context and then run task on celery worker """
290
290
291 proxy_data = getattr(self.request, 'rhodecode_proxy_data', None)
291 proxy_data = getattr(self.request, 'rhodecode_proxy_data', None)
292 if not proxy_data:
292 if not proxy_data:
293 return super(RequestContextTask, self).__call__(*args, **kwargs)
293 return super(RequestContextTask, self).__call__(*args, **kwargs)
294
294
295 log.debug('using celery proxy data to run task: %r', proxy_data)
295 log.debug('using celery proxy data to run task: %r', proxy_data)
296 # re-inject and register threadlocals for proper routing support
296 # re-inject and register threadlocals for proper routing support
297 request = prepare_request(proxy_data['environ'])
297 request = prepare_request(proxy_data['environ'])
298 request.user = AuthUser(user_id=proxy_data['auth_user']['user_id'],
298 request.user = AuthUser(user_id=proxy_data['auth_user']['user_id'],
299 ip_addr=proxy_data['auth_user']['ip_addr'])
299 ip_addr=proxy_data['auth_user']['ip_addr'])
300
300
301 return super(RequestContextTask, self).__call__(*args, **kwargs)
301 return super(RequestContextTask, self).__call__(*args, **kwargs)
302
302
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now