mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-09-05 02:24:21 -05:00
* Prority locking to consensus * Remove pstats * Linting * Do some stuff outside of lock * Fix startup * Add log timings * Try some different locking * Add limit * catch excp * CLVM inside lock * Try using a semaphore instead * use events for lock queue * test * Add logging for message types * type * remove seed * check new peak waiters * correct FullNodeAPI self.full_node.new_peak._waiters typo * correct logging string typos * only warn about new_peak Waiters if there is at least 1 * remove no-longer-accepted parameter to FullNode.peak_post_processing() * only warn about respond_transaction Waiters if there is at least 1 * lint * Change some constants * Small fix and logging changes * Put message types outside * Change some log levels so we can test with info * More logging * Increase rate limits but decrease paralelism * tweaks * Log dropped tx * Fix pool rpc test * Test fixes * Mempool optimization * Remove from seen if fails * Increase queue sizes * Message types info * More test and logging * Small changes to networking just in case * Decrease logging * Decrease logging even further * Decrease logging even further even further * Decrease logging 3 * Transaction queue * Don't cancel tasks or close connection * Cancel tasks on disconnect (for shutdown purposed) * Fix typo * Catch cancelled * Do multiple at a time * More accurate farmer response time * More efficiently create tasks * Increase queue size and priority by fee * Revert priority * Don't re-request too many times for dropped TX * Handle cancelled error so we don't go into a bad state * Catch cancelled in syncing tasks * Reduce new_peak_sem to improve performance * Less bytes conversion * Missing file, and 2 workers for CLVM * Validate BLS in a new thread * tests * Change semaphore constants * correct a cancellation triggered exception and assertion * Fix send_transaction, dont use BaseException, fix tests * Fix more tests * only log transaction handler cancellation in debug * typing in log * move unfinished validation to diff proc * it is asyncio.CancelledError * Add a test for bad signature * Fix more tests, reduce logging, lint * One more lint * blockchain tests, pass bytes directly, single call * Try to fix rl_wallet failures * Fix mempool test * catch everything * Don't test RL wallet * Fix more tests and return error code * Improve error handling in multiprocess * Add pre-validation time * Add pre-validation time in logs, and revert pytest.ini changes * Add log correctly * Ms.bls cache experiment (#9115) * Logging for cache * Less logging * Return to original plan * Clean up * Remove coment * Remove log * formalize LockQueue shutdown * Comments * Fix blockchain test * Improve cache * Remove logs * Fix sign_coin_spends * Fix pool wallet Co-authored-by: Kyle Altendorf <sda@fstab.net> Co-authored-by: Yostra <straya@chia.net>
86 lines
2.6 KiB
Python
86 lines
2.6 KiB
Python
import asyncio
|
|
import dataclasses
|
|
import logging
|
|
import traceback
|
|
from typing import Awaitable, Callable
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True, order=True)
|
|
class PrioritizedCallable:
|
|
priority: int
|
|
af: Callable[[], Awaitable[object]] = dataclasses.field(compare=False)
|
|
|
|
|
|
class LockQueue:
|
|
"""
|
|
The purpose of this class is to be able to control access to a lock, and give priority to certain clients
|
|
(LockClients). To use it, create a lock and clients:
|
|
```
|
|
my_lock = LockQueue(asyncio.Lock())
|
|
client_a = LockClient(0, my_lock)
|
|
client_b = LockClient(1, my_lock)
|
|
|
|
async with client_a:
|
|
...
|
|
```
|
|
|
|
The clients can be used like normal async locks, but the higher priority (lower number) will always go first.
|
|
Must be created under an asyncio running loop, and close and await_closed should be called.
|
|
"""
|
|
|
|
def __init__(self, inner_lock: asyncio.Lock):
|
|
self._inner_lock: asyncio.Lock = inner_lock
|
|
self._task_queue: asyncio.PriorityQueue = asyncio.PriorityQueue()
|
|
self._run_task = asyncio.create_task(self._run())
|
|
self._release_event = asyncio.Event()
|
|
|
|
async def put(self, priority: int, callback: Callable[[], Awaitable[object]]):
|
|
await self._task_queue.put(PrioritizedCallable(priority=priority, af=callback))
|
|
|
|
async def acquire(self):
|
|
await self._inner_lock.acquire()
|
|
|
|
def release(self):
|
|
self._inner_lock.release()
|
|
self._release_event.set()
|
|
|
|
async def _run(self):
|
|
try:
|
|
while True:
|
|
prioritized_callback = await self._task_queue.get()
|
|
self._release_event = asyncio.Event()
|
|
await self.acquire()
|
|
await prioritized_callback.af()
|
|
await self._release_event.wait()
|
|
except asyncio.CancelledError:
|
|
error_stack = traceback.format_exc()
|
|
log.debug(f"LockQueue._run() cancelled: {error_stack}")
|
|
|
|
def close(self):
|
|
self._run_task.cancel()
|
|
|
|
async def await_closed(self):
|
|
await self._run_task
|
|
|
|
|
|
class LockClient:
|
|
def __init__(self, priority: int, queue: LockQueue):
|
|
self._priority = priority
|
|
self._queue = queue
|
|
|
|
async def __aenter__(self):
|
|
called: asyncio.Event = asyncio.Event()
|
|
|
|
# Use a parameter default to avoid a closure
|
|
async def callback(called=called) -> None:
|
|
called.set()
|
|
|
|
await self._queue.put(priority=self._priority, callback=callback)
|
|
await called.wait()
|
|
|
|
async def __aexit__(self, exc_type, exc, tb):
|
|
self._queue.release()
|