diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f62094a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto +*.sh text eol=lf +*.bash text eol=lf diff --git a/.gitignore b/.gitignore index 5703ab7..ce1b74a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ # IDE .vscode/ .idea/ +.vs/ *.swp *.swo diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b4eec5..15111c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) project(moderation-service) enable_testing() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) if(MSVC) add_compile_options(/utf-8) diff --git a/configs/dev.yaml b/configs/dev.yaml index 7856c03..af6f05c 100644 --- a/configs/dev.yaml +++ b/configs/dev.yaml @@ -2,7 +2,7 @@ DATABASE_URL: "postgresql://esclient_devmodr:5C9C8NCFWGXR5m!R@pg4.sweb.ru:5433/e HOST: "0.0.0.0" PORT: "7006" -KAFKA_BROKERS: "localhost:9092" +KAFKA_BROKERS: "localhost:9093" KAFKA_REQUEST_TOPIC: "moderation-request" KAFKA_RESULT_TOPIC: "moderation-result" KAFKA_CONSUMER_GROUP_ID: "moderation-consumer-group" diff --git a/docker-compose.yml b/docker-compose.yml index bd10cbd..9fecb3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,11 @@ services: image: bashj79/kafka-kraft container_name: 'kafka' ports: - - '9092:9092' + - '9093:9092' environment: KAFKA_ENABLE_KRAFT: 'yes' ALLOW_PLAINTEXT_LISTENER: 'yes' + KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://localhost:9093' volumes: - kafka_data:/opt/kafka/kafka-logs healthcheck: diff --git a/tools/common.just b/tools/common.just index 20cbcda..d4b6865 100644 --- a/tools/common.just +++ b/tools/common.just @@ -17,18 +17,28 @@ build-linux: fetch-proto cmake --build build --config Release build-windows: fetch-proto - conan install . --output-folder=build --build=missing + conan install . --output-folder=build --build=missing -s compiler.cppstd=20 cmake -S . -B build \ -G "Visual Studio 17 2022" \ -A x64 \ -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 cmake --build build --config Release kafka-container-up: docker-compose up -d - MSYS_NO_PATHCONV=1 docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic moderation-result --replication-factor 1 --partitions 3 - MSYS_NO_PATHCONV=1 docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic moderation-request --replication-factor 1 --partitions 3 + @echo "Waiting for Kafka to be ready..." + @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30; do \ + if docker exec kafka nc -z localhost 9092 2>/dev/null; then \ + echo "Kafka is ready!"; \ + break; \ + fi; \ + echo "Waiting for Kafka... attempt $$i/30"; \ + sleep 2; \ + done + MSYS_NO_PATHCONV=1 docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --if-not-exists --topic moderation-result --replication-factor 1 --partitions 3 + MSYS_NO_PATHCONV=1 docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --if-not-exists --topic moderation-request --replication-factor 1 --partitions 3 kafka-container-down: MSYS_NO_PATHCONV=1 docker exec kafka /opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --delete --topic moderation-request diff --git a/tools/install_dev_tools.sh b/tools/install_dev_tools.sh index efe10cf..549a932 100644 --- a/tools/install_dev_tools.sh +++ b/tools/install_dev_tools.sh @@ -1,70 +1,283 @@ #!/bin/bash set -e -echo "=== Installing C++ Development Tools ===" +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color -if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then +echo -e "${GREEN}=== C++ Development Tools Installer ===${NC}" +echo "" + +# ============================================================================ +# OS Detection +# ============================================================================ +echo -e "${CYAN}=== Detecting Operating System ===${NC}" +echo "OSTYPE: $OSTYPE" +echo "uname: $(uname -s 2>/dev/null || echo 'N/A')" + +IS_WINDOWS=false +IS_WSL=false +IS_LINUX=false +IS_MACOS=false + +# Check for WSL first (highest priority) +if grep -qEi "(Microsoft|WSL)" /proc/version 2>/dev/null; then + IS_WSL=true + echo -e "${RED}WSL detected - Linux running inside Windows${NC}" + echo -e "${RED}ERROR: This script is not designed for WSL!${NC}" + echo -e "${YELLOW}Please use one of these instead:${NC}" + echo " 1. PowerShell script: tools/install_dev_tools.ps1" + echo " 2. Git Bash (from Git for Windows)" + echo "" + echo "Download Git for Windows: https://git-scm.com/download/win" + exit 1 +fi + +# Detect Windows (Git Bash, MSYS, Cygwin) +if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then + IS_WINDOWS=true +elif [[ "$(uname -s 2>/dev/null)" == MINGW* || "$(uname -s 2>/dev/null)" == MSYS* || "$(uname -s 2>/dev/null)" == CYGWIN* ]]; then + IS_WINDOWS=true +elif [[ -n "$WINDIR" || -n "$windir" ]]; then + IS_WINDOWS=true +# Detect Linux +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + IS_LINUX=true +# Detect macOS +elif [[ "$OSTYPE" == "darwin"* ]]; then + IS_MACOS=true +fi + +if [[ "$IS_WINDOWS" == "true" ]]; then + echo -e "${GREEN}✓ Windows detected (Git Bash/MSYS)${NC}" + + # Check for admin rights on Windows if ! net session > /dev/null 2>&1; then - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo -e "${RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "ERROR: This script MUST be run as ADMINISTRATOR on Windows." - echo "Please restart Git Bash/VS Code as Administrator and try again." - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + echo "Please restart Git Bash as Administrator and try again." + echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${NC}" exit 1 fi + echo -e "${GREEN}✓ Running as Administrator${NC}" +elif [[ "$IS_LINUX" == "true" ]]; then + echo -e "${GREEN}✓ Linux detected${NC}" +elif [[ "$IS_MACOS" == "true" ]]; then + echo -e "${GREEN}✓ macOS detected${NC}" +else + echo -e "${RED}✗ Unknown OS: $OSTYPE${NC}" + echo "Please install dependencies manually." + exit 1 fi -echo "=== Detecting OS ===" +echo "" -# Install OS-specific dependencies (pipx, curl, build tools, LLVM, Cmake, cppcheck) -if [[ "$OSTYPE" == "linux-gnu"* ]]; then - echo "Linux detected (Ubuntu/Debian style)" - sudo apt-get update - sudo apt-get install -y pipx curl build-essential clang-format clang-tidy cppcheck cmake -elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then - echo "Windows detected (Git Bash/MSYS)" +# ============================================================================ +# Check Prerequisites +# ============================================================================ +echo -e "${CYAN}=== Checking Prerequisites ===${NC}" - if ! command -v pipx &> /dev/null; then - echo "Installing pipx via python..." - python -m pip install --user pipx +# Check Python +if ! command -v python &> /dev/null && ! command -v python3 &> /dev/null; then + echo -e "${RED}✗ Python not found!${NC}" + if [[ "$IS_WINDOWS" == "true" ]]; then + echo "Install Python from: https://www.python.org/downloads/" + echo "Or use: choco install python -y" + elif [[ "$IS_LINUX" == "true" ]]; then + echo "Install with: sudo apt-get install python3 python3-pip" + elif [[ "$IS_MACOS" == "true" ]]; then + echo "Install with: brew install python3" fi - - choco install llvm -y - choco install cmake -y - choco install cppcheck -y -else - echo "Unknown OS: $OSTYPE. Please install dependencies manually." exit 1 +else + PYTHON_CMD=$(command -v python3 2>/dev/null || command -v python) + echo -e "${GREEN}✓ Python found: $($PYTHON_CMD --version)${NC}" +fi + +# Check Chocolatey on Windows +if [[ "$IS_WINDOWS" == "true" ]]; then + if ! command -v choco &> /dev/null; then + echo -e "${YELLOW}⚠ Chocolatey not found${NC}" + echo "Installing Chocolatey..." + powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" + export PATH="$PATH:/c/ProgramData/chocolatey/bin" + else + echo -e "${GREEN}✓ Chocolatey found${NC}" + fi +fi + +# Check Homebrew on macOS +if [[ "$IS_MACOS" == "true" ]]; then + if ! command -v brew &> /dev/null; then + echo -e "${YELLOW}⚠ Homebrew not found${NC}" + echo "Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + else + echo -e "${GREEN}✓ Homebrew found${NC}" + fi +fi + +echo "" + +# ============================================================================ +# Install System Dependencies +# ============================================================================ +echo -e "${CYAN}=== Installing System Dependencies ===${NC}" + +if [[ "$IS_WINDOWS" == "true" ]]; then + # LLVM (clang-format, clang-tidy) + if ! command -v clang-format &> /dev/null; then + echo "Installing LLVM..." + choco install llvm -y + else + echo -e "${GREEN}✓ LLVM already installed${NC}" + fi + + # CMake + if ! command -v cmake &> /dev/null; then + echo "Installing CMake..." + choco install cmake -y + else + echo -e "${GREEN}✓ CMake already installed${NC}" + fi + + # cppcheck + if ! command -v cppcheck &> /dev/null; then + echo "Installing cppcheck..." + choco install cppcheck -y + else + echo -e "${GREEN}✓ cppcheck already installed${NC}" + fi + +elif [[ "$IS_LINUX" == "true" ]]; then + echo "Updating package lists..." + sudo apt-get update -qq + + PACKAGES_TO_INSTALL=() + + command -v curl &> /dev/null || PACKAGES_TO_INSTALL+=(curl) + command -v g++ &> /dev/null || PACKAGES_TO_INSTALL+=(build-essential) + command -v clang-format &> /dev/null || PACKAGES_TO_INSTALL+=(clang-format) + command -v clang-tidy &> /dev/null || PACKAGES_TO_INSTALL+=(clang-tidy) + command -v cppcheck &> /dev/null || PACKAGES_TO_INSTALL+=(cppcheck) + command -v cmake &> /dev/null || PACKAGES_TO_INSTALL+=(cmake) + + if [ ${#PACKAGES_TO_INSTALL[@]} -gt 0 ]; then + echo "Installing: ${PACKAGES_TO_INSTALL[*]}" + sudo apt-get install -y "${PACKAGES_TO_INSTALL[@]}" + else + echo -e "${GREEN}✓ All system packages already installed${NC}" + fi + +elif [[ "$IS_MACOS" == "true" ]]; then + command -v clang-format &> /dev/null || brew install clang-format + command -v cmake &> /dev/null || brew install cmake + command -v cppcheck &> /dev/null || brew install cppcheck fi -if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then - PYTHON_SCRIPTS=$(python -c "import os, sysconfig; print(sysconfig.get_path('scripts',f'{os.name}_user'))") +echo "" + +# ============================================================================ +# Setup Python Environment +# ============================================================================ +echo -e "${CYAN}=== Setting up Python Environment ===${NC}" + +# Upgrade pip +echo "Upgrading pip..." +$PYTHON_CMD -m pip install --upgrade pip --quiet --user + +# Update PATH for user-installed Python packages +if [[ "$IS_WINDOWS" == "true" ]]; then + PYTHON_SCRIPTS=$($PYTHON_CMD -c "import os, sysconfig; print(sysconfig.get_path('scripts', f'{os.name}_user'))" 2>/dev/null || echo "$HOME/AppData/Roaming/Python/Scripts") export PATH="$PATH:$PYTHON_SCRIPTS:$HOME/.local/bin" else export PATH="$PATH:$HOME/.local/bin" fi -# Install Conan +echo "" + +# ============================================================================ +# Install Python Tools +# ============================================================================ +echo -e "${CYAN}=== Installing Python-based Tools ===${NC}" + +# Conan if ! command -v conan &> /dev/null; then echo "Installing Conan..." - pipx install conan --quiet + $PYTHON_CMD -m pip install --user conan --quiet export PATH="$PATH:$HOME/.local/bin" - conan profile detect --force + + # Detect Conan profile + if command -v conan &> /dev/null; then + conan profile detect --force 2>/dev/null || true + fi +else + echo -e "${GREEN}✓ Conan already installed${NC}" fi -# Install Python-based tools via pipx -echo "Installing Python linting tools via pipx..." -pipx install cpplint --quiet || true -pipx install cmakelang --quiet || true +# cpplint +if ! $PYTHON_CMD -c "import cpplint" 2>/dev/null; then + echo "Installing cpplint..." + $PYTHON_CMD -m pip install --user cpplint --quiet +else + echo -e "${GREEN}✓ cpplint already installed${NC}" +fi + +# cmakelang (cmake-format, cmake-lint) +if ! $PYTHON_CMD -c "import cmakelang" 2>/dev/null; then + echo "Installing cmakelang..." + $PYTHON_CMD -m pip install --user cmakelang --quiet +else + echo -e "${GREEN}✓ cmakelang already installed${NC}" +fi echo "" -echo "All development tools installed!" + +# ============================================================================ +# Verify Installation +# ============================================================================ +echo -e "${CYAN}=== Verifying Installation ===${NC}" +echo "" + +FAILED=0 + +check_tool() { + local tool=$1 + local check_cmd=$2 + + if eval "$check_cmd" &> /dev/null; then + echo -e "${GREEN}✓${NC} $tool" + else + echo -e "${RED}✗${NC} $tool - NOT FOUND" + FAILED=1 + fi +} + +check_tool "CMake" "command -v cmake" +check_tool "Conan" "command -v conan" +check_tool "clang-format" "command -v clang-format" +check_tool "clang-tidy" "command -v clang-tidy" +check_tool "cppcheck" "command -v cppcheck" +check_tool "cpplint" "$PYTHON_CMD -c 'import cpplint'" +check_tool "cmakelang" "$PYTHON_CMD -c 'import cmakelang'" + echo "" -echo "Installed versions:" -conan --version | head -n1 -cmake --version | head -n1 -clang-format --version | head -n1 -clang-tidy --version | head -n1 -cppcheck --version | head -n1 -cpplint --version 2>&1 | head -n1 || echo "cpplint installed via pipx" -echo "Cmake-format version:" -cmake-format --version 2>&1 | head -n1 || echo "cmake-format not installed" \ No newline at end of file + +if [ $FAILED -eq 0 ]; then + echo -e "${GREEN}=== ✓ All tools installed successfully! ===${NC}" + echo "" + echo "Installed versions:" + cmake --version 2>/dev/null | head -n1 || echo "cmake: version check failed" + conan --version 2>/dev/null | head -n1 || echo "conan: version check failed" + clang-format --version 2>/dev/null | head -n1 || echo "clang-format: version check failed" + cppcheck --version 2>/dev/null | head -n1 || echo "cppcheck: version check failed" + echo "" + echo -e "${YELLOW}Note: You may need to restart your terminal for PATH changes to take effect.${NC}" +else + echo -e "${RED}=== ✗ Some tools failed to install ===${NC}" + echo "Please check the errors above and try again." + exit 1 +fi \ No newline at end of file