Introduce webserver mode for fastapi
This commit is contained in:
parent
800e314bfd
commit
02b84bd018
@ -1,7 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -29,9 +28,14 @@ def start_trading(args: Dict[str, Any]) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def start_webserver(args: Dict[str, Any]) -> int:
|
def start_webserver(args: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Main entry point for webserver mode
|
Main entry point for webserver mode
|
||||||
"""
|
"""
|
||||||
|
from freqtrade.rpc.api_server import ApiServer
|
||||||
|
from freqtrade.configuration import Configuration
|
||||||
|
from freqtrade.enums import RunMode
|
||||||
|
|
||||||
print(args)
|
# Initialize configuration
|
||||||
|
config = Configuration(args, RunMode.WEBSERVER).get_config()
|
||||||
|
ApiServer(config, standalone=True)
|
||||||
|
@ -14,6 +14,7 @@ class RunMode(Enum):
|
|||||||
UTIL_EXCHANGE = "util_exchange"
|
UTIL_EXCHANGE = "util_exchange"
|
||||||
UTIL_NO_EXCHANGE = "util_no_exchange"
|
UTIL_NO_EXCHANGE = "util_no_exchange"
|
||||||
PLOT = "plot"
|
PLOT = "plot"
|
||||||
|
WEBSERVER = "webserver"
|
||||||
OTHER = "other"
|
OTHER = "other"
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ from fastapi import Depends, FastAPI
|
|||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from starlette.responses import JSONResponse
|
from starlette.responses import JSONResponse
|
||||||
|
|
||||||
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
|
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
|
||||||
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
||||||
|
|
||||||
@ -28,16 +29,30 @@ class FTJSONResponse(JSONResponse):
|
|||||||
|
|
||||||
class ApiServer(RPCHandler):
|
class ApiServer(RPCHandler):
|
||||||
|
|
||||||
|
__instance = None
|
||||||
|
__initialized = False
|
||||||
|
|
||||||
_rpc: RPC
|
_rpc: RPC
|
||||||
_has_rpc: bool = False
|
_has_rpc: bool = False
|
||||||
_config: Dict[str, Any] = {}
|
_config: Dict[str, Any] = {}
|
||||||
|
|
||||||
def __init__(self, rpc: RPC, config: Dict[str, Any]) -> None:
|
def __new__(cls, *args, **kwargs):
|
||||||
super().__init__(rpc, config)
|
"""
|
||||||
|
This class is a singleton.
|
||||||
|
We'll only have one instance of it around.
|
||||||
|
"""
|
||||||
|
if ApiServer.__instance is None:
|
||||||
|
ApiServer.__instance = object.__new__(cls)
|
||||||
|
ApiServer.__initialized = False
|
||||||
|
return ApiServer.__instance
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any], standalone: bool = False) -> None:
|
||||||
|
if self.__initialized and (standalone or self._standalone):
|
||||||
|
return
|
||||||
|
self._standalone: bool = standalone
|
||||||
|
self._config = config
|
||||||
self._server = None
|
self._server = None
|
||||||
|
|
||||||
ApiServer._rpc = rpc
|
|
||||||
ApiServer._has_rpc = True
|
|
||||||
ApiServer._config = config
|
ApiServer._config = config
|
||||||
api_config = self._config['api_server']
|
api_config = self._config['api_server']
|
||||||
|
|
||||||
@ -50,6 +65,18 @@ class ApiServer(RPCHandler):
|
|||||||
|
|
||||||
self.start_api()
|
self.start_api()
|
||||||
|
|
||||||
|
def add_rpc_handler(self, rpc: RPC):
|
||||||
|
"""
|
||||||
|
Attach rpc handler
|
||||||
|
"""
|
||||||
|
if not self._rpc:
|
||||||
|
self._rpc = rpc
|
||||||
|
ApiServer._rpc = rpc
|
||||||
|
ApiServer._has_rpc = True
|
||||||
|
else:
|
||||||
|
# This should not happen assuming we didn't mess up.
|
||||||
|
raise OperationalException('RPC Handler already attached.')
|
||||||
|
|
||||||
def cleanup(self) -> None:
|
def cleanup(self) -> None:
|
||||||
""" Cleanup pending module resources """
|
""" Cleanup pending module resources """
|
||||||
if self._server:
|
if self._server:
|
||||||
|
@ -36,15 +36,16 @@ class RPCManager:
|
|||||||
if config.get('api_server', {}).get('enabled', False):
|
if config.get('api_server', {}).get('enabled', False):
|
||||||
logger.info('Enabling rpc.api_server')
|
logger.info('Enabling rpc.api_server')
|
||||||
from freqtrade.rpc.api_server import ApiServer
|
from freqtrade.rpc.api_server import ApiServer
|
||||||
|
apiserver = ApiServer(config)
|
||||||
self.registered_modules.append(ApiServer(self._rpc, config))
|
apiserver.add_rpc_handler(self._rpc)
|
||||||
|
self.registered_modules.append(apiserver)
|
||||||
|
|
||||||
def cleanup(self) -> None:
|
def cleanup(self) -> None:
|
||||||
""" Stops all enabled rpc modules """
|
""" Stops all enabled rpc modules """
|
||||||
logger.info('Cleaning up rpc modules ...')
|
logger.info('Cleaning up rpc modules ...')
|
||||||
while self.registered_modules:
|
while self.registered_modules:
|
||||||
mod = self.registered_modules.pop()
|
mod = self.registered_modules.pop()
|
||||||
logger.debug('Cleaning up rpc.%s ...', mod.name)
|
logger.info('Cleaning up rpc.%s ...', mod.name)
|
||||||
mod.cleanup()
|
mod.cleanup()
|
||||||
del mod
|
del mod
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user