##// END OF EJS Templates
events: Add comments to the subcriber classes.
Martin Bornhold -
r1020:b4758185 default
parent child Browse files
Show More
@@ -1,143 +1,156 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 import logging
22 import logging
23 import pylons
23 import pylons
24 import Queue
24 import Queue
25 import subprocess32
25 import subprocess32
26
26
27 from pyramid.i18n import get_localizer
27 from pyramid.i18n import get_localizer
28 from pyramid.threadlocal import get_current_request
28 from pyramid.threadlocal import get_current_request
29 from threading import Thread
29 from threading import Thread
30
30
31 from rhodecode.translation import _ as tsf
31 from rhodecode.translation import _ as tsf
32
32
33
33
34 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
35
35
36
36
37 def add_renderer_globals(event):
37 def add_renderer_globals(event):
38 # Put pylons stuff into the context. This will be removed as soon as
38 # Put pylons stuff into the context. This will be removed as soon as
39 # migration to pyramid is finished.
39 # migration to pyramid is finished.
40 conf = pylons.config._current_obj()
40 conf = pylons.config._current_obj()
41 event['h'] = conf.get('pylons.h')
41 event['h'] = conf.get('pylons.h')
42 event['c'] = pylons.tmpl_context
42 event['c'] = pylons.tmpl_context
43 event['url'] = pylons.url
43 event['url'] = pylons.url
44
44
45 # TODO: When executed in pyramid view context the request is not available
45 # TODO: When executed in pyramid view context the request is not available
46 # in the event. Find a better solution to get the request.
46 # in the event. Find a better solution to get the request.
47 request = event['request'] or get_current_request()
47 request = event['request'] or get_current_request()
48
48
49 # Add Pyramid translation as '_' to context
49 # Add Pyramid translation as '_' to context
50 event['_'] = request.translate
50 event['_'] = request.translate
51 event['localizer'] = request.localizer
51 event['localizer'] = request.localizer
52
52
53
53
54 def add_localizer(event):
54 def add_localizer(event):
55 request = event.request
55 request = event.request
56 localizer = get_localizer(request)
56 localizer = get_localizer(request)
57
57
58 def auto_translate(*args, **kwargs):
58 def auto_translate(*args, **kwargs):
59 return localizer.translate(tsf(*args, **kwargs))
59 return localizer.translate(tsf(*args, **kwargs))
60
60
61 request.localizer = localizer
61 request.localizer = localizer
62 request.translate = auto_translate
62 request.translate = auto_translate
63
63
64
64
65 def scan_repositories_if_enabled(event):
65 def scan_repositories_if_enabled(event):
66 """
66 """
67 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
67 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
68 does a repository scan if enabled in the settings.
68 does a repository scan if enabled in the settings.
69 """
69 """
70 from rhodecode.model.scm import ScmModel
70 from rhodecode.model.scm import ScmModel
71 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
71 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
72 settings = event.app.registry.settings
72 settings = event.app.registry.settings
73 vcs_server_enabled = settings['vcs.server.enable']
73 vcs_server_enabled = settings['vcs.server.enable']
74 import_on_startup = settings['startup.import_repos']
74 import_on_startup = settings['startup.import_repos']
75 if vcs_server_enabled and import_on_startup:
75 if vcs_server_enabled and import_on_startup:
76 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
76 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
77 repo2db_mapper(repositories, remove_obsolete=False)
77 repo2db_mapper(repositories, remove_obsolete=False)
78
78
79
79
80 class Subscriber(object):
80 class Subscriber(object):
81 """
82 Base class for subscribers to the pyramid event system.
83 """
81 def __call__(self, event):
84 def __call__(self, event):
82 self.run(event)
85 self.run(event)
83
86
84 def run(self, event):
87 def run(self, event):
85 raise NotImplementedError('Subclass has to implement this.')
88 raise NotImplementedError('Subclass has to implement this.')
86
89
87
90
88 class AsyncSubscriber(Subscriber):
91 class AsyncSubscriber(Subscriber):
92 """
93 Subscriber that handles the execution of events in a separate task to not
94 block the execution of the code which triggers the event. It puts the
95 received events into a queue from which the worker process takes them in
96 order.
97 """
89 def __init__(self):
98 def __init__(self):
90 self._stop = False
99 self._stop = False
91 self._eventq = Queue.Queue()
100 self._eventq = Queue.Queue()
92 self._worker = self.create_worker()
101 self._worker = self.create_worker()
93 self._worker.start()
102 self._worker.start()
94
103
95 def __call__(self, event):
104 def __call__(self, event):
96 self._eventq.put(event)
105 self._eventq.put(event)
97
106
98 def create_worker(self):
107 def create_worker(self):
99 worker = Thread(target=self.do_work)
108 worker = Thread(target=self.do_work)
100 worker.daemon = True
109 worker.daemon = True
101 return worker
110 return worker
102
111
103 def stop_worker(self):
112 def stop_worker(self):
104 self._stop = False
113 self._stop = False
105 self._eventq.put(None)
114 self._eventq.put(None)
106 self._worker.join()
115 self._worker.join()
107
116
108 def do_work(self):
117 def do_work(self):
109 while not self._stop:
118 while not self._stop:
110 event = self._eventq.get()
119 event = self._eventq.get()
111 if event is not None:
120 if event is not None:
112 self.run(event)
121 self.run(event)
113
122
114
123
115 class AsyncSubprocessSubscriber(AsyncSubscriber):
124 class AsyncSubprocessSubscriber(AsyncSubscriber):
125 """
126 Subscriber that uses the subprocess32 module to execute a command if an
127 event is received. Events are handled asynchronously.
128 """
116
129
117 def __init__(self, cmd, timeout=None):
130 def __init__(self, cmd, timeout=None):
118 super(AsyncSubprocessSubscriber, self).__init__()
131 super(AsyncSubprocessSubscriber, self).__init__()
119 self._cmd = cmd
132 self._cmd = cmd
120 self._timeout = timeout
133 self._timeout = timeout
121
134
122 def run(self, event):
135 def run(self, event):
123 cmd = self._cmd
136 cmd = self._cmd
124 timeout = self._timeout
137 timeout = self._timeout
125 log.debug('Executing command %s.', cmd)
138 log.debug('Executing command %s.', cmd)
126
139
127 try:
140 try:
128 output = subprocess32.check_output(
141 output = subprocess32.check_output(
129 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
142 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
130 log.debug('Command finished %s', cmd)
143 log.debug('Command finished %s', cmd)
131 if output:
144 if output:
132 log.debug('Command output: %s', output)
145 log.debug('Command output: %s', output)
133 except subprocess32.TimeoutExpired as e:
146 except subprocess32.TimeoutExpired as e:
134 log.exception('Timeout while executing command.')
147 log.exception('Timeout while executing command.')
135 if e.output:
148 if e.output:
136 log.error('Command output: %s', e.output)
149 log.error('Command output: %s', e.output)
137 except subprocess32.CalledProcessError as e:
150 except subprocess32.CalledProcessError as e:
138 log.exception('Error while executing command.')
151 log.exception('Error while executing command.')
139 if e.output:
152 if e.output:
140 log.error('Command output: %s', e.output)
153 log.error('Command output: %s', e.output)
141 except:
154 except:
142 log.exception(
155 log.exception(
143 'Exception while executing command %s.', cmd)
156 'Exception while executing command %s.', cmd)
General Comments 0
You need to be logged in to leave comments. Login now