updated prisma service async runner

This commit is contained in:
2025-08-10 11:01:26 +03:00
parent c2fd263f27
commit 768f0a5daf
13637 changed files with 4688722 additions and 0 deletions

View File

@@ -0,0 +1 @@
3.12

View File

@@ -0,0 +1,22 @@
FROM python:3.12-slim
WORKDIR /app
# Copy only the dependency files first to leverage Docker cache
COPY ServicesRunner/AccountRecordServices/Reader/Banks/IsBank/pyproject.toml .
# Install dependencies
RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir .
# Copy only the necessary directories
COPY ServicesRunner/AccountRecordServices/Reader/Banks /app/ServicesRunner/AccountRecordServices/Reader/Banks
COPY ServicesRunner/Depends /app/ServicesRunner/Depends
# Set the Python path to include the root directory and ServicesRunner
ENV PYTHONPATH=/app:/app/ServicesRunner
# Set working directory to the IsBank service directory
WORKDIR /app/ServicesRunner/AccountRecordServices/Reader/Banks/IsBank
# Run the application
CMD ["python", "app.py"]

View File

@@ -0,0 +1,176 @@
import sys
import socket
import logging
from time import sleep
from config import IsBankConfig
from Depends.mail_handler import EmailReaderService, EmailServiceRunner
from Depends.service_handler import MailReaderService
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stdout), logging.FileHandler('isbank_email_service.log')]
)
logger = logging.getLogger('IsBank_Email_Service')
# Main application code
def main():
"""Main entry point for the IsBank email service"""
try:
redis_handler = MailReaderService()
email_service = EmailReaderService(IsBankConfig())
email_service.login_and_connect()
runner = EmailServiceRunner(redis_handler=redis_handler, email_service=email_service)
runner.fetch_and_set_mails()
runner.drop()
return True
except Exception as e:
logger.error(f"Error in main function: {str(e)}")
return False
def initialize_service():
"""Initialize the service with proper error handling"""
try:
# Create singleton instances directly
logger.info("Creating Redis handler singleton")
redis_handler = MailReaderService()
logger.info("Creating EmailReaderService")
email_service = EmailReaderService(IsBankConfig())
# Initialize email service and connect
logger.info("Connecting to email service")
email_service.login_and_connect()
# Create email service runner with the singletons
logger.info("Creating EmailServiceRunner")
runner = EmailServiceRunner(redis_handler=redis_handler, email_service=email_service)
if runner:
logger.info("Email service runner initialized successfully")
return runner
else:
logger.error("Failed to initialize email service runner")
# Sleep before retry to avoid rapid failure loops
sleep(5)
return initialize_service()
except Exception as e:
logger.error(f"Service initialization failed: {str(e)}")
# Sleep before retry to avoid rapid failure loops
sleep(5)
return initialize_service()
if __name__ == "__main__":
logger.info("Starting IsBank Email Service")
print(f"Starting Service Mail Reader.")
# Initialize service
runner = initialize_service()
# Configurable parameters
normal_sleep_time = 10 # seconds between normal operations
error_sleep_time = 30 # seconds to wait after an error before retrying
max_consecutive_errors = 5 # maximum number of consecutive errors before longer pause
extended_error_sleep = 120 # seconds to wait after hitting max consecutive errors
consecutive_errors = 0
# Main service loop
while True:
try:
# Main processing
runner.fetch_and_set_mails()
# Reset error counter on success
if consecutive_errors > 0:
logger.info(f"Service recovered after {consecutive_errors} consecutive errors")
consecutive_errors = 0
# Normal operation sleep
sleep(normal_sleep_time)
except MailReaderService.REDIS_EXCEPTIONS as e:
# Redis-specific errors
consecutive_errors += 1
logger.error(f"Redis error (attempt {consecutive_errors}): {str(e)}")
# Use centralized reconnection handler from RedisHandler
redis_handler, need_extended_sleep = MailReaderService.handle_reconnection(
consecutive_errors=consecutive_errors, max_consecutive_errors=max_consecutive_errors
)
if redis_handler:
# Update runner's redis handler with the new instance
runner.redis_handler = redis_handler
runner.redis_connected = False # Will trigger reconnection on next cycle
# Sleep based on error count
if need_extended_sleep:
sleep(extended_error_sleep)
else:
sleep(error_sleep_time)
except socket.error as e:
# Email connection errors
consecutive_errors += 1
logger.error(f"Email connection error (attempt {consecutive_errors}): {str(e)}")
# Try to re-establish email connection
try:
logger.info("Attempting to re-establish email connection...")
# Create new email service directly
email_service = EmailReaderService(IsBankConfig())
email_service.login_and_connect()
# Create new runner with existing Redis handler and new email service
redis_handler = runner.redis_handler # Preserve existing Redis handler
runner = EmailServiceRunner(redis_handler=redis_handler, email_service=email_service)
logger.info("Successfully re-established email connection")
except Exception as email_retry_error:
logger.error(f"Failed to re-establish email connection: {str(email_retry_error)}")
# Determine sleep time based on consecutive errors
if consecutive_errors >= max_consecutive_errors:
logger.warning(f"Hit {max_consecutive_errors} consecutive email errors, taking longer pause")
sleep(extended_error_sleep)
else:
sleep(error_sleep_time)
except Exception as e:
# Any other unexpected errors
consecutive_errors += 1
logger.error(f"Unexpected error (attempt {consecutive_errors}): {str(e)}")
# For any other error, try to reinitialize everything after some delay
if consecutive_errors >= max_consecutive_errors:
logger.warning(f"Hit {max_consecutive_errors} consecutive errors, reinitializing service")
try:
# Try to clean up existing connections
try:
runner.drop()
except Exception as cleanup_error:
logger.warning(f"Error during cleanup: {str(cleanup_error)}")
# Reinitialize the service directly
redis_handler = MailReaderService()
email_service = EmailReaderService(IsBankConfig())
email_service.login_and_connect()
runner = EmailServiceRunner(redis_handler=redis_handler, email_service=email_service)
if runner:
logger.info("Successfully reinitialized email service runner")
consecutive_errors = 0 # Reset counter after reinitialization
else:
logger.error("Failed to reinitialize email service runner")
except Exception as reinit_error:
logger.error(f"Service reinitialization failed: {str(reinit_error)}")
sleep(extended_error_sleep)
else:
# For fewer consecutive errors, just retry the current runner
print(f"Error: {str(e)}")
sleep(error_sleep_time)

