##// 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 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 import logging
23 23 import pylons
24 24 import Queue
25 25 import subprocess32
26 26
27 27 from pyramid.i18n import get_localizer
28 28 from pyramid.threadlocal import get_current_request
29 29 from threading import Thread
30 30
31 31 from rhodecode.translation import _ as tsf
32 32
33 33
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 37 def add_renderer_globals(event):
38 38 # Put pylons stuff into the context. This will be removed as soon as
39 39 # migration to pyramid is finished.
40 40 conf = pylons.config._current_obj()
41 41 event['h'] = conf.get('pylons.h')
42 42 event['c'] = pylons.tmpl_context
43 43 event['url'] = pylons.url
44 44
45 45 # TODO: When executed in pyramid view context the request is not available
46 46 # in the event. Find a better solution to get the request.
47 47 request = event['request'] or get_current_request()
48 48
49 49 # Add Pyramid translation as '_' to context
50 50 event['_'] = request.translate
51 51 event['localizer'] = request.localizer
52 52
53 53
54 54 def add_localizer(event):
55 55 request = event.request
56 56 localizer = get_localizer(request)
57 57
58 58 def auto_translate(*args, **kwargs):
59 59 return localizer.translate(tsf(*args, **kwargs))
60 60
61 61 request.localizer = localizer
62 62 request.translate = auto_translate
63 63
64 64
65 65 def scan_repositories_if_enabled(event):
66 66 """
67 67 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
68 68 does a repository scan if enabled in the settings.
69 69 """
70 70 from rhodecode.model.scm import ScmModel
71 71 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
72 72 settings = event.app.registry.settings
73 73 vcs_server_enabled = settings['vcs.server.enable']
74 74 import_on_startup = settings['startup.import_repos']
75 75 if vcs_server_enabled and import_on_startup:
76 76 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
77 77 repo2db_mapper(repositories, remove_obsolete=False)
78 78
79 79
80 80 class Subscriber(object):
81 """
82 Base class for subscribers to the pyramid event system.
83 """
81 84 def __call__(self, event):
82 85 self.run(event)
83 86
84 87 def run(self, event):
85 88 raise NotImplementedError('Subclass has to implement this.')
86 89
87 90
88 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 98 def __init__(self):
90 99 self._stop = False
91 100 self._eventq = Queue.Queue()
92 101 self._worker = self.create_worker()
93 102 self._worker.start()
94 103
95 104 def __call__(self, event):
96 105 self._eventq.put(event)
97 106
98 107 def create_worker(self):
99 108 worker = Thread(target=self.do_work)
100 109 worker.daemon = True
101 110 return worker
102 111
103 112 def stop_worker(self):
104 113 self._stop = False
105 114 self._eventq.put(None)
106 115 self._worker.join()
107 116
108 117 def do_work(self):
109 118 while not self._stop:
110 119 event = self._eventq.get()
111 120 if event is not None:
112 121 self.run(event)
113 122
114 123
115 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 130 def __init__(self, cmd, timeout=None):
118 131 super(AsyncSubprocessSubscriber, self).__init__()
119 132 self._cmd = cmd
120 133 self._timeout = timeout
121 134
122 135 def run(self, event):
123 136 cmd = self._cmd
124 137 timeout = self._timeout
125 138 log.debug('Executing command %s.', cmd)
126 139
127 140 try:
128 141 output = subprocess32.check_output(
129 142 cmd, timeout=timeout, stderr=subprocess32.STDOUT)
130 143 log.debug('Command finished %s', cmd)
131 144 if output:
132 145 log.debug('Command output: %s', output)
133 146 except subprocess32.TimeoutExpired as e:
134 147 log.exception('Timeout while executing command.')
135 148 if e.output:
136 149 log.error('Command output: %s', e.output)
137 150 except subprocess32.CalledProcessError as e:
138 151 log.exception('Error while executing command.')
139 152 if e.output:
140 153 log.error('Command output: %s', e.output)
141 154 except:
142 155 log.exception(
143 156 'Exception while executing command %s.', cmd)
General Comments 0
You need to be logged in to leave comments. Login now