Added a simple state management system
This commit is contained in:
parent
41e75554ed
commit
b8bb9f8189
77
state_management.py
Normal file
77
state_management.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
from abots.helpers import generator, infinitedict
|
||||||
|
from gevent.lock import BoundedSemaphore
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
class AtomicDict(object):#dict):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
#dict.__init__(self, *args, **kwargs)
|
||||||
|
self._dict = dict()
|
||||||
|
self._lock = BoundedSemaphore()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self._lock.acquire()
|
||||||
|
return self._dict
|
||||||
|
|
||||||
|
def __exit__(self, _type, value, traceback):
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
|
def get_state(meta):
|
||||||
|
state = infinitedict()
|
||||||
|
with meta as m:
|
||||||
|
state = m.get("state")
|
||||||
|
assert state is not None, "'state' is missing"
|
||||||
|
|
||||||
|
return state.copy()
|
||||||
|
|
||||||
|
def unsubscribe(meta, listener):
|
||||||
|
with meta as m:
|
||||||
|
listeners = m.get("listeners")
|
||||||
|
assert listener in listeners, f"'{listener}' missing from: {listeners}"
|
||||||
|
listeners.remove(listener)
|
||||||
|
|
||||||
|
def subscribe(meta, listener):
|
||||||
|
with meta as m:
|
||||||
|
listeners = m.get("listeners")
|
||||||
|
assert listeners is not None, "'listeners' is missing"
|
||||||
|
listeners.append(listener)
|
||||||
|
|
||||||
|
return lambda: unsubscribe(meta, listener)
|
||||||
|
|
||||||
|
@generator
|
||||||
|
def dispatch(meta):
|
||||||
|
action = (yield)
|
||||||
|
|
||||||
|
with meta as m:
|
||||||
|
is_dispatching = m.get("is_dispatching")
|
||||||
|
assert is_dispatching is not None, "'is_dispatching' is missing"
|
||||||
|
if is_dispatching:
|
||||||
|
raise Exception("Reducers cannot dispatch actions")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with meta as m:
|
||||||
|
m["is_dispatching"] = True
|
||||||
|
reducer = m.get("reducer")
|
||||||
|
assert reducer is not None, "'reducer' is missing"
|
||||||
|
m["state"] = reducer(state, action)
|
||||||
|
finally:
|
||||||
|
with meta as m:
|
||||||
|
m["is_dispatching"] = False
|
||||||
|
|
||||||
|
with meta as m:
|
||||||
|
listeners = m.get("listeners")
|
||||||
|
assert listeners is not None, "'listeners' is missing"
|
||||||
|
for listener in listeners[:]:
|
||||||
|
listener()
|
||||||
|
|
||||||
|
def manager(reducer, initial_state=infinitedict()):
|
||||||
|
meta = AtomicDict()
|
||||||
|
with meta as m:
|
||||||
|
m["listeners"] = list()
|
||||||
|
m["is_dispatching"] = False
|
||||||
|
m["reducer"] = reducer
|
||||||
|
m["state"] = initial_state
|
||||||
|
|
||||||
|
return meta, dispatch(meta)
|
||||||
|
|
||||||
|
Action = namedtuple("Action", ["type", "payload"])
|
||||||
|
meta, actions = manager(reducer, {"init": False})
|
|
@ -1,5 +1,5 @@
|
||||||
|
from state_management =
|
||||||
from abots.helpers import generator, infinitedict
|
from abots.helpers import generator, infinitedict
|
||||||
#from queue import Queue, Empty
|
|
||||||
from time import monotonic as time
|
from time import monotonic as time
|
||||||
from gevent import Greenlet, sleep, joinall
|
from gevent import Greenlet, sleep, joinall
|
||||||
from gevent.queue import Queue, Empty
|
from gevent.queue import Queue, Empty
|
||||||
|
|
Loading…
Reference in New Issue
Block a user