2018-11-03 23:50:34 +01:00
|
|
|
import signal
|
|
|
|
import logging
|
|
|
|
import asyncio
|
2019-01-25 15:57:45 +01:00
|
|
|
from concurrent.futures.thread import ThreadPoolExecutor
|
2020-01-13 21:52:31 +01:00
|
|
|
import typing
|
2018-11-03 23:50:34 +01:00
|
|
|
|
2019-12-31 20:52:57 +01:00
|
|
|
import lbry
|
2021-07-16 20:51:10 +02:00
|
|
|
from lbry.wallet.server.mempool import MemPool
|
|
|
|
from lbry.wallet.server.block_processor import BlockProcessor
|
|
|
|
from lbry.wallet.server.leveldb import LevelDB
|
|
|
|
from lbry.wallet.server.session import LBRYSessionManager
|
2020-04-24 02:21:27 +02:00
|
|
|
from lbry.prometheus import PrometheusServer
|
2018-11-03 23:50:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Server:
|
|
|
|
|
|
|
|
def __init__(self, env):
|
|
|
|
self.env = env
|
|
|
|
self.log = logging.getLogger(__name__).getChild(self.__class__.__name__)
|
|
|
|
self.shutdown_event = asyncio.Event()
|
|
|
|
self.cancellable_tasks = []
|
|
|
|
|
2018-11-04 06:55:50 +01:00
|
|
|
self.daemon = daemon = env.coin.DAEMON(env.coin, env.daemon_url)
|
2021-07-16 20:51:10 +02:00
|
|
|
self.db = db = LevelDB(env)
|
|
|
|
self.mempool = mempool = MemPool(env.coin, daemon, db)
|
|
|
|
self.bp = bp = BlockProcessor(env, db, daemon, mempool, self.shutdown_event)
|
2020-01-13 21:52:31 +01:00
|
|
|
self.prometheus_server: typing.Optional[PrometheusServer] = None
|
2018-11-03 23:50:34 +01:00
|
|
|
|
2021-07-16 20:51:10 +02:00
|
|
|
self.session_mgr = LBRYSessionManager(
|
2018-11-03 23:50:34 +01:00
|
|
|
env, db, bp, daemon, mempool, self.shutdown_event
|
|
|
|
)
|
2021-01-17 09:40:39 +01:00
|
|
|
self._indexer_task = None
|
2018-11-03 23:50:34 +01:00
|
|
|
|
2018-11-04 06:55:50 +01:00
|
|
|
async def start(self):
|
|
|
|
env = self.env
|
|
|
|
min_str, max_str = env.coin.SESSIONCLS.protocol_min_max_strings()
|
2019-12-31 20:52:57 +01:00
|
|
|
self.log.info(f'software version: {lbry.__version__}')
|
2018-11-04 06:55:50 +01:00
|
|
|
self.log.info(f'supported protocol versions: {min_str}-{max_str}')
|
|
|
|
self.log.info(f'event loop policy: {env.loop_policy}')
|
|
|
|
self.log.info(f'reorg limit is {env.reorg_limit:,d} blocks')
|
|
|
|
|
|
|
|
await self.daemon.height()
|
2018-11-03 23:50:34 +01:00
|
|
|
|
|
|
|
def _start_cancellable(run, *args):
|
|
|
|
_flag = asyncio.Event()
|
|
|
|
self.cancellable_tasks.append(asyncio.ensure_future(run(*args, _flag)))
|
|
|
|
return _flag.wait()
|
|
|
|
|
2021-01-21 22:01:33 +01:00
|
|
|
await self.start_prometheus()
|
2021-03-12 17:00:30 +01:00
|
|
|
if self.env.udp_port:
|
|
|
|
await self.bp.status_server.start(
|
2021-05-21 20:31:03 +02:00
|
|
|
0, bytes.fromhex(self.bp.coin.GENESIS_HASH)[::-1], self.env.country,
|
2021-04-28 21:28:00 +02:00
|
|
|
self.env.host, self.env.udp_port, self.env.allow_lan_udp
|
2021-03-12 17:00:30 +01:00
|
|
|
)
|
2018-11-04 06:55:50 +01:00
|
|
|
await _start_cancellable(self.bp.fetch_and_process_blocks)
|
2021-01-21 22:08:33 +01:00
|
|
|
|
2018-11-04 06:55:50 +01:00
|
|
|
await self.db.populate_header_merkle_cache()
|
|
|
|
await _start_cancellable(self.mempool.keep_synchronized)
|
2021-07-16 20:51:10 +02:00
|
|
|
await _start_cancellable(self.session_mgr.serve, self.mempool)
|
2018-11-03 23:50:34 +01:00
|
|
|
|
2018-12-14 22:15:59 +01:00
|
|
|
async def stop(self):
|
2018-11-03 23:50:34 +01:00
|
|
|
for task in reversed(self.cancellable_tasks):
|
|
|
|
task.cancel()
|
2018-12-14 22:15:59 +01:00
|
|
|
await asyncio.wait(self.cancellable_tasks)
|
2020-01-13 21:52:31 +01:00
|
|
|
if self.prometheus_server:
|
|
|
|
await self.prometheus_server.stop()
|
|
|
|
self.prometheus_server = None
|
2018-12-13 00:13:08 +01:00
|
|
|
self.shutdown_event.set()
|
2019-07-14 05:46:22 +02:00
|
|
|
await self.daemon.close()
|
2018-11-03 23:50:34 +01:00
|
|
|
|
|
|
|
def run(self):
|
|
|
|
loop = asyncio.get_event_loop()
|
2019-01-25 15:57:45 +01:00
|
|
|
executor = ThreadPoolExecutor(1)
|
|
|
|
loop.set_default_executor(executor)
|
2019-01-25 01:40:24 +01:00
|
|
|
|
|
|
|
def __exit():
|
|
|
|
raise SystemExit()
|
2018-11-03 23:50:34 +01:00
|
|
|
try:
|
2019-01-25 01:40:24 +01:00
|
|
|
loop.add_signal_handler(signal.SIGINT, __exit)
|
|
|
|
loop.add_signal_handler(signal.SIGTERM, __exit)
|
2018-11-03 23:50:34 +01:00
|
|
|
loop.run_until_complete(self.start())
|
2019-01-25 22:30:19 +01:00
|
|
|
loop.run_until_complete(self.shutdown_event.wait())
|
2019-01-25 01:40:24 +01:00
|
|
|
except (SystemExit, KeyboardInterrupt):
|
|
|
|
pass
|
2018-11-03 23:50:34 +01:00
|
|
|
finally:
|
2019-01-25 01:40:24 +01:00
|
|
|
loop.run_until_complete(self.stop())
|
2019-01-25 22:30:19 +01:00
|
|
|
executor.shutdown(True)
|
2020-01-13 21:52:31 +01:00
|
|
|
|
|
|
|
async def start_prometheus(self):
|
|
|
|
if not self.prometheus_server and self.env.prometheus_port:
|
|
|
|
self.prometheus_server = PrometheusServer()
|
2020-04-24 02:21:27 +02:00
|
|
|
await self.prometheus_server.start("0.0.0.0", self.env.prometheus_port)
|