wallet: put Sync and Verifier in their own TaskGroup, and that into interface.group
This commit is contained in:
@@ -26,11 +26,9 @@ import asyncio
|
||||
import itertools
|
||||
from collections import defaultdict
|
||||
|
||||
from aiorpcx import TaskGroup
|
||||
|
||||
from . import bitcoin
|
||||
from .bitcoin import COINBASE_MATURITY, TYPE_ADDRESS, TYPE_PUBKEY
|
||||
from .util import PrintError, profiler, bfh, VerifiedTxInfo, TxMinedStatus
|
||||
from .util import PrintError, profiler, bfh, VerifiedTxInfo, TxMinedStatus, aiosafe, CustomTaskGroup
|
||||
from .transaction import Transaction, TxOutput
|
||||
from .synchronizer import Synchronizer
|
||||
from .verifier import SPV
|
||||
@@ -62,6 +60,7 @@ class AddressSynchronizer(PrintError):
|
||||
self.synchronizer = None
|
||||
self.verifier = None
|
||||
self.sync_restart_lock = asyncio.Lock()
|
||||
self.group = None
|
||||
# locks: if you need to take multiple ones, acquire them in the order they are defined here!
|
||||
self.lock = threading.RLock()
|
||||
self.transaction_lock = threading.RLock()
|
||||
@@ -138,34 +137,45 @@ class AddressSynchronizer(PrintError):
|
||||
# add it in case it was previously unconfirmed
|
||||
self.add_unverified_tx(tx_hash, tx_height)
|
||||
|
||||
async def on_default_server_changed(self, evt):
|
||||
@aiosafe
|
||||
async def on_default_server_changed(self, event):
|
||||
async with self.sync_restart_lock:
|
||||
interface = self.network.interface
|
||||
if interface is None:
|
||||
return # we should get called again soon
|
||||
self.verifier = SPV(self.network, self)
|
||||
self.synchronizer = Synchronizer(self)
|
||||
await interface.group.spawn(self.verifier.main(interface))
|
||||
await interface.group.spawn(self.synchronizer.send_subscriptions(interface))
|
||||
await interface.group.spawn(self.synchronizer.handle_status(interface))
|
||||
await interface.group.spawn(self.synchronizer.main())
|
||||
self.stop_threads()
|
||||
await self._start_threads()
|
||||
|
||||
def start_threads(self, network):
|
||||
def start_network(self, network):
|
||||
self.network = network
|
||||
if self.network is not None:
|
||||
self.network.register_callback(self.on_default_server_changed, ['default_server_changed'])
|
||||
self.network.trigger_callback('default_server_changed')
|
||||
else:
|
||||
self.verifier = None
|
||||
self.synchronizer = None
|
||||
asyncio.run_coroutine_threadsafe(self._start_threads(), network.asyncio_loop)
|
||||
|
||||
async def _start_threads(self):
|
||||
interface = self.network.interface
|
||||
if interface is None:
|
||||
return # we should get called again soon
|
||||
|
||||
self.verifier = SPV(self.network, self)
|
||||
self.synchronizer = synchronizer = Synchronizer(self)
|
||||
assert self.group is None, 'group already exists'
|
||||
self.group = CustomTaskGroup()
|
||||
|
||||
async def job():
|
||||
async with self.group as group:
|
||||
await group.spawn(self.verifier.main(group))
|
||||
await group.spawn(self.synchronizer.send_subscriptions(group))
|
||||
await group.spawn(self.synchronizer.handle_status(group))
|
||||
await group.spawn(self.synchronizer.main())
|
||||
# we are being cancelled now
|
||||
interface.session.unsubscribe(synchronizer.status_queue)
|
||||
await interface.group.spawn(job)
|
||||
|
||||
def stop_threads(self):
|
||||
if self.network:
|
||||
#self.network.remove_jobs([self.verifier])
|
||||
self.synchronizer = None
|
||||
self.verifier = None
|
||||
# Now no references to the synchronizer or verifier
|
||||
# remain so they will be GC-ed
|
||||
if self.group:
|
||||
asyncio.run_coroutine_threadsafe(self.group.cancel_remaining(), self.network.asyncio_loop)
|
||||
self.group = None
|
||||
self.storage.put('stored_height', self.get_local_height())
|
||||
self.save_transactions()
|
||||
self.save_verified_tx()
|
||||
|
||||
Reference in New Issue
Block a user