From 5e9eb88bfcb0686f0b50ac77a36e495c66ab60a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 14:26:14 +0100 Subject: [PATCH 01/11] =?UTF-8?q?Implement=20crude=20FSMManager=20?= =?UTF-8?q?=E2=80=93=20wip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tfw/networking/server/tfw_server.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 8411bd4..2644ad1 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -36,6 +36,30 @@ class TFWServer: self.application.listen(port) +class FSMManager: + def __init__(self, fsm_type): + self.fsm = fsm_type() + self.trigger_handlers = {} + + def trigger(self, trigger): + self._prepare_handlerlist(trigger) + if all((handler() for handler in self.trigger_handlers[trigger])): + try: self.fsm.trigger(trigger, message='') + except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) + + def subscribe_handler(self, trigger, handler): + self._prepare_handlerlist(trigger) + self.trigger_handlers[trigger].append(handler) + + def unsubscribe_handler(self, trigger, handler): + self._prepare_handlerlist(trigger) + self.trigger_handlers[trigger].append(handler) + + def _prepare_handlerlist(self, trigger): + try: self.trigger_handlers[trigger] + except KeyError: self.trigger_handlers[trigger] = [] + + class FSMUpdater: def __init__(self, fsm): self.fsm = fsm From 47a4e078de4a28ded57b5181f0d021d7d6333e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:00:17 +0100 Subject: [PATCH 02/11] =?UTF-8?q?Replace=20homemade=20hacky=20defaultdict?= =?UTF-8?q?=20with=20defaultdict=20=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/tfw/networking/server/tfw_server.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 2644ad1..a3882d5 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -1,4 +1,5 @@ from tornado.web import Application +from collections import defaultdict from tfw.networking.server.controller_responder import ControllerResponder from tfw.networking.server.zmq_websocket_handler import ZMQWebSocketProxy @@ -39,26 +40,19 @@ class TFWServer: class FSMManager: def __init__(self, fsm_type): self.fsm = fsm_type() - self.trigger_handlers = {} + self.trigger_handlers = defaultdict(list) def trigger(self, trigger): - self._prepare_handlerlist(trigger) if all((handler() for handler in self.trigger_handlers[trigger])): try: self.fsm.trigger(trigger, message='') except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) def subscribe_handler(self, trigger, handler): - self._prepare_handlerlist(trigger) self.trigger_handlers[trigger].append(handler) def unsubscribe_handler(self, trigger, handler): - self._prepare_handlerlist(trigger) self.trigger_handlers[trigger].append(handler) - def _prepare_handlerlist(self, trigger): - try: self.trigger_handlers[trigger] - except KeyError: self.trigger_handlers[trigger] = [] - class FSMUpdater: def __init__(self, fsm): From 25fd71a2b8d7f76a136f4d209b89f74badaa99c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:01:26 +0100 Subject: [PATCH 03/11] Add message argument to FSMManager.trigger() --- lib/tfw/networking/server/tfw_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index a3882d5..0ce0b00 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -42,9 +42,9 @@ class FSMManager: self.fsm = fsm_type() self.trigger_handlers = defaultdict(list) - def trigger(self, trigger): + def trigger(self, trigger, message): if all((handler() for handler in self.trigger_handlers[trigger])): - try: self.fsm.trigger(trigger, message='') + try: self.fsm.trigger(trigger, message=message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) def subscribe_handler(self, trigger, handler): From 57764009902d27b4704e8bdbf73e5889f9227793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:02:06 +0100 Subject: [PATCH 04/11] Make FSMManager.fsm a property --- lib/tfw/networking/server/tfw_server.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 0ce0b00..4d9f8f6 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -39,9 +39,13 @@ class TFWServer: class FSMManager: def __init__(self, fsm_type): - self.fsm = fsm_type() + self._fsm = fsm_type() self.trigger_handlers = defaultdict(list) + @property + def fsm(self): + return self._fsm + def trigger(self, trigger, message): if all((handler() for handler in self.trigger_handlers[trigger])): try: self.fsm.trigger(trigger, message=message) From 50c940b21d7098d977a45ae13d5defacbd654582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:07:37 +0100 Subject: [PATCH 05/11] FSMManager no longer owns the managed FSM --- lib/tfw/networking/server/tfw_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 4d9f8f6..ff5a90c 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -38,8 +38,8 @@ class TFWServer: class FSMManager: - def __init__(self, fsm_type): - self._fsm = fsm_type() + def __init__(self, fsm): + self._fsm = fsm self.trigger_handlers = defaultdict(list) @property From 7e8ea0c7ac7def618651f810b3e54651f0ac8b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:08:29 +0100 Subject: [PATCH 06/11] Make FSM triggering dependent on FSMManager --- lib/tfw/networking/server/tfw_server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index ff5a90c..28aa242 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -12,6 +12,7 @@ class TFWServer: def __init__(self, fsm_type): self._fsm = fsm_type() self.fsm_updater = FSMUpdater(self._fsm) + self.fsm_manager = FSMManager(self._fsm) self._fsm.subscribe(self.fsm_updater.update) self.application = Application( @@ -26,7 +27,7 @@ class TFWServer: def make_response(self, message): trigger = message.get('trigger', '') - try: self.fsm.trigger(trigger, message=message) + try: self.fsm_manager.trigger(trigger, message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) return message From 78b689f650d9aa237735b08ae5b37e9db517788a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 15:54:10 +0100 Subject: [PATCH 07/11] Rename FSMManager handler -> predicate so it actually makes some sense --- lib/tfw/networking/server/tfw_server.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 28aa242..b73b762 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -41,22 +41,22 @@ class TFWServer: class FSMManager: def __init__(self, fsm): self._fsm = fsm - self.trigger_handlers = defaultdict(list) + self.trigger_predicates = defaultdict(list) @property def fsm(self): return self._fsm def trigger(self, trigger, message): - if all((handler() for handler in self.trigger_handlers[trigger])): + if all((predicate() for predicate in self.trigger_predicates[trigger])): try: self.fsm.trigger(trigger, message=message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) - def subscribe_handler(self, trigger, handler): - self.trigger_handlers[trigger].append(handler) + def subscribe_predicate(self, trigger, predicate): + self.trigger_predicates[trigger].append(predicate) - def unsubscribe_handler(self, trigger, handler): - self.trigger_handlers[trigger].append(handler) + def unsubscribe_predicate(self, trigger, predicate): + self.trigger_predicates[trigger].append(predicate) class FSMUpdater: From 250b9da6d674cfa2f7ce0e8f4d0e70a95d73930c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 16:20:28 +0100 Subject: [PATCH 08/11] Fix FSMManager.unsubscribe_predicate() --- lib/tfw/networking/server/tfw_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index b73b762..0ddcc34 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -56,7 +56,7 @@ class FSMManager: self.trigger_predicates[trigger].append(predicate) def unsubscribe_predicate(self, trigger, predicate): - self.trigger_predicates[trigger].append(predicate) + self.trigger_predicates[trigger].remove(predicate) class FSMUpdater: From 5d7223779a40368e336c293a0f03e5f4db948419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 17:47:35 +0100 Subject: [PATCH 09/11] Rework FSMManager predicate contract --- lib/tfw/networking/server/tfw_server.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 0ddcc34..252b79e 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -4,6 +4,7 @@ from collections import defaultdict from tfw.networking.server.controller_responder import ControllerResponder from tfw.networking.server.zmq_websocket_handler import ZMQWebSocketProxy from tfw.networking.event_handlers.server_connector import ServerUplinkConnector +from tfw.message_sender import MessageSender from tfw.config.logs import logging log = logging.getLogger(__name__) @@ -42,13 +43,20 @@ class FSMManager: def __init__(self, fsm): self._fsm = fsm self.trigger_predicates = defaultdict(list) + self.messenge_sender = MessageSender() @property def fsm(self): return self._fsm def trigger(self, trigger, message): - if all((predicate() for predicate in self.trigger_predicates[trigger])): + predicate_results = [] + for predicate in self.trigger_predicates[trigger]: + success, message = predicate() + predicate_results.append(success) + self.messenge_sender.send('FSM', message) + + if all(predicate_results): try: self.fsm.trigger(trigger, message=message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) From 770123310a6334d6051c56dbe91250ab33182f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Mon, 26 Feb 2018 17:52:34 +0100 Subject: [PATCH 10/11] Refactor FSMManager.(un)?subscribe() family of methods to accept lists --- lib/tfw/networking/server/tfw_server.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index 252b79e..f7a55c0 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -60,11 +60,12 @@ class FSMManager: try: self.fsm.trigger(trigger, message=message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) - def subscribe_predicate(self, trigger, predicate): - self.trigger_predicates[trigger].append(predicate) + def subscribe_predicate(self, trigger, *predicates): + self.trigger_predicates[trigger].extend(predicates) - def unsubscribe_predicate(self, trigger, predicate): - self.trigger_predicates[trigger].remove(predicate) + def unsubscribe_predicate(self, trigger, *predicates): + self.trigger_predicates[trigger] = [predicate for predicate in self.trigger_predicates[trigger] + not in predicates] class FSMUpdater: From f21036091c499d1836ff33f0504415c27592ae07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Tue, 27 Feb 2018 13:39:31 +0100 Subject: [PATCH 11/11] Expose TFWServer.fsm_manager as a property --- lib/tfw/networking/server/tfw_server.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/tfw/networking/server/tfw_server.py b/lib/tfw/networking/server/tfw_server.py index f7a55c0..da1f49e 100644 --- a/lib/tfw/networking/server/tfw_server.py +++ b/lib/tfw/networking/server/tfw_server.py @@ -12,9 +12,9 @@ log = logging.getLogger(__name__) class TFWServer: def __init__(self, fsm_type): self._fsm = fsm_type() - self.fsm_updater = FSMUpdater(self._fsm) - self.fsm_manager = FSMManager(self._fsm) - self._fsm.subscribe(self.fsm_updater.update) + self._fsm_updater = FSMUpdater(self._fsm) + self._fsm_manager = FSMManager(self._fsm) + self._fsm.subscribe(self._fsm_updater.update) self.application = Application( [(r'/ws', ZMQWebSocketProxy, {'make_response': self.make_response, @@ -26,9 +26,13 @@ class TFWServer: def fsm(self): return self._fsm + @property + def fsm_manager(self): + return self._fsm_manager + def make_response(self, message): trigger = message.get('trigger', '') - try: self.fsm_manager.trigger(trigger, message) + try: self._fsm_manager.trigger(trigger, message) except AttributeError: log.debug('FSM failed to execute nonexistent trigger: "{}"'.format(trigger)) return message