From 9c8f5795f806db0b7d7a7474efcd3b68506bf0c1 Mon Sep 17 00:00:00 2001 From: miloszowi Date: Wed, 13 Oct 2021 18:40:24 +0200 Subject: [PATCH] Singleton mongo client, added mongosh easy enter command, better logging, added idle time to mongo connection --- docker-compose.yml | 1 - docker/mongosh | 8 ++++++++ docker/start | 5 +++++ src/config/envs.py | 11 ++++++----- src/database/client.py | 26 +++++++++++++------------- src/decorators/singleton.py | 8 ++++++++ src/logger.py | 10 +++++----- 7 files changed, 45 insertions(+), 24 deletions(-) create mode 100755 docker/mongosh create mode 100755 docker/start create mode 100644 src/decorators/singleton.py diff --git a/docker-compose.yml b/docker-compose.yml index 32d7996..1677662 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,6 @@ services: - ./docker/config/app.env volumes: - ./src:/src - - ./logs:/var/log/bot ports: - $APP_EXPOSED_PORT:$APP_INTERNAL_PORT depends_on: diff --git a/docker/mongosh b/docker/mongosh new file mode 100755 index 0000000..a87a43e --- /dev/null +++ b/docker/mongosh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +if [ -f docker/config/app.env ] +then + source docker/config/app.env +fi + +docker-compose exec database mongosh --port $MONGODB_PORT --host $MONGODB_HOSTNAME --username $MONGODB_USERNAME --password $MONGODB_PASSWORD --authenticationDatabase admin $MONGODB_DATABASE \ No newline at end of file diff --git a/docker/start b/docker/start new file mode 100755 index 0000000..596f2d9 --- /dev/null +++ b/docker/start @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +docker-compose stop +docker-compose up -d +docker logs -f $(docker-compose ps -q app) &> app.log & \ No newline at end of file diff --git a/src/config/envs.py b/src/config/envs.py index fccb6bd..76b45e7 100755 --- a/src/config/envs.py +++ b/src/config/envs.py @@ -1,4 +1,5 @@ import os +from urllib.parse import quote_plus from dotenv import load_dotenv @@ -8,10 +9,10 @@ BOT_TOKEN = os.environ['BOT_TOKEN'] WEBHOOK_URL = os.environ['WEBHOOK_URL'] PORT = os.environ['PORT'] -MONGODB_DATABASE = os.environ['MONGODB_DATABASE'] -MONGODB_USERNAME = os.environ['MONGODB_USERNAME'] -MONGODB_PASSWORD = os.environ['MONGODB_PASSWORD'] -MONGODB_HOSTNAME = os.environ['MONGODB_HOSTNAME'] -MONGODB_PORT = os.environ['MONGODB_PORT'] +MONGO_DATABASE = os.environ['MONGODB_DATABASE'] +MONGO_CONNECTION_STRING = "mongodb://%s:%s@%s:%s/%s?authSource=admin" % ( + os.environ['MONGODB_USERNAME'], quote_plus(os.environ['MONGODB_PASSWORD']), + os.environ['MONGODB_HOSTNAME'], os.environ['MONGODB_PORT'], MONGO_DATABASE +) BANNED_USERS = os.environ['BANNED_USERS'].split(',') or [] diff --git a/src/database/client.py b/src/database/client.py index 5ea9f50..31aa468 100755 --- a/src/database/client.py +++ b/src/database/client.py @@ -1,25 +1,25 @@ -from urllib.parse import quote_plus - +from __future__ import annotations from pymongo import MongoClient from pymongo.database import Database -from config.envs import (MONGODB_DATABASE, MONGODB_HOSTNAME, - MONGODB_PASSWORD, MONGODB_PORT, - MONGODB_USERNAME) +from config.envs import MONGO_CONNECTION_STRING, MONGO_DATABASE +from decorators.singleton import Singleton -class Client: +class Client(metaclass=Singleton): mongo_client: MongoClient database: Database - def __init__(self) -> None: - uri = "mongodb://%s:%s@%s:%s/%s?authSource=admin" % ( - MONGODB_USERNAME, quote_plus(MONGODB_PASSWORD), - MONGODB_HOSTNAME, MONGODB_PORT, MONGODB_DATABASE - ) + # allow only 10 minutes on idle, close connection after + max_idle_time: int = 10 * (60 * 1000) - self.mongo_client = MongoClient(uri) - self.database = self.mongo_client[MONGODB_DATABASE] + def __init__(self) -> None: + self.mongo_client = MongoClient( + MONGO_CONNECTION_STRING, + connect=False, + maxIdleTimeMS=self.max_idle_time + ) + self.database = self.mongo_client[MONGO_DATABASE] def insert_one(self, collection: str, data: dict) -> None: self.database.get_collection(collection).insert_one(data) diff --git a/src/decorators/singleton.py b/src/decorators/singleton.py new file mode 100644 index 0000000..3886cfd --- /dev/null +++ b/src/decorators/singleton.py @@ -0,0 +1,8 @@ +class Singleton(type): + _instances: dict = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + + return cls._instances[cls] diff --git a/src/logger.py b/src/logger.py index 6dc33f5..57a9c9a 100644 --- a/src/logger.py +++ b/src/logger.py @@ -14,9 +14,6 @@ class Logger: main_logger: str = 'main-logger' main_logger_file: str = '/var/log/bot/app.log' - # noinspection SpellCheckingInspection - formatter: logging.Formatter = logging.Formatter('%(asctime)s[%(levelname)s]: %(message)s') - def __init__(self): self.configure(self.action_logger, self.action_logger_file, logging.INFO) self.configure(self.main_logger, self.main_logger_file, logging.ERROR) @@ -27,10 +24,13 @@ class Logger: os.makedirs(directory) logger = logging.getLogger(logger_name) + logger.propagate = False + file_handler = logging.FileHandler(log_file, mode='w') - file_handler.setFormatter(self.formatter) + formatter = logging.Formatter('%(asctime)s [%(levelname)s]: %(message)s', datefmt='%H:%M:%S %Y/%m/%d') + file_handler.setFormatter(formatter) stream_handler = logging.StreamHandler() - stream_handler.setFormatter(self.formatter) + stream_handler.setFormatter(formatter) logger.setLevel(level) logger.addHandler(file_handler)