88 lines
2.5 KiB
Python
88 lines
2.5 KiB
Python
import json
|
|
import logging
|
|
import time
|
|
|
|
import asyncio
|
|
import aiohttp
|
|
|
|
from bigchaindb.common.utils import gen_timestamp
|
|
from bigchaindb.events import EventTypes, Event
|
|
from bigchaindb.tendermint.utils import decode_transaction_base64
|
|
|
|
|
|
HOST = 'localhost'
|
|
PORT = 46657
|
|
URL = f'ws://{HOST}:{PORT}/websocket'
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def connect_and_recv(event_queue):
|
|
session = aiohttp.ClientSession()
|
|
ws = yield from session.ws_connect(URL)
|
|
|
|
logger.info('Connected to tendermint ws server')
|
|
|
|
stream_id = "bigchaindb_stream_{}".format(gen_timestamp())
|
|
yield from subscribe_events(ws, stream_id)
|
|
|
|
while True:
|
|
msg = yield from ws.receive()
|
|
process_event(event_queue, msg.data, stream_id)
|
|
|
|
if msg.type in (aiohttp.WSMsgType.CLOSED,
|
|
aiohttp.WSMsgType.ERROR):
|
|
session.close()
|
|
raise aiohttp.ClientConnectionError()
|
|
|
|
|
|
def process_event(event_queue, event, stream_id):
|
|
event_stream_id = stream_id + '#event'
|
|
event = json.loads(event)
|
|
|
|
if (event['id'] == event_stream_id and event['result']['name'] == 'NewBlock'):
|
|
block = event['result']['data']['data']['block']
|
|
block_id = block['header']['height']
|
|
block_txs = block['data']['txs']
|
|
|
|
# Only push non empty blocks
|
|
if block_txs:
|
|
block_txs = [decode_transaction_base64(txn) for txn in block_txs]
|
|
new_block = {'id': str(block_id), 'transactions': block_txs}
|
|
event = Event(EventTypes.BLOCK_VALID, new_block)
|
|
event_queue.put(event)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def subscribe_events(ws, stream_id):
|
|
payload = {
|
|
"method": "subscribe",
|
|
"jsonrpc": "2.0",
|
|
"params": ["NewBlock"],
|
|
"id": stream_id
|
|
}
|
|
yield from ws.send_str(json.dumps(payload))
|
|
|
|
|
|
@asyncio.coroutine
|
|
def try_connect_and_recv(event_queue, max_tries):
|
|
try:
|
|
yield from connect_and_recv(event_queue)
|
|
|
|
except Exception as e:
|
|
if max_tries:
|
|
logger.warning('WebSocket connection failed with exception %s', e)
|
|
time.sleep(2)
|
|
yield from try_connect_and_recv(event_queue, max_tries-1)
|
|
else:
|
|
logger.exception('WebSocket connection failed with exception %s', e)
|
|
|
|
|
|
def start(event_queue):
|
|
loop = asyncio.get_event_loop()
|
|
try:
|
|
loop.run_until_complete(try_connect_and_recv(event_queue, 5))
|
|
except (KeyboardInterrupt, SystemExit):
|
|
logger.info('Shutting down Tendermint event stream connection')
|