Browse Source

Update daemon management: rewrite stop daemon strategy

Bastien Sevajol (Algoo) 8 years ago
parent
commit
29f219819d
3 changed files with 44 additions and 39 deletions
  1. 1 1
      tracim/test.ini
  2. 1 1
      tracim/tracim/config/middleware.py
  3. 42 37
      tracim/tracim/lib/daemons.py

+ 1 - 1
tracim/test.ini View File

@@ -11,7 +11,7 @@ smtp_server = localhost
11 11
 error_email_from = turbogears@localhost
12 12
 
13 13
 [server:main]
14
-use = egg:gearbox#cherrypy
14
+use = egg:gearbox#wsgiref
15 15
 host = 127.0.0.1
16 16
 port = 8080
17 17
 

+ 1 - 1
tracim/tracim/config/middleware.py View File

@@ -37,6 +37,6 @@ def make_app(global_conf, full_stack=True, **app_conf):
37 37
     
38 38
     # Wrap your base TurboGears 2 application with custom middleware here
39 39
     daemons = DaemonsManager(app)
40
-    daemons.run(RadicaleDaemon.name, RadicaleDaemon)
40
+    daemons.run('radicale', RadicaleDaemon)
41 41
 
42 42
     return app

+ 42 - 37
tracim/tracim/lib/daemons.py View File

@@ -2,6 +2,7 @@ import threading
2 2
 from wsgiref.simple_server import make_server
3 3
 
4 4
 import signal
5
+
5 6
 from radicale import Application as RadicaleApplication
6 7
 from radicale import HTTPServer as RadicaleHTTPServer
7 8
 from radicale import HTTPSServer as RadicaleHTTPSServer
@@ -16,6 +17,8 @@ class DaemonsManager(object):
16 17
     def __init__(self, app: TGApp):
17 18
         self._app = app
18 19
         self._daemons = {}
20
+        signal.signal(signal.SIGTERM, lambda *_: self.stop_all())
21
+        signal.signal(signal.SIGINT, lambda *_: self.stop_all())
19 22
 
20 23
     def run(self, name: str, daemon_class: object, **kwargs) -> None:
21 24
         """
@@ -32,55 +35,57 @@ class DaemonsManager(object):
32 35
                 'Daemon with name "{0}" already running'.format(name)
33 36
             )
34 37
 
35
-        kwargs['app'] = self._app
36
-        shutdown_program = threading.Event()
37
-        # SIGTERM and SIGINT (aka KeyboardInterrupt) should just mark this for
38
-        # shutdown
39
-        signal.signal(signal.SIGTERM, lambda *_: shutdown_program.set())
40
-        signal.signal(signal.SIGINT, lambda *_: shutdown_program.set())
41
-
42
-        try:
43
-            threading.Thread(target=daemon_class.start, kwargs=kwargs).start()
44
-            self._daemons[name] = daemon_class
45
-        finally:
46
-            shutdown_program.set()
47
-
38
+        daemon = daemon_class(name=name, kwargs=kwargs, daemon=True)
39
+        daemon.start()
40
+        self._daemons[name] = daemon
48 41
 
49
-class Daemon(object):
50
-    _name = NotImplemented
51
-
52
-    def __init__(self, app: TGApp):
53
-        self._app = app
54
-
55
-    @classmethod
56
-    def start(cls, **kwargs):
57
-        return cls(**kwargs)
42
+    def stop(self, name: str) -> None:
43
+        """
44
+        Stop daemon with his name and wait for him.
45
+        Where name is given name when daemon started
46
+        with run method. If daemon name unknow, raise IndexError.
47
+        :param name:
48
+        """
49
+        self._daemons[name].stop()
50
+        self._daemons[name].join()
58 51
 
59
-    @classmethod
60
-    def kill(cls):
52
+    def stop_all(self) -> None:
53
+        """
54
+        Stop all started daemons and w<ait for them.
55
+        """
56
+        for daemon_name in self._daemons:
57
+            self._daemons[daemon_name].stop()
58
+        for daemon_name in self._daemons:
59
+            self._daemons[daemon_name].join()
60
+
61
+
62
+class Daemon(threading.Thread):
63
+    """
64
+    Thread who contains daemon. You must implement start and stop methods to
65
+    manage daemon life correctly.
66
+    """
67
+    def run(self):
61 68
         raise NotImplementedError()
62 69
 
63
-    @property
64
-    def name(self):
65
-        return self._name
70
+    def stop(self):
71
+        raise NotImplementedError()
66 72
 
67 73
 
68 74
 class RadicaleDaemon(Daemon):
69
-    _name = 'tracim-radicale-server'
70
-
71
-    @classmethod
72
-    def kill(cls):
73
-        pass  # TODO
75
+    def __init__(self, *args, **kwargs):
76
+        super().__init__(*args, **kwargs)
77
+        self._prepare_config()
78
+        self._server = self._get_server()
74 79
 
75
-    def __init__(self, app: TGApp):
80
+    def run(self):
76 81
         """
77 82
         To see origin radical server start method, refer to
78 83
         radicale.__main__.run
79 84
         """
80
-        super().__init__(app)
81
-        self._prepare_config()
82
-        server = self._get_server()
83
-        server.serve_forever()
85
+        self._server.serve_forever()
86
+
87
+    def stop(self):
88
+        self._server.shutdown()
84 89
 
85 90
     def _prepare_config(self):
86 91
         from tracim.config.app_cfg import CFG