Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions puzzle-generator/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ DATABASE_USER= # Required for PostgreSQL, leave blank for SQ
DATABASE_PASSWORD= # Required for PostgreSQL, leave blank for SQLite
DATABASE_HOST=localhost # Required for PostgreSQL, typically "localhost" or an IP address
DATABASE_PORT=5432 # Default PostgreSQL port, leave as-is or set if using a different port

# System resource configuration
PARALLELISM_DIVISOR=1 # Controls CPU core usage: CPU cores / PARALLELISM_DIVISOR = cores used
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit this in your .env file to set amount of parallelism
1 = as parallelized as possible
2 = half
3 = one third
so on ..

# Example: 16 cores with PARALLELISM_DIVISOR=2 will use 8 cores
# Default is 2 if not specified, set to 1 to use all available cores
104 changes: 104 additions & 0 deletions puzzle-generator/src/utils/EnvironmentManager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""Utility class for environment variable management."""

import os
from enum import Enum
from typing import Any, cast


class EnvVarType(Enum):
"""Types of environment variables."""
INT = "int"
STRING = "str"
BOOL = "bool"


class EnvironmentVariables(Enum):
"""
Enum of known environment variables used in the application.

Each enum value is a tuple of (env_var_name, default_value, type).
"""
PARALLELISM_DIVISOR = ("PARALLELISM_DIVISOR", 2, EnvVarType.INT)

def __init__(self, env_name: str, default_value: Any, var_type: EnvVarType):
self.env_name = env_name
self.default_value = default_value
self.var_type = var_type


class EnvironmentManager:
"""Static utility class for environment variable management."""

@staticmethod
def get_value(env_var: EnvironmentVariables, override_default: Any = None) -> Any:
"""
Get a value from an environment variable with appropriate type conversion.

Args:
env_var: The environment variable to retrieve
override_default: Optional value to override the default defined in the enum

Returns:
The value of the environment variable or the default with appropriate type
"""
# Use override_default if provided, otherwise use the enum's default
default = override_default if override_default is not None else env_var.default_value

# Get the value from environment
value = os.environ.get(env_var.env_name)
if value is None:
return default

# Convert to appropriate type
if env_var.var_type == EnvVarType.INT:
try:
return int(value)
except ValueError:
# Log warning here if needed
return default
elif env_var.var_type == EnvVarType.BOOL:
return value.lower() in ('true', 'yes', '1', 'y')
else: # STRING or any other type
return value

@staticmethod
def get_int(env_var: EnvironmentVariables, default = None) -> int:
"""
Get an integer value from an environment variable.

Args:
env_var: The environment variable to retrieve
default: Optional value to override the default defined in the enum

Returns:
int: The value of the environment variable or the default
"""
return cast(int, EnvironmentManager.get_value(env_var, default))

@staticmethod
def get_string(env_var: EnvironmentVariables, default = None) -> str:
"""
Get a string value from an environment variable.

Args:
env_var: The environment variable to retrieve
default: Optional value to override the default defined in the enum

Returns:
str: The value of the environment variable or the default
"""
return cast(str, EnvironmentManager.get_value(env_var, default))

@staticmethod
def get_bool(env_var: EnvironmentVariables, default = None) -> bool:
"""
Get a boolean value from an environment variable.

Args:
env_var: The environment variable to retrieve
default: Optional value to override the default defined in the enum

Returns:
bool: The value of the environment variable or the default
"""
return cast(bool, EnvironmentManager.get_value(env_var, default))
13 changes: 10 additions & 3 deletions puzzle-generator/src/utils/SystemSpecs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Utility class for system specifications and resource management."""

import multiprocessing
from .EnvironmentManager import EnvironmentManager, EnvironmentVariables


class SystemSpecs:
Expand All @@ -11,10 +12,16 @@ def get_num_parallel_processes() -> int:
"""
Calculate the optimal number of parallel processes to use.

Returns half the number of CPU cores, with a minimum of 1.
Returns the number of CPU cores divided by the parallelization divisor,
with a minimum of 1.

The parallelization divisor can be configured via the PARALLELISM_DIVISOR
environment variable. Default is 2.

Returns:
int: Number of parallel processes to use
"""
parallelization_denominator = 2 # if cpu has 16 cores and parallelization denominator is 2 then this codebase will use 8 cores
return multiprocessing.cpu_count() // parallelization_denominator or 1 # default to 1 if only 1 core available
parallelism_divisor = EnvironmentManager.get_int(
EnvironmentVariables.PARALLELISM_DIVISOR
)
return multiprocessing.cpu_count() // parallelism_divisor or 1 # default to 1 if only 1 core available
3 changes: 2 additions & 1 deletion puzzle-generator/src/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Utility modules for the puzzle generator."""

from .SystemSpecs import SystemSpecs
from .EnvironmentManager import EnvironmentManager, EnvironmentVariables

__all__ = ["SystemSpecs"]
__all__ = ["SystemSpecs", "EnvironmentManager", "EnvironmentVariables"]