mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Rename things, add tests
This commit is contained in:
parent
21a7da1c9d
commit
a0cbb63db8
@ -6,6 +6,8 @@ POISON_PILL = 'POISON_PILL'
|
|||||||
|
|
||||||
|
|
||||||
class EventTypes:
|
class EventTypes:
|
||||||
|
"""Container class that holds all the possible
|
||||||
|
events BigchainDB manages."""
|
||||||
|
|
||||||
ALL = ~0
|
ALL = ~0
|
||||||
BLOCK_VALID = 1
|
BLOCK_VALID = 1
|
||||||
@ -16,37 +18,69 @@ class EventTypes:
|
|||||||
|
|
||||||
|
|
||||||
class Event:
|
class Event:
|
||||||
|
"""An Event."""
|
||||||
|
|
||||||
def __init__(self, event_type, event_data):
|
def __init__(self, event_type, event_data):
|
||||||
|
"""Creates a new event.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
event_type (int): the type of the event, see
|
||||||
|
:class:`~bigchaindb.events.EventTypes`
|
||||||
|
event_data (obj): the data of the event.
|
||||||
|
"""
|
||||||
|
|
||||||
self.type = event_type
|
self.type = event_type
|
||||||
self.data = event_data
|
self.data = event_data
|
||||||
|
|
||||||
|
|
||||||
class PubSub:
|
class Exchange:
|
||||||
|
"""Dispatch events to subscribers."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.publisher_queue = Queue()
|
self.publisher_queue = Queue()
|
||||||
|
|
||||||
# Map <event_types -> queues>
|
# Map <event_types -> queues>
|
||||||
self.queues = defaultdict(list)
|
self.queues = defaultdict(list)
|
||||||
|
|
||||||
def get_publisher_queue(self):
|
def get_publisher_queue(self):
|
||||||
|
"""Get the queue used by the publisher.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a :class:`multiprocessing.Queue`.
|
||||||
|
"""
|
||||||
|
|
||||||
return self.publisher_queue
|
return self.publisher_queue
|
||||||
|
|
||||||
def get_subscriber_queue(self, event_types=EventTypes.ALL):
|
def get_subscriber_queue(self, event_types=EventTypes.ALL):
|
||||||
|
"""Create a new queue for a specific combination of event types
|
||||||
|
and return it.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a :class:`multiprocessing.Queue`.
|
||||||
|
"""
|
||||||
queue = Queue()
|
queue = Queue()
|
||||||
self.queues[event_types].append(queue)
|
self.queues[event_types].append(queue)
|
||||||
return queue
|
return queue
|
||||||
|
|
||||||
def publish(self, event):
|
def dispatch(self, event):
|
||||||
|
"""Given an event, send it to all the subscribers.
|
||||||
|
|
||||||
|
Args
|
||||||
|
event (:class:`~bigchaindb.events.EventTypes`): the event to
|
||||||
|
dispatch to all the subscribers.
|
||||||
|
"""
|
||||||
|
|
||||||
for event_types, queues in self.queues.items():
|
for event_types, queues in self.queues.items():
|
||||||
if event.type & event_types:
|
if event.type & event_types:
|
||||||
for queue in queues:
|
for queue in queues:
|
||||||
queue.put(event)
|
queue.put(event)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
"""Start the exchange"""
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
event = self.publisher_queue.get()
|
event = self.publisher_queue.get()
|
||||||
if event is POISON_PILL:
|
if event is POISON_PILL:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.publish(event)
|
self.dispatch(event)
|
||||||
|
@ -2,9 +2,9 @@ import logging
|
|||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
|
|
||||||
import bigchaindb
|
import bigchaindb
|
||||||
from bigchaindb.config_utils import load_events_plugins
|
from bigchaindb import config_utils
|
||||||
from bigchaindb.pipelines import vote, block, election, stale
|
from bigchaindb.pipelines import vote, block, election, stale
|
||||||
from bigchaindb.events import PubSub
|
from bigchaindb.events import Exchange
|
||||||
from bigchaindb.web import server, websocket_server
|
from bigchaindb.web import server, websocket_server
|
||||||
|
|
||||||
|
|
||||||
@ -24,14 +24,15 @@ BANNER = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def start_events_plugins(pubsub):
|
def start_events_plugins(exchange):
|
||||||
plugins = load_events_plugins(bigchaindb.config.get('events_plugins'))
|
plugins = config_utils.load_events_plugins(
|
||||||
|
bigchaindb.config.get('events_plugins'))
|
||||||
|
|
||||||
for name, plugin in plugins:
|
for name, plugin in plugins:
|
||||||
logger.info('Loading events plugin %s', name)
|
logger.info('Loading events plugin %s', name)
|
||||||
|
|
||||||
event_types = getattr(plugin, 'event_types', None)
|
event_types = getattr(plugin, 'event_types', None)
|
||||||
queue = pubsub.get_subscriber_queue(event_types)
|
queue = exchange.get_subscriber_queue(event_types)
|
||||||
|
|
||||||
mp.Process(name='events_plugin_{}'.format(name),
|
mp.Process(name='events_plugin_{}'.format(name),
|
||||||
target=plugin.run,
|
target=plugin.run,
|
||||||
@ -41,12 +42,12 @@ def start_events_plugins(pubsub):
|
|||||||
def start():
|
def start():
|
||||||
logger.info('Initializing BigchainDB...')
|
logger.info('Initializing BigchainDB...')
|
||||||
|
|
||||||
# Create a PubSub object.
|
# Create a Exchange object.
|
||||||
# The events queue needs to be initialized once and shared between
|
# The events queue needs to be initialized once and shared between
|
||||||
# processes. This seems the best way to do it
|
# processes. This seems the best way to do it
|
||||||
# At this point only the election processs and the event consumer require
|
# At this point only the election processs and the event consumer require
|
||||||
# this queue.
|
# this queue.
|
||||||
pubsub = PubSub()
|
exchange = Exchange()
|
||||||
|
|
||||||
# start the processes
|
# start the processes
|
||||||
logger.info('Starting block')
|
logger.info('Starting block')
|
||||||
@ -59,7 +60,7 @@ def start():
|
|||||||
stale.start()
|
stale.start()
|
||||||
|
|
||||||
logger.info('Starting election')
|
logger.info('Starting election')
|
||||||
election.start(events_queue=pubsub.get_publisher_queue())
|
election.start(events_queue=exchange.get_publisher_queue())
|
||||||
|
|
||||||
# start the web api
|
# start the web api
|
||||||
app_server = server.create_server(bigchaindb.config['server'])
|
app_server = server.create_server(bigchaindb.config['server'])
|
||||||
@ -69,12 +70,12 @@ def start():
|
|||||||
logger.info('WebSocket server started')
|
logger.info('WebSocket server started')
|
||||||
p_websocket_server = mp.Process(name='ws',
|
p_websocket_server = mp.Process(name='ws',
|
||||||
target=websocket_server.start,
|
target=websocket_server.start,
|
||||||
args=(pubsub.get_subscriber_queue(),))
|
args=(exchange.get_subscriber_queue(),))
|
||||||
p_websocket_server.start()
|
p_websocket_server.start()
|
||||||
|
|
||||||
# start message
|
# start message
|
||||||
logger.info(BANNER.format(bigchaindb.config['server']['bind']))
|
logger.info(BANNER.format(bigchaindb.config['server']['bind']))
|
||||||
|
|
||||||
start_events_plugins(pubsub)
|
start_events_plugins(exchange)
|
||||||
|
|
||||||
pubsub.run()
|
exchange.run()
|
||||||
|
@ -202,10 +202,10 @@ def test_full_pipeline(b, user_pk):
|
|||||||
|
|
||||||
|
|
||||||
def test_handle_block_events():
|
def test_handle_block_events():
|
||||||
from bigchaindb.events import PubSub, EventTypes
|
from bigchaindb.events import Exchange, EventTypes
|
||||||
|
|
||||||
pubsub = PubSub()
|
exchange = Exchange()
|
||||||
events_queue = pubsub.get_publisher_queue()
|
events_queue = exchange.get_publisher_queue()
|
||||||
e = election.Election(events_queue=events_queue)
|
e = election.Election(events_queue=events_queue)
|
||||||
block_id = 'a' * 64
|
block_id = 'a' * 64
|
||||||
|
|
||||||
|
@ -80,13 +80,13 @@ def test_load_consensus_plugin_raises_with_invalid_subclass(monkeypatch):
|
|||||||
config_utils.load_consensus_plugin(str(time.time()))
|
config_utils.load_consensus_plugin(str(time.time()))
|
||||||
|
|
||||||
|
|
||||||
def test_load_block_publisher(monkeypatch):
|
def test_load_events_plugins(monkeypatch):
|
||||||
from bigchaindb import config_utils
|
from bigchaindb import config_utils
|
||||||
monkeypatch.setattr(config_utils,
|
monkeypatch.setattr(config_utils,
|
||||||
'iter_entry_points',
|
'iter_entry_points',
|
||||||
lambda *args: [type('entry_point', (object, ), {'load': lambda: object})])
|
lambda *args: [type('entry_point', (object, ), {'load': lambda: object})])
|
||||||
|
|
||||||
plugins = config_utils.load_block_publisher_plugins(['one', 'two'])
|
plugins = config_utils.load_events_plugins(['one', 'two'])
|
||||||
assert len(plugins) == 2
|
assert len(plugins) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
def test_event_handler():
|
def test_event_handler():
|
||||||
from bigchaindb.events import EventTypes, Event, PubSub
|
from bigchaindb.events import EventTypes, Event, Exchange
|
||||||
|
|
||||||
# create and event
|
# create and event
|
||||||
event_data = {'msg': 'some data'}
|
event_data = {'msg': 'some data'}
|
||||||
event = Event(EventTypes.BLOCK_VALID, event_data)
|
event = Event(EventTypes.BLOCK_VALID, event_data)
|
||||||
|
|
||||||
# create the events pub sub
|
# create the events pub sub
|
||||||
pubsub = PubSub()
|
exchange = Exchange()
|
||||||
|
|
||||||
sub0 = pubsub.get_subscriber_queue(EventTypes.BLOCK_VALID)
|
sub0 = exchange.get_subscriber_queue(EventTypes.BLOCK_VALID)
|
||||||
sub1 = pubsub.get_subscriber_queue(EventTypes.BLOCK_VALID |
|
sub1 = exchange.get_subscriber_queue(EventTypes.BLOCK_VALID |
|
||||||
EventTypes.BLOCK_INVALID)
|
EventTypes.BLOCK_INVALID)
|
||||||
# Subscribe to all events
|
# Subscribe to all events
|
||||||
sub2 = pubsub.get_subscriber_queue()
|
sub2 = exchange.get_subscriber_queue()
|
||||||
sub3 = pubsub.get_subscriber_queue(EventTypes.BLOCK_INVALID)
|
sub3 = exchange.get_subscriber_queue(EventTypes.BLOCK_INVALID)
|
||||||
|
|
||||||
# push and event to the queue
|
# push and event to the queue
|
||||||
pubsub.publish(event)
|
exchange.dispatch(event)
|
||||||
|
|
||||||
# get the event from the queue
|
# get the event from the queue
|
||||||
event_sub0 = sub0.get()
|
event_sub0 = sub0.get()
|
||||||
|
@ -9,9 +9,9 @@ from bigchaindb.pipelines import vote, block, election, stale
|
|||||||
@patch.object(block, 'start')
|
@patch.object(block, 'start')
|
||||||
@patch.object(vote, 'start')
|
@patch.object(vote, 'start')
|
||||||
@patch.object(Process, 'start')
|
@patch.object(Process, 'start')
|
||||||
@patch('bigchaindb.events.PubSub.get_publisher_queue', spec_set=True, autospec=True)
|
@patch('bigchaindb.events.Exchange.get_publisher_queue', spec_set=True, autospec=True)
|
||||||
@patch('bigchaindb.events.PubSub.run', spec_set=True, autospec=True)
|
@patch('bigchaindb.events.Exchange.run', spec_set=True, autospec=True)
|
||||||
def test_processes_start(mock_pub_sub_run, mock_pub_sub, mock_process, mock_vote,
|
def test_processes_start(mock_exchange_run, mock_exchange, mock_process, mock_vote,
|
||||||
mock_block, mock_election, mock_stale):
|
mock_block, mock_election, mock_stale):
|
||||||
from bigchaindb import processes
|
from bigchaindb import processes
|
||||||
|
|
||||||
@ -22,4 +22,26 @@ def test_processes_start(mock_pub_sub_run, mock_pub_sub, mock_process, mock_vote
|
|||||||
mock_stale.assert_called_with()
|
mock_stale.assert_called_with()
|
||||||
mock_process.assert_called_with()
|
mock_process.assert_called_with()
|
||||||
mock_election.assert_called_once_with(
|
mock_election.assert_called_once_with(
|
||||||
events_queue=mock_pub_sub.return_value)
|
events_queue=mock_exchange.return_value)
|
||||||
|
|
||||||
|
|
||||||
|
@patch.object(Process, 'start')
|
||||||
|
def test_start_events_plugins(mock_process, monkeypatch):
|
||||||
|
|
||||||
|
class MockPlugin:
|
||||||
|
def __init__(self, event_types):
|
||||||
|
self.event_types = event_types
|
||||||
|
|
||||||
|
def run(self, queue):
|
||||||
|
pass
|
||||||
|
|
||||||
|
monkeypatch.setattr('bigchaindb.config_utils.load_events_plugins',
|
||||||
|
lambda names: [('one', MockPlugin(1)),
|
||||||
|
('two', MockPlugin(2))])
|
||||||
|
|
||||||
|
from bigchaindb import processes
|
||||||
|
from bigchaindb.events import Exchange
|
||||||
|
|
||||||
|
exchange = Exchange()
|
||||||
|
processes.start_events_plugins(exchange)
|
||||||
|
assert len(exchange.queues) == 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user