diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2ead75e --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +RESPONSE_TIMEOUT=5 + +PORT=65526 +HOST= \ No newline at end of file diff --git a/README.md b/README.md index bd2a628..4ff872a 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,9 @@ ## Sources -- [Catch SIGTERM](https://stackoverflow.com/questions/18499497/how-to-process-sigterm-signal-gracefully#31464349) \ No newline at end of file +### Signal catching +- [Catch SIGTERM](https://stackoverflow.com/a/31464349) +- [Get ENUM name from value](https://stackoverflow.com/a/38716384) + +### Networking +- [Dynamically finding host IP address](https://stackoverflow.com/a/28950776) \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 39dbf12..81c8073 100644 --- a/poetry.lock +++ b/poetry.lock @@ -86,6 +86,20 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "sqlalchemy" version = "2.0.37" @@ -195,4 +209,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "3568ec5bd2911d0c45c9b8689c11ed6c688d07ef23b6a739b25b4f188dd8e10e" +content-hash = "6ac48c667aa2e9a90b4339005a250d1e664006645cd9c7b0dcec6d8a888a3e50" diff --git a/pyproject.toml b/pyproject.toml index f1ff405..5caaed7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" sqlalchemy = "^2.0.37" +python-dotenv = "^1.0.1" [build-system] diff --git a/src/app.py b/src/app.py index e69de29..9626a00 100644 --- a/src/app.py +++ b/src/app.py @@ -0,0 +1,4 @@ +from bank_node.bank_node import BankNode + +if __name__ == "__main__": + BankNode().start_server() diff --git a/src/bank_node.py b/src/bank_node/__init__.py similarity index 100% rename from src/bank_node.py rename to src/bank_node/__init__.py diff --git a/src/bank_node/bank_node.py b/src/bank_node/bank_node.py new file mode 100644 index 0000000..f66d6e1 --- /dev/null +++ b/src/bank_node/bank_node.py @@ -0,0 +1,39 @@ +import socket +import signal +import sys +import logging + +from core.config import BankNodeConfig + +class BankNode(): + def __init__(self): + self.logger = logging.getLogger(__name__) + self._setup_signals() + self.config = BankNodeConfig() + + def _setup_signals(self): + self.logger.debug("Setting up exit signal hooks") + signal.signal(signal.SIGTERM, self.gracefully_exit) + signal.signal(signal.SIGINT, self.gracefully_exit) + + def gracefully_exit(self, signum, frame): + signal_name = signal.Signals(signum).name + self.logger.warning("Caught %s. Cleaning up before exiting", signal_name) + self.cleanup() + sys.exit(0) + + + def start_server(self): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_server: + socket_server.bind(("127.0.0.1", 6969)) + socket_server.listen() + + while True: + conn, addr = socket_server.accept() + with conn: + print(f"{addr} connected") + request = conn.recv(1024).decode("utf-8") + print(f"Request:\n{request}") + + def cleanup(self): + pass diff --git a/src/bank_node/bank_process.py b/src/bank_node/bank_process.py new file mode 100644 index 0000000..46405fe --- /dev/null +++ b/src/bank_node/bank_process.py @@ -0,0 +1,4 @@ +from multiprocessing import Process + +class BankProcess(Process): + pass \ No newline at end of file diff --git a/src/bank_protocol/exceptions.py b/src/bank_protocol/exceptions.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/config.py b/src/core/config.py new file mode 100644 index 0000000..2033f85 --- /dev/null +++ b/src/core/config.py @@ -0,0 +1,17 @@ +import os +import logging + +import dotenv + +from utils import setup_logger + +dotenv.load_dotenv() + +class BankNodeConfig: + def __init__(self): + self.logger = logging.getLogger(__name__) + self.port = os.getenv("PORT", "6969") + + self.timeout = os.getenv("RESPONSE_TIMEOUT", "5") + + self.verbosity = os.getenv("VERBOSITY", "DEBUG") \ No newline at end of file diff --git a/src/core/exceptions.py b/src/core/exceptions.py new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/setup_logger.py b/src/utils/setup_logger.py new file mode 100644 index 0000000..cf153be --- /dev/null +++ b/src/utils/setup_logger.py @@ -0,0 +1,13 @@ +import sys +import logging + + +def setup_logger(): + logger = logging.getLogger() + + handler = logging.StreamHandler(sys.stdout) + + formatter = logging.Formatter("[%(levelname)s] - %(name)s:%(lineno)d - %(message)s") + handler.setFormatter(formatter) + + logger.addHandler(handler)