Consolidate 3 separate applications (reports-app, data-entry-app, telegram-bot) into a unified
architecture with single backend and frontend:
Backend Changes:
- Unified FastAPI backend at backend/ with modular structure
- Modules: reports, data_entry, telegram in backend/modules/
- Centralized config.py and main.py with all routers registered
- Single worker mode (--workers 1) for Telegram bot compatibility
- Shared Oracle connection pool and JWT authentication
- Unified requirements.txt and environment configuration
Frontend Changes:
- Single Vue.js SPA with module-based routing
- Unified frontend at src/ with modules in src/modules/{reports,data-entry}/
- Shared components and stores in src/shared/
- Error boundaries for module isolation
- Dual API proxy in Vite for module communication
Infrastructure:
- New unified startup scripts: start-prod.sh, start-test.sh, start-backend.sh
- Environment templates: .env.dev.example, .env.test.example, .env.prod.example
- Updated deployment scripts for Windows IIS
- Simplified SSH tunnel management
Documentation:
- Comprehensive CLAUDE.md with architecture overview
- Module-specific docs in docs/{data-entry,telegram}/
- Architecture decision records in docs/ARCHITECTURE-DECISIONS.md
- Deployment guides consolidated in deployment/windows/docs/
This migration reduces complexity, improves maintainability, and enables easier
deployment while maintaining all existing functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
242 lines
9.7 KiB
PowerShell
242 lines
9.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Fix Telegram bot conflict by updating NSSM service to use single worker
|
|
|
|
.DESCRIPTION
|
|
Updates ROA2WEB-Backend Windows service to use --workers 1 instead of --workers 4.
|
|
This fixes the Telegram bot conflict error:
|
|
"terminated by other getUpdates request; make sure that only one bot instance is running"
|
|
|
|
The issue occurs because multiple uvicorn workers each try to start their own
|
|
Telegram bot instance, but Telegram API allows only one bot to poll for updates.
|
|
|
|
.EXAMPLE
|
|
.\Fix-TelegramWorkers.ps1
|
|
#>
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
# Configuration (hardcoded for simplicity)
|
|
$ServiceName = "ROA2WEB-Backend"
|
|
$ServicePort = 8000
|
|
$LogsPath = "C:\inetpub\wwwroot\roa2web\logs"
|
|
|
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan
|
|
Write-Host " FIX TELEGRAM BOT WORKER CONFLICT" -ForegroundColor Cyan
|
|
Write-Host ("=" * 70) -ForegroundColor Cyan
|
|
Write-Host ""
|
|
|
|
# Check if running as Administrator
|
|
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
|
|
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
|
|
if (-not $isAdmin) {
|
|
Write-Host "[ERROR] This script must be run as Administrator" -ForegroundColor Red
|
|
Write-Host "Please right-click PowerShell and select 'Run as Administrator'" -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
# Check if NSSM exists
|
|
$nssmPath = "C:\ProgramData\chocolatey\bin\nssm.exe"
|
|
if (-not (Test-Path $nssmPath)) {
|
|
Write-Host "[ERROR] NSSM not found at: $nssmPath" -ForegroundColor Red
|
|
Write-Host "Please install NSSM first: choco install nssm" -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
# Check if service exists
|
|
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
if (-not $service) {
|
|
Write-Host "[ERROR] Service not found: $ServiceName" -ForegroundColor Red
|
|
Write-Host "Please install the service first using Install-ROA2WEB.ps1" -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
Write-Host "[*] Service found: $ServiceName" -ForegroundColor Cyan
|
|
Write-Host " Current status: $($service.Status)" -ForegroundColor Gray
|
|
|
|
# Get current NSSM parameters
|
|
Write-Host "`n[*] Getting current service parameters..." -ForegroundColor Cyan
|
|
$currentParams = & nssm get $ServiceName AppParameters
|
|
|
|
Write-Host " Current parameters:" -ForegroundColor Gray
|
|
Write-Host " $currentParams" -ForegroundColor Yellow
|
|
|
|
# Check if already using --workers 1
|
|
if ($currentParams -match '--workers\s+1\b') {
|
|
Write-Host "`n[!] Service already configured with --workers 1" -ForegroundColor Green
|
|
Write-Host " No changes needed!" -ForegroundColor Green
|
|
|
|
# Check if service is running
|
|
$service = Get-Service -Name $ServiceName
|
|
if ($service.Status -ne 'Running') {
|
|
Write-Host "`n[*] Starting service..." -ForegroundColor Cyan
|
|
Start-Service -Name $ServiceName
|
|
Start-Sleep -Seconds 2
|
|
Write-Host " [OK] Service started" -ForegroundColor Green
|
|
}
|
|
|
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Green
|
|
Write-Host " SERVICE ALREADY CONFIGURED CORRECTLY" -ForegroundColor Green
|
|
Write-Host ("=" * 70) -ForegroundColor Green
|
|
exit 0
|
|
}
|
|
|
|
# Confirm action
|
|
Write-Host "`n[!] This will:" -ForegroundColor Yellow
|
|
Write-Host " 1. Stop the backend service" -ForegroundColor Gray
|
|
Write-Host " 2. Change --workers 4 to --workers 1" -ForegroundColor Gray
|
|
Write-Host " 3. Restart the service" -ForegroundColor Gray
|
|
Write-Host ""
|
|
$confirm = Read-Host "Do you want to continue? (Y/N)"
|
|
|
|
if ($confirm -ne 'Y' -and $confirm -ne 'y') {
|
|
Write-Host "`n[!] Operation cancelled by user" -ForegroundColor Yellow
|
|
exit 0
|
|
}
|
|
|
|
# Stop the service
|
|
Write-Host "`n[*] Stopping service..." -ForegroundColor Cyan
|
|
try {
|
|
Stop-Service -Name $ServiceName -Force
|
|
Start-Sleep -Seconds 3
|
|
Write-Host " [OK] Service stopped" -ForegroundColor Green
|
|
} catch {
|
|
Write-Host " [ERROR] Failed to stop service: $_" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Update parameters to use --workers 1
|
|
Write-Host "`n[*] Updating service parameters..." -ForegroundColor Cyan
|
|
|
|
try {
|
|
# Set new parameters with --workers 1
|
|
& nssm set $ServiceName AppParameters `
|
|
"-m uvicorn main:app --host 127.0.0.1 --port $ServicePort --workers 1"
|
|
|
|
Write-Host " [OK] Parameters updated to: --workers 1" -ForegroundColor Green
|
|
} catch {
|
|
Write-Host " [ERROR] Failed to update parameters: $_" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Verify the change
|
|
$newParams = & nssm get $ServiceName AppParameters
|
|
Write-Host "`n[*] New parameters:" -ForegroundColor Cyan
|
|
Write-Host " $newParams" -ForegroundColor Yellow
|
|
|
|
# Verify it contains --workers 1
|
|
if ($newParams -match '--workers\s+1\b') {
|
|
Write-Host " [OK] Verified: --workers 1 is set" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " [ERROR] Verification failed: --workers 1 not found" -ForegroundColor Red
|
|
Write-Host " Current value: $newParams" -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
# Start the service
|
|
Write-Host "`n[*] Starting service..." -ForegroundColor Cyan
|
|
try {
|
|
Start-Service -Name $ServiceName
|
|
Start-Sleep -Seconds 5
|
|
Write-Host " [OK] Service started" -ForegroundColor Green
|
|
} catch {
|
|
Write-Host " [ERROR] Failed to start service: $_" -ForegroundColor Red
|
|
Write-Host " Check logs at: $LogsPath" -ForegroundColor Yellow
|
|
exit 1
|
|
}
|
|
|
|
# Check service status
|
|
$service = Get-Service -Name $ServiceName
|
|
Write-Host "`n[*] Service status:" -ForegroundColor Cyan
|
|
Write-Host " Name: $($service.Name)" -ForegroundColor Gray
|
|
Write-Host " Status: $($service.Status)" -ForegroundColor $(if ($service.Status -eq 'Running') { 'Green' } else { 'Red' })
|
|
|
|
# Wait a few seconds for service to fully start
|
|
Write-Host "`n[*] Waiting for service to fully initialize..." -ForegroundColor Cyan
|
|
Start-Sleep -Seconds 10
|
|
|
|
# Check backend health
|
|
Write-Host "`n[*] Checking backend health..." -ForegroundColor Cyan
|
|
try {
|
|
$response = Invoke-WebRequest -Uri "http://localhost:$ServicePort/health" -UseBasicParsing -TimeoutSec 5
|
|
if ($response.StatusCode -eq 200) {
|
|
Write-Host " [OK] Backend is responding: $($response.StatusCode)" -ForegroundColor Green
|
|
|
|
$healthData = $response.Content | ConvertFrom-Json
|
|
Write-Host "`n Health check details:" -ForegroundColor Gray
|
|
Write-Host " - Status: $($healthData.status)" -ForegroundColor Gray
|
|
Write-Host " - Oracle: $($healthData.oracle_status)" -ForegroundColor Gray
|
|
if ($healthData.modules_enabled) {
|
|
Write-Host " - Modules: $($healthData.modules_enabled -join ', ')" -ForegroundColor Gray
|
|
}
|
|
}
|
|
} catch {
|
|
Write-Host " [WARN] Backend health check failed: $_" -ForegroundColor Yellow
|
|
Write-Host " Service may still be starting. Check logs for details." -ForegroundColor Yellow
|
|
}
|
|
|
|
# Check for Telegram errors in logs
|
|
Write-Host "`n[*] Checking recent logs for Telegram errors..." -ForegroundColor Cyan
|
|
$stderrLog = Join-Path $LogsPath "backend-stderr.log"
|
|
|
|
if (Test-Path $stderrLog) {
|
|
# Get last 100 lines and check for Telegram conflict errors
|
|
$recentLogs = Get-Content $stderrLog -Tail 100 | Out-String
|
|
|
|
# Count "Bot running" messages
|
|
$botStartCount = ([regex]::Matches($recentLogs, "Bot running: @ROA2WEBBot")).Count
|
|
|
|
if ($recentLogs -match "terminated by other getUpdates request") {
|
|
Write-Host " [WARN] Telegram conflict detected in recent logs!" -ForegroundColor Yellow
|
|
Write-Host " This may be from before the fix. Wait 30 seconds and check again." -ForegroundColor Yellow
|
|
} elseif ($botStartCount -gt 1) {
|
|
Write-Host " [WARN] Multiple bot startup messages found ($botStartCount)" -ForegroundColor Yellow
|
|
Write-Host " This may be from before the fix. New logs should show only 1." -ForegroundColor Yellow
|
|
} else {
|
|
Write-Host " [OK] No recent Telegram conflict errors found" -ForegroundColor Green
|
|
if ($botStartCount -eq 1) {
|
|
Write-Host " [OK] Bot started exactly once (correct!)" -ForegroundColor Green
|
|
}
|
|
}
|
|
} else {
|
|
Write-Host " [WARN] Log file not found: $stderrLog" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Check process count
|
|
Write-Host "`n[*] Checking Python processes..." -ForegroundColor Cyan
|
|
$pythonProcesses = Get-Process -Name python -ErrorAction SilentlyContinue
|
|
if ($pythonProcesses) {
|
|
$count = ($pythonProcesses | Measure-Object).Count
|
|
Write-Host " Python processes running: $count" -ForegroundColor Gray
|
|
|
|
if ($count -eq 2) {
|
|
Write-Host " [OK] Correct! (1 parent + 1 worker)" -ForegroundColor Green
|
|
} elseif ($count -eq 1) {
|
|
Write-Host " [OK] Single process (expected for --workers 1)" -ForegroundColor Green
|
|
} elseif ($count -eq 5) {
|
|
Write-Host " [ERROR] Still 5 processes! (1 parent + 4 workers)" -ForegroundColor Red
|
|
Write-Host " Fix may not have applied. Check NSSM parameters." -ForegroundColor Yellow
|
|
} else {
|
|
Write-Host " [WARN] Unexpected process count: $count" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
Write-Host "`n" + ("=" * 70) -ForegroundColor Green
|
|
Write-Host " FIX COMPLETE - SERVICE UPDATED TO SINGLE WORKER" -ForegroundColor Green
|
|
Write-Host ("=" * 70) -ForegroundColor Green
|
|
|
|
Write-Host "`nNext steps:" -ForegroundColor Yellow
|
|
Write-Host " 1. Monitor logs for 1-2 minutes:" -ForegroundColor Gray
|
|
Write-Host " Get-Content '$stderrLog' -Tail 20 -Wait" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host " 2. Look for (should appear ONCE):" -ForegroundColor Gray
|
|
Write-Host " [TELEGRAM] Bot running: @ROA2WEBBot" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host " 3. Verify NO conflict errors:" -ForegroundColor Gray
|
|
Write-Host " Get-Content '$stderrLog' -Tail 100 | Select-String 'Conflict'" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host " 4. Test the application:" -ForegroundColor Gray
|
|
Write-Host " https://roa2web.romfast.ro/roa2web/" -ForegroundColor Cyan
|
|
Write-Host ""
|