-
Notifications
You must be signed in to change notification settings - Fork 20
#709 extract mempool service #710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f422848
97190e9
1a70b77
1903f44
9bb0ccf
6058114
386db34
a392798
84b9c23
9c46bad
c851c55
60d2930
b338993
01f86a5
3a695d5
66b1124
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from proxy.mempool.mempool_service import MemPoolService | ||
|
|
||
| mempool_service = MemPoolService() | ||
|
|
||
| mempool_service.start() | ||
| mempool_service.wait() | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import abc | ||
| import multiprocessing as mp | ||
| from multiprocessing.managers import BaseManager | ||
| from dataclasses import dataclass, astuple, field | ||
| from typing import Tuple, Dict, Any | ||
|
|
||
| from logged_groups import logged_group | ||
|
|
||
|
|
||
| @dataclass | ||
| class ServiceInvocation: | ||
| method_name: str = None | ||
| args: Tuple[Any] = field(default_factory=tuple) | ||
| kwargs: Dict[str, Any] = field(default_factory=dict) | ||
|
|
||
|
|
||
| class QueueBasedServiceClient: | ||
|
|
||
| def __init__(self, host: str, port: int): | ||
| class MemPoolQueueManager(BaseManager): | ||
| pass | ||
|
|
||
| MemPoolQueueManager.register('get_queue') | ||
| queue_manager = MemPoolQueueManager(address=(host, port), authkey=b'abracadabra') | ||
| queue_manager.connect() | ||
| self._queue = queue_manager.get_queue() | ||
|
|
||
| def invoke(self, method_name, *args, **kwargs): | ||
| invocation = ServiceInvocation(method_name=method_name, args=args, kwargs=kwargs) | ||
|
|
||
| self._queue.put(invocation) | ||
|
|
||
|
|
||
| @logged_group("neon") | ||
| class QueueBasedService(abc.ABC): | ||
|
|
||
| QUEUE_TIMEOUT_SEC = 10 | ||
| BREAK_PROC_INVOCATION = 0 | ||
| JOIN_PROC_TIMEOUT_SEC = 5 | ||
|
|
||
| def __init__(self, port: int): | ||
| self._queue = mp.Queue() | ||
| self._port = port | ||
|
|
||
| class MemPoolQueueManager(BaseManager): | ||
| pass | ||
|
|
||
| MemPoolQueueManager.register("get_queue", callable=lambda: self._queue) | ||
| self._queue_manager = MemPoolQueueManager(address=('', port), authkey=b'abracadabra') | ||
| self._mempool_server = self._queue_manager.get_server() | ||
| self._mempool_server_process = mp.Process(target=self._mempool_server.serve_forever) | ||
| self._timeout = self.QUEUE_TIMEOUT_SEC | ||
rozhkovdmitrii marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def start(self): | ||
| self.info(f"Starting queue server: {self._port}") | ||
| self._mempool_server_process.start() | ||
| self.run() | ||
|
|
||
| def run(self): | ||
| while True: | ||
| try: | ||
| if not self._run_impl(): | ||
| break | ||
| except BaseException as e: | ||
rozhkovdmitrii marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self.do_extras() | ||
| self.info("Processing has been finished") | ||
|
|
||
| def _run_impl(self) -> bool: | ||
|
|
||
rozhkovdmitrii marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| invocation = self._queue.get(block=True, timeout=self._timeout) | ||
| if invocation == self.BREAK_PROC_INVOCATION: | ||
| return False | ||
| self.dispatch(invocation) | ||
| return True | ||
|
|
||
| def dispatch(self, invocation: ServiceInvocation): | ||
| method_name, args, kwargs = astuple(invocation) | ||
| handler = getattr(self, method_name, None) | ||
| if handler is None: | ||
| raise NotImplementedError(f"Process has no handler for {handler}") | ||
| handler(*args, **kwargs) | ||
|
|
||
| def finish(self): | ||
| self._queue.put(self.BREAK_PROC_INVOCATION) | ||
| # self._mempool_queue_process.join(timeout=self.JOIN_PROC_TIMEOUT_SEC) | ||
| # self._mempool_service_process.join(timeout=self.JOIN_PROC_TIMEOUT_SEC) | ||
|
|
||
| @abc.abstractmethod | ||
| def do_extras(self): | ||
| assert "To be implemented in derived class" | ||
|
|
||
| def wait(self): | ||
| self._mempool_queue_process.join() | ||
| self._mempool_service_process.join() | ||
|
|
||
| def __del__(self): | ||
| self.finish() | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # from .mempool_service import MemPoolService | ||
| # from .mempool_client import MemPoolClient | ||
| # from .mem_pool import MemPool |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| from logged_groups import logged_group | ||
| from multiprocessing import Pool | ||
|
|
||
|
|
||
| @logged_group("neon.Proxy") | ||
|
||
| class MemPool: | ||
|
|
||
| POOL_PROC_COUNT = 4 | ||
|
|
||
| def __init__(self): | ||
| self._pool = Pool(processes=self.POOL_PROC_COUNT) | ||
|
|
||
| def on_eth_send_raw_transaction(self, *, eth_trx_hash): | ||
| self._pool.apply_async(self._on_eth_send_raw_transaction_impl, (eth_trx_hash,), {}, self.on_sending_trx_proceed, self.error_callback) | ||
|
|
||
| def error_callback(self, error): | ||
| self.error("Failed to invoke the function on worker process: ", error) | ||
|
|
||
| def on_sending_trx_proceed(self, result): | ||
| self.debug(f"Sending transaction proceed: {result}") | ||
|
|
||
| def _on_eth_send_raw_transaction_impl(self, eth_trx_hash): | ||
| self.debug(f"Transaction is being processed on the worker: {eth_trx_hash}") | ||
|
|
||
| def do_extras(self): | ||
| pass | ||
|
|
||
| def __getstate__(self): | ||
| self_dict = self.__dict__.copy() | ||
| del self_dict['_pool'] | ||
| return self_dict | ||
|
|
||
| def __setstate__(self, state): | ||
| self.__dict__.update(state) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from proxy.common_neon.utils import QueueBasedServiceClient | ||
| from logged_groups import logged_group | ||
| from .mempool_service import MemPoolService | ||
|
|
||
|
|
||
| @logged_group("neon") | ||
| class MemPoolClient(QueueBasedServiceClient): | ||
|
|
||
| MEM_POOL_SERVICE_HOST = "127.0.0.1" | ||
|
|
||
| def __init__(self): | ||
| self.info("Construct MemPoolClient") | ||
rozhkovdmitrii marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| QueueBasedServiceClient.__init__(self, "localhost", 9091) | ||
|
|
||
| def on_eth_send_raw_transaction(self, eth_trx_signature): | ||
| self.invoke("on_eth_send_raw_transaction", eth_trx_hash=eth_trx_signature) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| from logged_groups import logged_group | ||
|
|
||
| from ..common_neon.utils import QueueBasedService | ||
|
|
||
| from .mem_pool import MemPool | ||
rozhkovdmitrii marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| @logged_group("neon") | ||
| class MemPoolService(QueueBasedService): | ||
|
|
||
| MEM_POOL_SERVICE_PORT = 9091 | ||
|
|
||
| def __init__(self): | ||
| QueueBasedService.__init__(self, self.MEM_POOL_SERVICE_PORT) | ||
| self._mem_pool = MemPool() | ||
|
|
||
| def on_eth_send_raw_transaction(self, *, eth_trx_hash): | ||
| self._mem_pool.on_eth_send_raw_transaction(eth_trx_hash=eth_trx_hash) | ||
|
|
||
| def do_extras(self): | ||
| self._mem_pool.do_extras() | ||
|
|
||
| def __del__(self): | ||
| self.info("Delete Mempool service") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,19 @@ | ||
| # from .proxy import entry_point | ||
| from .mempool.MemPollService import MemPoolService | ||
| # from .statistics_exporter.prometheus_proxy_server import PrometheusProxyServer | ||
| from .proxy import entry_point | ||
| from .mempool.mempool_service import MemPoolService | ||
| from .statistics_exporter.prometheus_proxy_server import PrometheusProxyServer | ||
| import multiprocessing as mp | ||
|
|
||
|
|
||
| class NeonProxyApp: | ||
|
|
||
| def __init__(self): | ||
| self._mem_pool_service = MemPoolService() | ||
| self._mem_pool_process = mp.Process(target=NeonProxyApp.run_mempool_service) | ||
|
|
||
| def start(self): | ||
| # PrometheusProxyServer() | ||
| self._mem_pool_service.start() | ||
| # entry_point() | ||
| @staticmethod | ||
| def run_mempool_service(): | ||
| MemPoolService().start() | ||
|
|
||
| def __del__(self): | ||
| self._mem_pool_service.finish() | ||
| self._mem_pool_service.join(timeout=5) | ||
| def start(self): | ||
| PrometheusProxyServer() | ||
| self._mem_pool_process.start() | ||
| entry_point() |
Uh oh!
There was an error while loading. Please reload this page.