浏览代码

Update daemon management: rewrite stop daemon strategy

Bastien Sevajol (Algoo) 9 年前
父节点
当前提交
29f219819d
共有 3 个文件被更改,包括 44 次插入39 次删除
  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 查看文件

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

+ 1 - 1
tracim/tracim/config/middleware.py 查看文件

37
     
37
     
38
     # Wrap your base TurboGears 2 application with custom middleware here
38
     # Wrap your base TurboGears 2 application with custom middleware here
39
     daemons = DaemonsManager(app)
39
     daemons = DaemonsManager(app)
40
-    daemons.run(RadicaleDaemon.name, RadicaleDaemon)
40
+    daemons.run('radicale', RadicaleDaemon)
41
 
41
 
42
     return app
42
     return app

+ 42 - 37
tracim/tracim/lib/daemons.py 查看文件

2
 from wsgiref.simple_server import make_server
2
 from wsgiref.simple_server import make_server
3
 
3
 
4
 import signal
4
 import signal
5
+
5
 from radicale import Application as RadicaleApplication
6
 from radicale import Application as RadicaleApplication
6
 from radicale import HTTPServer as RadicaleHTTPServer
7
 from radicale import HTTPServer as RadicaleHTTPServer
7
 from radicale import HTTPSServer as RadicaleHTTPSServer
8
 from radicale import HTTPSServer as RadicaleHTTPSServer
16
     def __init__(self, app: TGApp):
17
     def __init__(self, app: TGApp):
17
         self._app = app
18
         self._app = app
18
         self._daemons = {}
19
         self._daemons = {}
20
+        signal.signal(signal.SIGTERM, lambda *_: self.stop_all())
21
+        signal.signal(signal.SIGINT, lambda *_: self.stop_all())
19
 
22
 
20
     def run(self, name: str, daemon_class: object, **kwargs) -> None:
23
     def run(self, name: str, daemon_class: object, **kwargs) -> None:
21
         """
24
         """
32
                 'Daemon with name "{0}" already running'.format(name)
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
         raise NotImplementedError()
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
 class RadicaleDaemon(Daemon):
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
         To see origin radical server start method, refer to
82
         To see origin radical server start method, refer to
78
         radicale.__main__.run
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
     def _prepare_config(self):
90
     def _prepare_config(self):
86
         from tracim.config.app_cfg import CFG
91
         from tracim.config.app_cfg import CFG