update pay ui
This commit is contained in:
73
app.py
73
app.py
@@ -318,7 +318,9 @@ if USE_REDIS_SESSION:
|
||||
app.config['SESSION_PERMANENT'] = True
|
||||
app.config['SESSION_USE_SIGNER'] = True # 对 session cookie 签名,提高安全性
|
||||
app.config['SESSION_KEY_PREFIX'] = 'vf_session:' # session key 前缀
|
||||
print(f"📦 Flask Session 配置: Redis {_REDIS_HOST}:{_REDIS_PORT}/db=1")
|
||||
# 显式设置 Session 生命周期为 7 天(Flask-Session 会用这个值设置 Redis TTL)
|
||||
app.config['SESSION_LIFETIME'] = timedelta(days=7)
|
||||
print(f"📦 Flask Session 配置: Redis {_REDIS_HOST}:{_REDIS_PORT}/db=1, 过期时间: 7天")
|
||||
else:
|
||||
# 使用默认的 cookie session(单 Worker 模式可用)
|
||||
app.config['SESSION_TYPE'] = 'null' # 禁用服务端 session,使用 cookie
|
||||
@@ -10603,28 +10605,32 @@ def initialize_event_polling():
|
||||
print(f'\n[轮询] ========== 初始化事件轮询 (PID: {os.getpid()}) ==========')
|
||||
print(f'[轮询] 当前时间: {current_time.strftime("%Y-%m-%d %H:%M:%S")}')
|
||||
|
||||
# 查询近24小时内的所有活跃事件
|
||||
events_in_24h = Event.query.filter(
|
||||
Event.created_at >= time_24h_ago,
|
||||
Event.status == 'active'
|
||||
).order_by(Event.id.asc()).all()
|
||||
# 查询数据库中最大的事件 ID(不限于 24 小时)
|
||||
max_event = Event.query.filter_by(status='active').order_by(Event.id.desc()).first()
|
||||
db_max_id = max_event.id if max_event else 0
|
||||
|
||||
# 初始化最大事件ID(只有当 Redis 中没有值时才设置)
|
||||
# 获取 Redis 中当前保存的最大 ID
|
||||
current_redis_max = _get_last_max_event_id()
|
||||
if events_in_24h:
|
||||
db_max_id = max(event.id for event in events_in_24h)
|
||||
if db_max_id > current_redis_max:
|
||||
_set_last_max_event_id(db_max_id)
|
||||
print(f'[轮询] 初始化最大事件ID: {db_max_id}')
|
||||
else:
|
||||
print(f'[轮询] 使用 Redis 中的最大事件ID: {current_redis_max}')
|
||||
print(f'[轮询] 近24小时内共有 {len(events_in_24h)} 个活跃事件')
|
||||
|
||||
print(f'[轮询] 数据库最大事件ID: {db_max_id}')
|
||||
print(f'[轮询] Redis 中的最大事件ID: {current_redis_max}')
|
||||
|
||||
# 始终使用数据库中的最大 ID(避免推送历史事件)
|
||||
# 只在 Redis 值为 0 或小于数据库最大值时更新
|
||||
if current_redis_max == 0 or db_max_id > current_redis_max:
|
||||
_set_last_max_event_id(db_max_id)
|
||||
print(f'[轮询] 更新最大事件ID为: {db_max_id}(避免推送历史事件)')
|
||||
else:
|
||||
print(f'[轮询] 近24小时内没有活跃事件')
|
||||
print(f'[轮询] 保持 Redis 中的最大事件ID: {current_redis_max}')
|
||||
|
||||
# 统计数据库中的事件总数
|
||||
total_events = Event.query.filter_by(status='active').count()
|
||||
print(f'[轮询] 数据库中共有 {total_events} 个活跃事件(所有时间)')
|
||||
events_in_24h_count = Event.query.filter(
|
||||
Event.created_at >= time_24h_ago,
|
||||
Event.status == 'active'
|
||||
).count()
|
||||
print(f'[轮询] 数据库中共有 {total_events} 个活跃事件(其中近24小时: {events_in_24h_count} 个)')
|
||||
print(f'[轮询] 只会推送 ID > {max(current_redis_max, db_max_id)} 的新事件')
|
||||
print(f'[轮询] ========== 初始化完成 ==========\n')
|
||||
|
||||
# 创建后台调度器
|
||||
@@ -10651,17 +10657,40 @@ def initialize_event_polling():
|
||||
|
||||
# ==================== Gunicorn 兼容:自动初始化轮询 ====================
|
||||
|
||||
# Redis key 用于确保只有一个 Worker 启动调度器
|
||||
REDIS_KEY_SCHEDULER_LOCK = 'vf:event_polling:scheduler_lock'
|
||||
|
||||
|
||||
def _auto_init_polling():
|
||||
"""
|
||||
自动初始化事件轮询(兼容 gunicorn)
|
||||
使用延迟初始化,在第一个请求到来时初始化
|
||||
使用 Redis 锁确保整个集群只有一个 Worker 启动调度器
|
||||
"""
|
||||
global _polling_initialized
|
||||
if not _polling_initialized:
|
||||
try:
|
||||
import os
|
||||
|
||||
if _polling_initialized:
|
||||
return
|
||||
|
||||
try:
|
||||
# 尝试获取调度器锁(10分钟过期,防止死锁)
|
||||
lock_acquired = redis_client.set(
|
||||
REDIS_KEY_SCHEDULER_LOCK,
|
||||
str(os.getpid()),
|
||||
nx=True, # 只在不存在时设置
|
||||
ex=600 # 10分钟过期
|
||||
)
|
||||
|
||||
if lock_acquired:
|
||||
print(f'[轮询] Worker {os.getpid()} 获得调度器锁,启动轮询调度器')
|
||||
initialize_event_polling()
|
||||
except Exception as e:
|
||||
print(f'[轮询] 自动初始化失败: {e}')
|
||||
else:
|
||||
# 其他 Worker 已经启动了调度器
|
||||
_polling_initialized = True # 标记为已初始化,避免重复尝试
|
||||
print(f'[轮询] Worker {os.getpid()} 跳过调度器初始化(已由其他 Worker 启动)')
|
||||
|
||||
except Exception as e:
|
||||
print(f'[轮询] 自动初始化失败: {e}')
|
||||
|
||||
|
||||
# 注册 before_request 钩子,确保 gunicorn 启动后也能初始化轮询
|
||||
|
||||
Reference in New Issue
Block a user