diff --git a/backend/handler/redis_handler.py b/backend/handler/redis_handler.py index 936f7aefe..34c6a7a6f 100644 --- a/backend/handler/redis_handler.py +++ b/backend/handler/redis_handler.py @@ -1,3 +1,4 @@ +import sys from enum import Enum from config import REDIS_HOST, REDIS_PASSWORD, REDIS_PORT @@ -12,6 +13,32 @@ class QueuePrio(Enum): LOW = "low" +class FallbackCache: + def __init__(self) -> None: + self.fallback: dict = {} + + def get(self, key: str, *args, **kwargs) -> str: + return self.fallback.get(key, "") + + def set(self, key: str, value: str, *args, **kwargs) -> None: + self.fallback[key] = value + + def delete(self, key: str, *args, **kwargs) -> None: + self.fallback.pop(key, None) + + def exists(self, key: str, *args, **kwargs) -> bool: + return key in self.fallback + + def flushall(self) -> None: + self.fallback = {} + + def __repr__(self) -> str: + return f"" + + def __str__(self) -> str: + return repr(self) + + redis_client = Redis( host=REDIS_HOST, port=int(REDIS_PORT), password=REDIS_PASSWORD, db=0 ) @@ -26,13 +53,15 @@ high_prio_queue = Queue(name=QueuePrio.HIGH.value, connection=redis_client) default_queue = Queue(name=QueuePrio.DEFAULT.value, connection=redis_client) low_prio_queue = Queue(name=QueuePrio.LOW.value, connection=redis_client) -# A seperate client that auto-decodes responses is needed -_cache_client = Redis( - host=REDIS_HOST, - port=int(REDIS_PORT), - password=REDIS_PASSWORD, - db=0, - decode_responses=True, -) -log.info("Connecting to redis...") -cache = _cache_client +if "pytest" in sys.modules: + cache = FallbackCache() +else: + log.info("Connecting to redis...") + # A seperate client that auto-decodes responses is needed + cache = Redis( + host=REDIS_HOST, + port=int(REDIS_PORT), + password=REDIS_PASSWORD, + db=0, + decode_responses=True, + ) diff --git a/backend/handler/tests/conftest.py b/backend/handler/tests/conftest.py index 1daa478f9..ab207773c 100644 --- a/backend/handler/tests/conftest.py +++ b/backend/handler/tests/conftest.py @@ -8,7 +8,7 @@ from models.platform import Platform from models.rom import Rom from models.user import User from models.assets import Save, State, Screenshot -from models.user import Role, User +from models.user import Role from handler import db_user_handler, db_platform_handler, db_rom_handler, db_save_handler, db_state_handler, auth_handler, db_screenshot_handler engine = create_engine(ConfigManager.get_db_engine(), pool_pre_ping=True) diff --git a/backend/main.py b/backend/main.py index a0eb5f86e..19903abb0 100644 --- a/backend/main.py +++ b/backend/main.py @@ -85,8 +85,11 @@ app.mount("/ws", socket_handler.socket_app) def startup() -> None: """Event to handle RomM startup logic.""" + if "pytest" in sys.modules: + return + # Create default admin user if no admin user exists - if len(db_user_handler.get_admin_users()) == 0 and "pytest" not in sys.modules: + if len(db_user_handler.get_admin_users()) == 0: auth_handler.create_default_admin_user() diff --git a/docker-compose.yml b/docker-compose.yml index 203d11d58..53e5848d4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,14 +15,6 @@ services: redis: image: redis:alpine container_name: redis - command: - # - /bin/sh - # - -c - # # - Double dollars, so that the variable is not expanded by Docker Compose - # # - Surround by quotes, so that the shell does not split the password - # # - The ${variable:?message} syntax causes shell to exit with a non-zero - # # code and print a message, when the variable is not set or empty - # - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}" restart: unless-stopped ports: - ${REDIS_PORT}:6379 diff --git a/examples/docker-compose.example.yml b/examples/docker-compose.example.yml index dbf2c5acd..69dcab7fb 100644 --- a/examples/docker-compose.example.yml +++ b/examples/docker-compose.example.yml @@ -1,49 +1,51 @@ version: "3" + volumes: mysql_data: + romm_resources: + services: romm: image: zurdi15/romm:latest container_name: romm + restart: unless-stopped environment: - - ROMM_HOST=https://localhost:3000 # Your host ip or domain name (including http(s)://, subdomain and port if needed) - - DB_HOST=romm_db + - DB_HOST=mariadb - DB_PORT=3306 - - DB_USER=romm-user - - DB_NAME=romm # Should match the MYSQL_DATABASE value in the mariadb container - - DB_PASSWD= - - IGDB_CLIENT_ID= - - IGDB_CLIENT_SECRET= - - ROMM_AUTH_SECRET_KEY= # Generate a key with `openssl rand -hex 32` + - DB_NAME=romm # Should match MYSQL_DATABASE in mariadb + - DB_USER=romm-user # Should match MYSQL_USER in mariadb + - DB_PASSWORD= # Should match MYSQL_PASSWORD in mariadb + - IGDB_CLIENT_ID= # Generate an ID and SECRET in IGDB + - IGDB_CLIENT_SECRET= # https://api-docs.igdb.com/#account-creation + - ROMM_AUTH_SECRET_KEY= # Generate a key with `openssl rand -hex 32` - ROMM_AUTH_USERNAME=admin - - ROMM_AUTH_PASSWORD= # default: admin + - ROMM_AUTH_PASSWORD= # default: admin - REDIS_HOST=redis - REDIS_PORT=6379 volumes: - - "/path/to/library:/romm/library" - - "/path/to/assets:/romm/assets" # Path where saves, states and other assets are stored - - "/path/to/resources:/romm/resources" # Path where roms metadata (covers) are stored + - romm_resources:/romm/resources" # Resources fetched from IGDB (covers, screenshots, etc.) + - "/path/to/library:/romm/library" # Your game library + - "/path/to/assets:/romm/assets" # Uploaded saves, states, etc. - "/path/to/config:/romm/config" # [Optional] Path where config.yml is stored - "/path/to/logs:/romm/logs" # [Optional] Path where logs are stored ports: - 80:8080 depends_on: - - romm_db - restart: "unless-stopped" + - mariadb - romm_db: + mariadb: image: mariadb:latest - container_name: romm_db + container_name: mariadb + restart: unless-stopped environment: - - MYSQL_ROOT_PASSWORD= + - MYSQL_ROOT_PASSWORD= # Use a unique, secure password - MYSQL_DATABASE=romm - MYSQL_USER=romm-user - - MYSQL_PASSWORD= + - MYSQL_PASSWORD= volumes: - mysql_data:/var/lib/mysql ports: - 3306:3306 - restart: "unless-stopped" redis: image: redis:alpine