Spaces:
Running
Running
added redis and aiven ping
Browse files- aiven_keep_alive_service.py +80 -0
- keep_projects_alive_service.py +4 -0
- redis_keep_alive_service.py +63 -0
- requirements.txt +3 -1
aiven_keep_alive_service.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
import psycopg2 # For PostgreSQL
|
| 5 |
+
import pymysql # For MySQL
|
| 6 |
+
|
| 7 |
+
# Load environment variables
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
sql_uri = os.getenv("AIVEN_MYSQL_URI")
|
| 11 |
+
postgres_uri = os.getenv("AIVEN_POSTGRES_URI")
|
| 12 |
+
|
| 13 |
+
# Configure logging
|
| 14 |
+
logging.basicConfig(
|
| 15 |
+
level=logging.INFO,
|
| 16 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
| 17 |
+
handlers=[
|
| 18 |
+
logging.StreamHandler(),
|
| 19 |
+
logging.FileHandler('keepalive.log')
|
| 20 |
+
]
|
| 21 |
+
)
|
| 22 |
+
logger = logging.getLogger('KeepAlive')
|
| 23 |
+
|
| 24 |
+
def ping_mysql():
|
| 25 |
+
"""Ping MySQL database to keep connection alive"""
|
| 26 |
+
try:
|
| 27 |
+
from urllib.parse import urlparse, parse_qs
|
| 28 |
+
|
| 29 |
+
# Parse the URI
|
| 30 |
+
parsed_uri = urlparse(sql_uri)
|
| 31 |
+
|
| 32 |
+
# Extract connection parameters
|
| 33 |
+
host = parsed_uri.hostname
|
| 34 |
+
port = parsed_uri.port or 3306 # default MySQL port
|
| 35 |
+
user = parsed_uri.username
|
| 36 |
+
password = parsed_uri.password
|
| 37 |
+
database = parsed_uri.path.lstrip('/') or 'defaultdb'
|
| 38 |
+
|
| 39 |
+
# Parse query parameters for SSL mode
|
| 40 |
+
query_params = parse_qs(parsed_uri.query)
|
| 41 |
+
ssl_mode = query_params.get('ssl-mode', ['REQUIRED'])[0]
|
| 42 |
+
|
| 43 |
+
connection = pymysql.connect(
|
| 44 |
+
host=host,
|
| 45 |
+
port=port,
|
| 46 |
+
user=user,
|
| 47 |
+
password=password,
|
| 48 |
+
database=database,
|
| 49 |
+
ssl={'mode': ssl_mode} if ssl_mode else None
|
| 50 |
+
)
|
| 51 |
+
with connection.cursor() as cursor:
|
| 52 |
+
cursor.execute("SELECT 1")
|
| 53 |
+
result = cursor.fetchone()
|
| 54 |
+
logger.info(f"MySQL ping successful: {result}")
|
| 55 |
+
connection.close()
|
| 56 |
+
except Exception as e:
|
| 57 |
+
logger.error(f"MySQL ping failed: {str(e)}")
|
| 58 |
+
|
| 59 |
+
def ping_postgres():
|
| 60 |
+
"""Ping PostgreSQL database to keep connection alive"""
|
| 61 |
+
try:
|
| 62 |
+
connection = psycopg2.connect(postgres_uri)
|
| 63 |
+
cursor = connection.cursor()
|
| 64 |
+
cursor.execute("SELECT 1")
|
| 65 |
+
result = cursor.fetchone()
|
| 66 |
+
logger.info(f"PostgreSQL ping successful: {result}")
|
| 67 |
+
cursor.close()
|
| 68 |
+
connection.close()
|
| 69 |
+
except Exception as e:
|
| 70 |
+
logger.error(f"PostgreSQL ping failed: {str(e)}")
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def ping_aiven_projects():
|
| 75 |
+
"""Ping Aiven projects to keep connections alive"""
|
| 76 |
+
logger.info("Starting Aiven service health check")
|
| 77 |
+
ping_mysql()
|
| 78 |
+
ping_postgres()
|
| 79 |
+
|
| 80 |
+
|
keep_projects_alive_service.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
|
| 2 |
|
|
|
|
| 3 |
from mongodb_keep_alive_service import ping_mongodb_projects
|
| 4 |
from neondb_postgres_keep_alive_service import ping_neondb_projects
|
| 5 |
from pinecone_keep_alive_service import ping_all_pinecone_indexes
|
|
|
|
| 6 |
from supabase_keep_alive_service import ping_all_supabase_projects
|
| 7 |
|
| 8 |
|
|
@@ -11,4 +13,6 @@ def ping_all_projects():
|
|
| 11 |
ping_neondb_projects()
|
| 12 |
ping_all_pinecone_indexes()
|
| 13 |
ping_mongodb_projects()
|
|
|
|
|
|
|
| 14 |
|
|
|
|
| 1 |
|
| 2 |
|
| 3 |
+
from aiven_keep_alive_service import ping_aiven_projects
|
| 4 |
from mongodb_keep_alive_service import ping_mongodb_projects
|
| 5 |
from neondb_postgres_keep_alive_service import ping_neondb_projects
|
| 6 |
from pinecone_keep_alive_service import ping_all_pinecone_indexes
|
| 7 |
+
from redis_keep_alive_service import ping_all_redis_projects
|
| 8 |
from supabase_keep_alive_service import ping_all_supabase_projects
|
| 9 |
|
| 10 |
|
|
|
|
| 13 |
ping_neondb_projects()
|
| 14 |
ping_all_pinecone_indexes()
|
| 15 |
ping_mongodb_projects()
|
| 16 |
+
ping_aiven_projects()
|
| 17 |
+
ping_all_redis_projects()
|
| 18 |
|
redis_keep_alive_service.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
import redis
|
| 4 |
+
import logging
|
| 5 |
+
from datetime import datetime
|
| 6 |
+
|
| 7 |
+
# Set up logging
|
| 8 |
+
logging.basicConfig(
|
| 9 |
+
level=logging.INFO,
|
| 10 |
+
format='%(asctime)s - %(levelname)s - %(message)s',
|
| 11 |
+
handlers=[
|
| 12 |
+
logging.FileHandler('redis_ping.log'),
|
| 13 |
+
logging.StreamHandler()
|
| 14 |
+
]
|
| 15 |
+
)
|
| 16 |
+
logger = logging.getLogger(__name__)
|
| 17 |
+
|
| 18 |
+
load_dotenv()
|
| 19 |
+
|
| 20 |
+
REDIS_SERVICES = {
|
| 21 |
+
"redis_production": {
|
| 22 |
+
"host": os.getenv("REDIS_PRODUCTION_HOST"),
|
| 23 |
+
"port": os.getenv("REDIS_PRODUCTION_PORT"),
|
| 24 |
+
"password": os.getenv("REDIS_PRODUCTION_PASSWORD"),
|
| 25 |
+
},
|
| 26 |
+
"redis_development": {
|
| 27 |
+
"host": os.getenv("REDIS_DEVELOPMENT_HOST"),
|
| 28 |
+
"port": os.getenv("REDIS_DEVELOPMENT_PORT"),
|
| 29 |
+
"password": os.getenv("REDIS_DEVELOPMENT_PASSWORD"),
|
| 30 |
+
},
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
def ping_redis(redis_config):
|
| 34 |
+
try:
|
| 35 |
+
start_time = datetime.now()
|
| 36 |
+
r = redis.Redis(
|
| 37 |
+
host=redis_config["host"],
|
| 38 |
+
port=redis_config["port"],
|
| 39 |
+
password=redis_config["password"],
|
| 40 |
+
ssl=True if redis_config.get("ssl") else False,
|
| 41 |
+
)
|
| 42 |
+
response = r.ping()
|
| 43 |
+
latency = (datetime.now() - start_time).total_seconds() * 1000 # in milliseconds
|
| 44 |
+
logger.info(
|
| 45 |
+
f"Successfully pinged {redis_config['host']}:{redis_config['port']} - "
|
| 46 |
+
f"Response: {response}, Latency: {latency:.2f}ms"
|
| 47 |
+
)
|
| 48 |
+
return True
|
| 49 |
+
except Exception as e:
|
| 50 |
+
logger.error(f"Failed to ping {redis_config.get('host', 'unknown_host')}: {str(e)}")
|
| 51 |
+
return False
|
| 52 |
+
|
| 53 |
+
def ping_all_redis_projects():
|
| 54 |
+
logger.info("Starting Redis service health check")
|
| 55 |
+
results = {}
|
| 56 |
+
|
| 57 |
+
for service_name, config in REDIS_SERVICES.items():
|
| 58 |
+
logger.info(f"Pinging {service_name} at {config['host']}:{config['port']}")
|
| 59 |
+
results[service_name] = ping_redis(config)
|
| 60 |
+
|
| 61 |
+
logger.info("Completed all Redis service checks")
|
| 62 |
+
return results
|
| 63 |
+
|
requirements.txt
CHANGED
|
@@ -8,4 +8,6 @@ twilio
|
|
| 8 |
pymongo==4.11.2
|
| 9 |
psycopg2-binary==2.9.10
|
| 10 |
pinecone==6.0.2
|
| 11 |
-
supabase==2.13.0
|
|
|
|
|
|
|
|
|
| 8 |
pymongo==4.11.2
|
| 9 |
psycopg2-binary==2.9.10
|
| 10 |
pinecone==6.0.2
|
| 11 |
+
supabase==2.13.0
|
| 12 |
+
pymysql
|
| 13 |
+
redis
|