sage/bin/backend_accounting.py

94 lines
2.8 KiB
Python

#!/usr/bin/env python
"""
独立运行的产品后台计费程序。
产品记账已从 llmage 迁移到 product_management 模块。
"""
import os
import sys
import asyncio
import signal
# 切换到 Sage 工作目录
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'py3', 'lib', 'python3.10', 'site-packages'))
from appPublic.folderUtils import ProgramPath
from appPublic.jsonConfig import getConfig
from sqlor.dbpools import DBPools
from ahserver.serverenv import ServerEnv
from ahserver.globalEnv import initEnv
from appPublic.log import MyLogger, debug, exception, info
from accounting.init import load_accounting
from appbase.init import load_appbase
from llmage.init import load_llmage
from pricing.init import load_pricing
from discount.init import load_discount
from dapi.init import load_dapi
from product_management import get_manager
# 初始化配置
p = ProgramPath()
config = getConfig(NS={'workdir': os.getcwd(), 'ProgramPath': p})
db = DBPools(config.databases)
# 生产环境 get_business_date 内直接 db=DBPools() 创建空实例 → sqlorFactory(None)
# 替换为使用已初始化的 db
import appbase.businessdate as _bd
_orig_gbd = _bd.get_business_date
async def _patched_get_business_date(sor=None):
async def _f(sor):
sql = "select * from params where params_name = 'business_date'"
recs = await sor.sqlExe(sql, {})
if len(recs) > 0:
return recs[0]['params_value']
raise Exception('BusinessDateParamsError')
if sor:
return await _f(sor)
async with db.sqlorContext(get_module_dbname('appbase')) as sor:
return await _f(sor)
_bd.get_business_date = _patched_get_business_date
def get_module_dbname(m):
return 'sage'
def main():
logger = MyLogger('backend_accounting', levelname='info',
logfile=os.path.join(os.getcwd(), 'logs', 'backend_accounting.log'))
info(f'Backend accounting process started (PID: {os.getpid()})')
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
def handle_signal(signum, frame):
info(f'Received signal {signum}, shutting down...')
for task in asyncio.all_tasks(loop):
task.cancel()
loop.stop()
signal.signal(signal.SIGTERM, handle_signal)
signal.signal(signal.SIGINT, handle_signal)
initEnv()
env = ServerEnv()
env.get_module_dbname = get_module_dbname
# Mock event_dispatcher for standalone mode
class _MockDispatcher:
def bind(self, *a, **kw): pass
env.event_dispatcher = _MockDispatcher()
load_appbase()
load_accounting()
load_pricing()
load_discount()
load_dapi()
load_llmage()
manager = get_manager()
try:
loop.run_until_complete(manager.backend_accounting())
except asyncio.CancelledError:
pass
finally:
loop.close()
info('Backend accounting process stopped.')
if __name__ == '__main__':
main()