View File

@@ -0,0 +1,16 @@
import os
from Depends.config import ConfigServices
class IsBankConfig:
MAILBOX: str = os.getenv("MAILBOX", "bilgilendirme@ileti.isbank.com.tr")
AUTHORIZE_IBAN: str = os.getenv("AUTHORIZE_IBAN", "4245-0093333")
NO_ATTACHMENT_FOLDER: str = "NoAttachment"
COMPLETED_FOLDER: str = "Completed"
TASK_DATA_PREFIX: str = ConfigServices.MAIN_TASK_PREFIX
TASK_MAILID_INDEX_PREFIX: str = ConfigServices.TASK_MAILID_INDEX_PREFIX
TASK_UUID_INDEX_PREFIX: str = ConfigServices.TASK_UUID_INDEX_PREFIX
TASK_SEEN_PREFIX: str = ConfigServices.TASK_SEEN_PREFIX
SERVICE_PREFIX: str = ConfigServices.SERVICE_PREFIX_MAIL_READER
NEXT_SERVICE_PREFIX: str = ConfigServices.SERVICE_PREFIX_MAIL_PARSER

View File

@@ -0,0 +1,13 @@
[project]
name = "isbank-email-reader"
version = "0.1.0"
description = "IsBank Email Reader Service"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"arrow>=1.3.0",
"redis>=6.4.0",
"pydantic>=2.0.0",
"pydantic-settings>=2.0.0",
"email-validator>=2.0.0",
]

View File

@@ -0,0 +1,4 @@
Uses
- MainRedisHandler
- MailHandler

View File

@@ -0,0 +1,9 @@
[project]
name = "reader"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"redis>=6.4.0",
]

View File

@@ -0,0 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "reader"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "redis" },
]
[package.metadata]
requires-dist = [{ name = "redis", specifier = ">=6.4.0" }]
[[package]]
name = "redis"
version = "6.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0d/d6/e8b92798a5bd67d659d51a18170e91c16ac3b59738d91894651ee255ed49/redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", size = 4647399, upload-time = "2025-08-07T08:10:11.441Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" },
]