mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
添加对 PostgreSQL 的支持
This commit is contained in:
+24
-8
@@ -82,10 +82,16 @@ class ConfigModel(BaseModel):
|
|||||||
PORT: int = 3001
|
PORT: int = 3001
|
||||||
# 前端监听端口
|
# 前端监听端口
|
||||||
NGINX_PORT: int = 3000
|
NGINX_PORT: int = 3000
|
||||||
|
# 配置文件目录
|
||||||
|
CONFIG_DIR: Optional[str] = None
|
||||||
|
# 超级管理员
|
||||||
|
SUPERUSER: str = "admin"
|
||||||
# 是否调试模式
|
# 是否调试模式
|
||||||
DEBUG: bool = False
|
DEBUG: bool = False
|
||||||
# 是否开发模式
|
# 是否开发模式
|
||||||
DEV: bool = False
|
DEV: bool = False
|
||||||
|
# 数据库类型,支持 sqlite 和 postgresql,默认使用 sqlite
|
||||||
|
DB_TYPE: str = "sqlite"
|
||||||
# 是否在控制台输出 SQL 语句,默认关闭
|
# 是否在控制台输出 SQL 语句,默认关闭
|
||||||
DB_ECHO: bool = False
|
DB_ECHO: bool = False
|
||||||
# 数据库连接池类型,QueuePool, NullPool
|
# 数据库连接池类型,QueuePool, NullPool
|
||||||
@@ -100,16 +106,26 @@ class ConfigModel(BaseModel):
|
|||||||
DB_TIMEOUT: int = 60
|
DB_TIMEOUT: int = 60
|
||||||
# SQLite 是否启用 WAL 模式,默认开启
|
# SQLite 是否启用 WAL 模式,默认开启
|
||||||
DB_WAL_ENABLE: bool = True
|
DB_WAL_ENABLE: bool = True
|
||||||
|
# PostgreSQL 主机地址
|
||||||
|
DB_POSTGRESQL_HOST: str = "localhost"
|
||||||
|
# PostgreSQL 端口
|
||||||
|
DB_POSTGRESQL_PORT: int = 5432
|
||||||
|
# PostgreSQL 数据库名
|
||||||
|
DB_POSTGRESQL_DATABASE: str = "moviepilot"
|
||||||
|
# PostgreSQL 用户名
|
||||||
|
DB_POSTGRESQL_USERNAME: str = "moviepilot"
|
||||||
|
# PostgreSQL 密码
|
||||||
|
DB_POSTGRESQL_PASSWORD: str = "moviepilot"
|
||||||
|
# PostgreSQL 连接池大小
|
||||||
|
DB_POSTGRESQL_POOL_SIZE: int = 20
|
||||||
|
# PostgreSQL 连接池溢出数量
|
||||||
|
DB_POSTGRESQL_MAX_OVERFLOW: int = 30
|
||||||
# 缓存类型,支持 cachetools 和 redis,默认使用 cachetools
|
# 缓存类型,支持 cachetools 和 redis,默认使用 cachetools
|
||||||
CACHE_BACKEND_TYPE: str = "cachetools"
|
CACHE_BACKEND_TYPE: str = "cachetools"
|
||||||
# 缓存连接字符串,仅外部缓存(如 Redis、Memcached)需要
|
# 缓存连接字符串,仅外部缓存(如 Redis、Memcached)需要
|
||||||
CACHE_BACKEND_URL: Optional[str] = None
|
CACHE_BACKEND_URL: Optional[str] = None
|
||||||
# Redis 缓存最大内存限制,未配置时,如开启大内存模式时为 "1024mb",未开启时为 "256mb"
|
# Redis 缓存最大内存限制,未配置时,如开启大内存模式时为 "1024mb",未开启时为 "256mb"
|
||||||
CACHE_REDIS_MAXMEMORY: Optional[str] = None
|
CACHE_REDIS_MAXMEMORY: Optional[str] = None
|
||||||
# 配置文件目录
|
|
||||||
CONFIG_DIR: Optional[str] = None
|
|
||||||
# 超级管理员
|
|
||||||
SUPERUSER: str = "admin"
|
|
||||||
# 辅助认证,允许通过外部服务进行认证、单点登录以及自动创建用户
|
# 辅助认证,允许通过外部服务进行认证、单点登录以及自动创建用户
|
||||||
AUXILIARY_AUTH_ENABLE: bool = False
|
AUXILIARY_AUTH_ENABLE: bool = False
|
||||||
# API密钥,需要更换
|
# API密钥,需要更换
|
||||||
@@ -124,6 +140,10 @@ class ConfigModel(BaseModel):
|
|||||||
SEARCH_SOURCE: str = "themoviedb,douban,bangumi"
|
SEARCH_SOURCE: str = "themoviedb,douban,bangumi"
|
||||||
# 媒体识别来源 themoviedb/douban
|
# 媒体识别来源 themoviedb/douban
|
||||||
RECOGNIZE_SOURCE: str = "themoviedb"
|
RECOGNIZE_SOURCE: str = "themoviedb"
|
||||||
|
# 元数据识别缓存过期时间(小时)
|
||||||
|
META_CACHE_EXPIRE: int = 0
|
||||||
|
# 电视剧动漫的分类genre_ids
|
||||||
|
ANIME_GENREIDS: List[int] = Field(default=[16])
|
||||||
# 刮削来源 themoviedb/douban
|
# 刮削来源 themoviedb/douban
|
||||||
SCRAP_SOURCE: str = "themoviedb"
|
SCRAP_SOURCE: str = "themoviedb"
|
||||||
# 新增已入库媒体是否跟随TMDB信息变化
|
# 新增已入库媒体是否跟随TMDB信息变化
|
||||||
@@ -151,10 +171,6 @@ class ConfigModel(BaseModel):
|
|||||||
U115_APP_ID: str = "100196807"
|
U115_APP_ID: str = "100196807"
|
||||||
# Alipan AppId
|
# Alipan AppId
|
||||||
ALIPAN_APP_ID: str = "ac1bf04dc9fd4d9aaabb65b4a668d403"
|
ALIPAN_APP_ID: str = "ac1bf04dc9fd4d9aaabb65b4a668d403"
|
||||||
# 元数据识别缓存过期时间(小时)
|
|
||||||
META_CACHE_EXPIRE: int = 0
|
|
||||||
# 电视剧动漫的分类genre_ids
|
|
||||||
ANIME_GENREIDS: List[int] = Field(default=[16])
|
|
||||||
# 用户认证站点
|
# 用户认证站点
|
||||||
AUTH_SITE: str = ""
|
AUTH_SITE: str = ""
|
||||||
# 重启自动升级
|
# 重启自动升级
|
||||||
|
|||||||
+85
-5
@@ -1,19 +1,43 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any, Generator, List, Optional, Self, Tuple, AsyncGenerator, Sequence, Union
|
from typing import Any, Generator, List, Optional, Self, Tuple, AsyncGenerator, Union
|
||||||
|
|
||||||
from sqlalchemy import NullPool, QueuePool, and_, create_engine, inspect, text, select, delete
|
from sqlalchemy import NullPool, QueuePool, and_, create_engine, inspect, text, select, delete, Column, Integer, \
|
||||||
|
Sequence
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
||||||
from sqlalchemy.orm import Session, as_declarative, declared_attr, scoped_session, sessionmaker
|
from sqlalchemy.orm import Session, as_declarative, declared_attr, scoped_session, sessionmaker
|
||||||
|
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
|
|
||||||
|
|
||||||
|
def get_id_column():
|
||||||
|
"""
|
||||||
|
根据数据库类型返回合适的ID列定义
|
||||||
|
"""
|
||||||
|
if settings.DB_TYPE.lower() == "postgresql":
|
||||||
|
# PostgreSQL使用SERIAL类型
|
||||||
|
return Column(Integer, primary_key=True, index=True)
|
||||||
|
else:
|
||||||
|
# SQLite使用Sequence
|
||||||
|
return Column(Integer, Sequence('id'), primary_key=True, index=True)
|
||||||
|
|
||||||
|
|
||||||
def _get_database_engine(is_async: bool = False):
|
def _get_database_engine(is_async: bool = False):
|
||||||
"""
|
"""
|
||||||
获取数据库连接参数并设置WAL模式
|
获取数据库连接参数并设置WAL模式
|
||||||
:param is_async: 是否创建异步引擎,True - 异步引擎, False - 同步引擎
|
:param is_async: 是否创建异步引擎,True - 异步引擎, False - 同步引擎
|
||||||
:return: 返回对应的数据库引擎
|
:return: 返回对应的数据库引擎
|
||||||
"""
|
"""
|
||||||
|
# 根据数据库类型选择连接方式
|
||||||
|
if settings.DB_TYPE.lower() == "postgresql":
|
||||||
|
return _get_postgresql_engine(is_async)
|
||||||
|
else:
|
||||||
|
return _get_sqlite_engine(is_async)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sqlite_engine(is_async: bool = False):
|
||||||
|
"""
|
||||||
|
获取SQLite数据库引擎
|
||||||
|
"""
|
||||||
# 连接参数
|
# 连接参数
|
||||||
_connect_args = {
|
_connect_args = {
|
||||||
"timeout": settings.DB_TIMEOUT,
|
"timeout": settings.DB_TIMEOUT,
|
||||||
@@ -52,7 +76,7 @@ def _get_database_engine(is_async: bool = False):
|
|||||||
_journal_mode = "WAL" if settings.DB_WAL_ENABLE else "DELETE"
|
_journal_mode = "WAL" if settings.DB_WAL_ENABLE else "DELETE"
|
||||||
with engine.connect() as connection:
|
with engine.connect() as connection:
|
||||||
current_mode = connection.execute(text(f"PRAGMA journal_mode={_journal_mode};")).scalar()
|
current_mode = connection.execute(text(f"PRAGMA journal_mode={_journal_mode};")).scalar()
|
||||||
print(f"Database journal mode set to: {current_mode}")
|
print(f"SQLite database journal mode set to: {current_mode}")
|
||||||
|
|
||||||
return engine
|
return engine
|
||||||
else:
|
else:
|
||||||
@@ -78,12 +102,68 @@ def _get_database_engine(is_async: bool = False):
|
|||||||
async with async_engine.connect() as _connection:
|
async with async_engine.connect() as _connection:
|
||||||
result = await _connection.execute(text(f"PRAGMA journal_mode={_journal_mode};"))
|
result = await _connection.execute(text(f"PRAGMA journal_mode={_journal_mode};"))
|
||||||
_current_mode = result.scalar()
|
_current_mode = result.scalar()
|
||||||
print(f"Async database journal mode set to: {_current_mode}")
|
print(f"Async SQLite database journal mode set to: {_current_mode}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
asyncio.run(set_async_wal_mode())
|
asyncio.run(set_async_wal_mode())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to set async WAL mode: {e}")
|
print(f"Failed to set async SQLite WAL mode: {e}")
|
||||||
|
|
||||||
|
return async_engine
|
||||||
|
|
||||||
|
|
||||||
|
def _get_postgresql_engine(is_async: bool = False):
|
||||||
|
"""
|
||||||
|
获取PostgreSQL数据库引擎
|
||||||
|
"""
|
||||||
|
# 构建PostgreSQL连接URL
|
||||||
|
if settings.DB_POSTGRESQL_PASSWORD:
|
||||||
|
db_url = f"postgresql://{settings.DB_POSTGRESQL_USERNAME}:{settings.DB_POSTGRESQL_PASSWORD}@{settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}"
|
||||||
|
else:
|
||||||
|
db_url = f"postgresql://{settings.DB_POSTGRESQL_USERNAME}@{settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}"
|
||||||
|
|
||||||
|
# 创建同步引擎
|
||||||
|
if not is_async:
|
||||||
|
# 根据池类型设置 poolclass 和相关参数
|
||||||
|
_pool_class = NullPool if settings.DB_POOL_TYPE == "NullPool" else QueuePool
|
||||||
|
|
||||||
|
# 数据库参数
|
||||||
|
_db_kwargs = {
|
||||||
|
"url": db_url,
|
||||||
|
"pool_pre_ping": settings.DB_POOL_PRE_PING,
|
||||||
|
"echo": settings.DB_ECHO,
|
||||||
|
"poolclass": _pool_class,
|
||||||
|
"pool_recycle": settings.DB_POOL_RECYCLE,
|
||||||
|
}
|
||||||
|
|
||||||
|
# 当使用 QueuePool 时,添加 QueuePool 特有的参数
|
||||||
|
if _pool_class == QueuePool:
|
||||||
|
_db_kwargs.update({
|
||||||
|
"pool_size": settings.DB_POSTGRESQL_POOL_SIZE,
|
||||||
|
"pool_timeout": settings.DB_POOL_TIMEOUT,
|
||||||
|
"max_overflow": settings.DB_POSTGRESQL_MAX_OVERFLOW
|
||||||
|
})
|
||||||
|
|
||||||
|
# 创建数据库引擎
|
||||||
|
engine = create_engine(**_db_kwargs)
|
||||||
|
print(f"PostgreSQL database connected to {settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}")
|
||||||
|
|
||||||
|
return engine
|
||||||
|
else:
|
||||||
|
# 构建异步PostgreSQL连接URL
|
||||||
|
async_db_url = f"postgresql+asyncpg://{settings.DB_POSTGRESQL_USERNAME}:{settings.DB_POSTGRESQL_PASSWORD}@{settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}"
|
||||||
|
|
||||||
|
# 数据库参数,只能使用 NullPool
|
||||||
|
_db_kwargs = {
|
||||||
|
"url": async_db_url,
|
||||||
|
"pool_pre_ping": settings.DB_POOL_PRE_PING,
|
||||||
|
"echo": settings.DB_ECHO,
|
||||||
|
"poolclass": NullPool,
|
||||||
|
"pool_recycle": settings.DB_POOL_RECYCLE,
|
||||||
|
}
|
||||||
|
# 创建异步数据库引擎
|
||||||
|
async_engine = create_async_engine(**_db_kwargs)
|
||||||
|
print(f"Async PostgreSQL database connected to {settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}")
|
||||||
|
|
||||||
return async_engine
|
return async_engine
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -18,12 +18,22 @@ def update_db():
|
|||||||
"""
|
"""
|
||||||
更新数据库
|
更新数据库
|
||||||
"""
|
"""
|
||||||
db_location = settings.CONFIG_PATH / 'user.db'
|
|
||||||
script_location = settings.ROOT_PATH / 'database'
|
script_location = settings.ROOT_PATH / 'database'
|
||||||
try:
|
try:
|
||||||
alembic_cfg = Config()
|
alembic_cfg = Config()
|
||||||
alembic_cfg.set_main_option('script_location', str(script_location))
|
alembic_cfg.set_main_option('script_location', str(script_location))
|
||||||
alembic_cfg.set_main_option('sqlalchemy.url', f"sqlite:///{db_location}")
|
|
||||||
|
# 根据数据库类型设置不同的URL
|
||||||
|
if settings.DB_TYPE.lower() == "postgresql":
|
||||||
|
if settings.DB_POSTGRESQL_PASSWORD:
|
||||||
|
db_url = f"postgresql://{settings.DB_POSTGRESQL_USERNAME}:{settings.DB_POSTGRESQL_PASSWORD}@{settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}"
|
||||||
|
else:
|
||||||
|
db_url = f"postgresql://{settings.DB_POSTGRESQL_USERNAME}@{settings.DB_POSTGRESQL_HOST}:{settings.DB_POSTGRESQL_PORT}/{settings.DB_POSTGRESQL_DATABASE}"
|
||||||
|
else:
|
||||||
|
db_location = settings.CONFIG_PATH / 'user.db'
|
||||||
|
db_url = f"sqlite:///{db_location}"
|
||||||
|
|
||||||
|
alembic_cfg.set_main_option('sqlalchemy.url', db_url)
|
||||||
upgrade(alembic_cfg, 'head')
|
upgrade(alembic_cfg, 'head')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'数据库更新失败:{str(e)}')
|
logger.error(f'数据库更新失败:{str(e)}')
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import time
|
import time
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON, select
|
from sqlalchemy import Column, Integer, String, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query
|
from app.db import db_query, db_update, get_id_column, Base, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class DownloadHistory(Base):
|
class DownloadHistory(Base):
|
||||||
"""
|
"""
|
||||||
下载历史记录
|
下载历史记录
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 保存路径
|
# 保存路径
|
||||||
path = Column(String, nullable=False, index=True)
|
path = Column(String, nullable=False, index=True)
|
||||||
# 类型 电影/电视剧
|
# 类型 电影/电视剧
|
||||||
@@ -188,7 +188,7 @@ class DownloadFiles(Base):
|
|||||||
"""
|
"""
|
||||||
下载文件记录
|
下载文件记录
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 下载器
|
# 下载器
|
||||||
downloader = Column(String)
|
downloader = Column(String)
|
||||||
# 下载任务Hash
|
# 下载任务Hash
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON
|
from sqlalchemy import Column, Integer, String, JSON
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, async_db_query, Base
|
from app.db import db_query, db_update, get_id_column, async_db_query, Base
|
||||||
|
|
||||||
|
|
||||||
class MediaServerItem(Base):
|
class MediaServerItem(Base):
|
||||||
"""
|
"""
|
||||||
媒体服务器媒体条目表
|
媒体服务器媒体条目表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 服务器类型
|
# 服务器类型
|
||||||
server = Column(String)
|
server = Column(String)
|
||||||
# 媒体库ID
|
# 媒体库ID
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON, select
|
from sqlalchemy import Column, Integer, String, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, Base, async_db_query
|
from app.db import db_query, Base, get_id_column, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class Message(Base):
|
class Message(Base):
|
||||||
"""
|
"""
|
||||||
消息表
|
消息表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 消息渠道
|
# 消息渠道
|
||||||
channel = Column(String)
|
channel = Column(String)
|
||||||
# 消息来源
|
# 消息来源
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON
|
from sqlalchemy import Column, String, JSON
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base
|
from app.db import db_query, db_update, get_id_column, Base
|
||||||
|
|
||||||
|
|
||||||
class PluginData(Base):
|
class PluginData(Base):
|
||||||
"""
|
"""
|
||||||
插件数据表
|
插件数据表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
plugin_id = Column(String, nullable=False, index=True)
|
plugin_id = Column(String, nullable=False, index=True)
|
||||||
key = Column(String, index=True, nullable=False)
|
key = Column(String, index=True, nullable=False)
|
||||||
value = Column(JSON)
|
value = Column(JSON)
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from sqlalchemy import Boolean, Column, Integer, String, Sequence, JSON, select, delete
|
from sqlalchemy import Boolean, Column, Integer, String, JSON, select, delete
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query, async_db_update
|
from app.db import db_query, db_update, Base, async_db_query, async_db_update, get_id_column
|
||||||
|
|
||||||
|
|
||||||
class Site(Base):
|
class Site(Base):
|
||||||
"""
|
"""
|
||||||
站点表
|
站点表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 站点名
|
# 站点名
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
# 域名Key
|
# 域名Key
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, select
|
from sqlalchemy import Column, String, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, Base, async_db_query
|
from app.db import db_query, Base, get_id_column, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class SiteIcon(Base):
|
class SiteIcon(Base):
|
||||||
"""
|
"""
|
||||||
站点图标表
|
站点图标表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 站点名称
|
# 站点名称
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False)
|
||||||
# 域名Key
|
# 域名Key
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON, select
|
from sqlalchemy import Column, Integer, String, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query
|
from app.db import db_query, db_update, get_id_column, Base, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class SiteStatistic(Base):
|
class SiteStatistic(Base):
|
||||||
"""
|
"""
|
||||||
站点统计表
|
站点统计表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 域名Key
|
# 域名Key
|
||||||
domain = Column(String, index=True)
|
domain = Column(String, index=True)
|
||||||
# 成功次数
|
# 成功次数
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, Float, JSON, func, or_, select
|
from sqlalchemy import Column, Integer, String, Float, JSON, func, or_, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, Base, async_db_query
|
from app.db import db_query, Base, get_id_column, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class SiteUserData(Base):
|
class SiteUserData(Base):
|
||||||
"""
|
"""
|
||||||
站点数据表
|
站点数据表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 站点域名
|
# 站点域名
|
||||||
domain = Column(String, index=True)
|
domain = Column(String, index=True)
|
||||||
# 站点名称
|
# 站点名称
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import time
|
import time
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, Float, JSON, select
|
from sqlalchemy import Column, Integer, String, Float, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query, async_db_update
|
from app.db import db_query, db_update, get_id_column, Base, async_db_query, async_db_update
|
||||||
|
|
||||||
|
|
||||||
class Subscribe(Base):
|
class Subscribe(Base):
|
||||||
"""
|
"""
|
||||||
订阅表
|
订阅表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 标题
|
# 标题
|
||||||
name = Column(String, nullable=False, index=True)
|
name = Column(String, nullable=False, index=True)
|
||||||
# 年份
|
# 年份
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, Float, JSON, select
|
from sqlalchemy import Column, Integer, String, Float, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, Base, async_db_query
|
from app.db import db_query, Base, get_id_column, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class SubscribeHistory(Base):
|
class SubscribeHistory(Base):
|
||||||
"""
|
"""
|
||||||
订阅历史表
|
订阅历史表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 标题
|
# 标题
|
||||||
name = Column(String, nullable=False, index=True)
|
name = Column(String, nullable=False, index=True)
|
||||||
# 年份
|
# 年份
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, JSON, select
|
from sqlalchemy import Column, String, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query
|
from app.db import db_query, db_update, Base, async_db_query, get_id_column
|
||||||
|
|
||||||
|
|
||||||
class SystemConfig(Base):
|
class SystemConfig(Base):
|
||||||
"""
|
"""
|
||||||
配置表
|
配置表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 主键
|
# 主键
|
||||||
key = Column(String, index=True)
|
key = Column(String, index=True)
|
||||||
# 值
|
# 值
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import time
|
import time
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, Sequence, Boolean, func, or_, JSON, select
|
from sqlalchemy import Column, Integer, String, Boolean, func, or_, JSON, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base, async_db_query
|
from app.db import db_query, db_update, get_id_column, Base, async_db_query
|
||||||
|
|
||||||
|
|
||||||
class TransferHistory(Base):
|
class TransferHistory(Base):
|
||||||
"""
|
"""
|
||||||
整理记录
|
整理记录
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 源路径
|
# 源路径
|
||||||
src = Column(String, index=True)
|
src = Column(String, index=True)
|
||||||
# 源存储
|
# 源存储
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from sqlalchemy import Boolean, Column, Integer, JSON, Sequence, String, select
|
from sqlalchemy import Boolean, Column, JSON, String, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import Base, db_query, db_update, async_db_query, async_db_update
|
from app.db import Base, db_query, db_update, async_db_query, async_db_update, get_id_column
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
@@ -10,7 +10,7 @@ class User(Base):
|
|||||||
用户表
|
用户表
|
||||||
"""
|
"""
|
||||||
# ID
|
# ID
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 用户名,唯一值
|
# 用户名,唯一值
|
||||||
name = Column(String, index=True, nullable=False)
|
name = Column(String, index=True, nullable=False)
|
||||||
# 邮箱
|
# 邮箱
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from sqlalchemy import Column, Integer, String, Sequence, UniqueConstraint, Index, JSON
|
from sqlalchemy import Column, String, UniqueConstraint, Index, JSON
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.db import db_query, db_update, Base
|
from app.db import db_query, db_update, get_id_column, Base
|
||||||
|
|
||||||
|
|
||||||
class UserConfig(Base):
|
class UserConfig(Base):
|
||||||
"""
|
"""
|
||||||
用户配置表
|
用户配置表
|
||||||
"""
|
"""
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 用户名
|
# 用户名
|
||||||
username = Column(String, index=True)
|
username = Column(String, index=True)
|
||||||
# 配置键
|
# 配置键
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, JSON, Sequence, String, and_, or_, select
|
from sqlalchemy import Column, Integer, JSON, String, and_, or_, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.db import Base, db_query, db_update, async_db_query, async_db_update
|
from app.db import Base, db_query, get_id_column, db_update, async_db_query, async_db_update
|
||||||
|
|
||||||
|
|
||||||
class Workflow(Base):
|
class Workflow(Base):
|
||||||
@@ -12,7 +12,7 @@ class Workflow(Base):
|
|||||||
工作流表
|
工作流表
|
||||||
"""
|
"""
|
||||||
# ID
|
# ID
|
||||||
id = Column(Integer, Sequence('id'), primary_key=True, index=True)
|
id = get_id_column()
|
||||||
# 名称
|
# 名称
|
||||||
name = Column(String, index=True, nullable=False)
|
name = Column(String, index=True, nullable=False)
|
||||||
# 描述
|
# 描述
|
||||||
|
|||||||
+28
-6
@@ -9,9 +9,31 @@ SUPERUSER=admin
|
|||||||
DEV=false
|
DEV=false
|
||||||
# 为指定字幕添加.default后缀设置为默认字幕,支持为'zh-cn','zh-tw','eng'添加默认字幕,未定义或设置为None则不添加
|
# 为指定字幕添加.default后缀设置为默认字幕,支持为'zh-cn','zh-tw','eng'添加默认字幕,未定义或设置为None则不添加
|
||||||
DEFAULT_SUB=zh-cn
|
DEFAULT_SUB=zh-cn
|
||||||
# 是否启用内存监控,开启后将定期生成内存快照文件
|
# 数据库类型,支持 sqlite 和 postgresql,默认使用 sqlite
|
||||||
MEMORY_ANALYSIS=false
|
DB_TYPE=sqlite
|
||||||
# 内存快照间隔(分钟)
|
# 是否在控制台输出 SQL 语句,默认关闭
|
||||||
MEMORY_SNAPSHOT_INTERVAL=30
|
DB_ECHO=False
|
||||||
# 保留的内存快照文件数量
|
# 是否在获取连接时进行预先 ping 操作
|
||||||
MEMORY_SNAPSHOT_KEEP_COUNT=20
|
DB_POOL_PRE_PING=True
|
||||||
|
# 数据库连接的回收时间(秒)
|
||||||
|
DB_POOL_RECYCLE=300
|
||||||
|
# 数据库连接池获取连接的超时时间(秒)
|
||||||
|
DB_POOL_TIMEOUT=30
|
||||||
|
# SQLite 的 busy_timeout 参数,默认为 60 秒
|
||||||
|
DB_TIMEOUT=60
|
||||||
|
# SQLite 是否启用 WAL 模式,默认开启
|
||||||
|
DB_WAL_ENABLE=True
|
||||||
|
# PostgreSQL 主机地址
|
||||||
|
DB_POSTGRESQL_HOST=localhost
|
||||||
|
# PostgreSQL 端口
|
||||||
|
DB_POSTGRESQL_PORT=5432
|
||||||
|
# PostgreSQL 数据库名
|
||||||
|
DB_POSTGRESQL_DATABASE=moviepilot
|
||||||
|
# PostgreSQL 用户名
|
||||||
|
DB_POSTGRESQL_USERNAME=moviepilot
|
||||||
|
# PostgreSQL 密码
|
||||||
|
DB_POSTGRESQL_PASSWORD=moviepilot
|
||||||
|
# PostgreSQL 连接池大小
|
||||||
|
DB_POSTGRESQL_POOL_SIZE=20
|
||||||
|
# PostgreSQL 连接池溢出数量
|
||||||
|
DB_POSTGRESQL_MAX_OVERFLOW=30
|
||||||
+35
-10
@@ -40,13 +40,25 @@ def run_migrations_offline() -> None:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
url = config.get_main_option("sqlalchemy.url")
|
url = config.get_main_option("sqlalchemy.url")
|
||||||
context.configure(
|
|
||||||
url=url,
|
# 根据数据库类型配置不同的参数
|
||||||
target_metadata=target_metadata,
|
if url and "postgresql" in url:
|
||||||
literal_binds=True,
|
# PostgreSQL配置
|
||||||
dialect_opts={"paramstyle": "named"},
|
context.configure(
|
||||||
render_as_batch=True
|
url=url,
|
||||||
)
|
target_metadata=target_metadata,
|
||||||
|
literal_binds=True,
|
||||||
|
dialect_opts={"paramstyle": "named"},
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# SQLite配置
|
||||||
|
context.configure(
|
||||||
|
url=url,
|
||||||
|
target_metadata=target_metadata,
|
||||||
|
literal_binds=True,
|
||||||
|
dialect_opts={"paramstyle": "named"},
|
||||||
|
render_as_batch=True
|
||||||
|
)
|
||||||
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
@@ -66,9 +78,22 @@ def run_migrations_online() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
with connectable.connect() as connection:
|
||||||
context.configure(
|
url = config.get_main_option("sqlalchemy.url")
|
||||||
connection=connection, target_metadata=target_metadata
|
|
||||||
)
|
# 根据数据库类型配置不同的参数
|
||||||
|
if url and "postgresql" in url:
|
||||||
|
# PostgreSQL配置
|
||||||
|
context.configure(
|
||||||
|
connection=connection,
|
||||||
|
target_metadata=target_metadata
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# SQLite配置
|
||||||
|
context.configure(
|
||||||
|
connection=connection,
|
||||||
|
target_metadata=target_metadata,
|
||||||
|
render_as_batch=True
|
||||||
|
)
|
||||||
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|||||||
+4
-1
@@ -28,6 +28,9 @@ RUN apt-get update -y \
|
|||||||
rsync \
|
rsync \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
nano \
|
nano \
|
||||||
|
postgresql-client \
|
||||||
|
postgresql \
|
||||||
|
postgresql-contrib \
|
||||||
&& dpkg-reconfigure --frontend noninteractive tzdata \
|
&& dpkg-reconfigure --frontend noninteractive tzdata \
|
||||||
&& \
|
&& \
|
||||||
if [ "$(uname -m)" = "x86_64" ]; \
|
if [ "$(uname -m)" = "x86_64" ]; \
|
||||||
@@ -84,6 +87,6 @@ RUN cp -f /app/docker/nginx.common.conf /etc/nginx/common.conf \
|
|||||||
&& curl -sL "https://github.com/jxxghp/MoviePilot-Resources/archive/refs/heads/main.zip" | busybox unzip -d /tmp - \
|
&& curl -sL "https://github.com/jxxghp/MoviePilot-Resources/archive/refs/heads/main.zip" | busybox unzip -d /tmp - \
|
||||||
&& mv -f /tmp/MoviePilot-Resources-main/resources.v2/* /app/app/helper/ \
|
&& mv -f /tmp/MoviePilot-Resources-main/resources.v2/* /app/app/helper/ \
|
||||||
&& rm -rf /tmp/*
|
&& rm -rf /tmp/*
|
||||||
EXPOSE 3000
|
EXPOSE 3000 5432
|
||||||
VOLUME [ "${CONFIG_DIR}" ]
|
VOLUME [ "${CONFIG_DIR}" ]
|
||||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||||
|
|||||||
@@ -43,6 +43,16 @@ function load_config_from_app_env() {
|
|||||||
["GITHUB_TOKEN"]=""
|
["GITHUB_TOKEN"]=""
|
||||||
["MOVIEPILOT_AUTO_UPDATE"]="release"
|
["MOVIEPILOT_AUTO_UPDATE"]="release"
|
||||||
|
|
||||||
|
# database
|
||||||
|
["DB_TYPE"]="sqlite"
|
||||||
|
["DB_POSTGRESQL_HOST"]="localhost"
|
||||||
|
["DB_POSTGRESQL_PORT"]="5432"
|
||||||
|
["DB_POSTGRESQL_DATABASE"]="moviepilot"
|
||||||
|
["DB_POSTGRESQL_USERNAME"]="moviepilot"
|
||||||
|
["DB_POSTGRESQL_PASSWORD"]="moviepilot"
|
||||||
|
["DB_POSTGRESQL_POOL_SIZE"]="20"
|
||||||
|
["DB_POSTGRESQL_MAX_OVERFLOW"]="30"
|
||||||
|
|
||||||
# cert
|
# cert
|
||||||
["ENABLE_SSL"]="false"
|
["ENABLE_SSL"]="false"
|
||||||
["SSL_DOMAIN"]=""
|
["SSL_DOMAIN"]=""
|
||||||
@@ -211,12 +221,70 @@ chown -R moviepilot:moviepilot \
|
|||||||
/var/lib/nginx \
|
/var/lib/nginx \
|
||||||
/var/log/nginx
|
/var/log/nginx
|
||||||
chown moviepilot:moviepilot /etc/hosts /tmp
|
chown moviepilot:moviepilot /etc/hosts /tmp
|
||||||
|
|
||||||
|
# 如果使用PostgreSQL,确保数据目录权限正确
|
||||||
|
if [ "${DB_TYPE:-sqlite}" = "postgresql" ]; then
|
||||||
|
POSTGRESQL_DATA_DIR="${CONFIG_DIR}/postgresql"
|
||||||
|
POSTGRESQL_LOG_DIR="${CONFIG_DIR}/postgresql/logs"
|
||||||
|
mkdir -p "${POSTGRESQL_DATA_DIR}" "${POSTGRESQL_LOG_DIR}"
|
||||||
|
chown -R postgres:postgres "${POSTGRESQL_DATA_DIR}" "${POSTGRESQL_LOG_DIR}"
|
||||||
|
fi
|
||||||
# 下载浏览器内核
|
# 下载浏览器内核
|
||||||
if [[ "$HTTPS_PROXY" =~ ^https?:// ]] || [[ "$HTTPS_PROXY" =~ ^https?:// ]] || [[ "$PROXY_HOST" =~ ^https?:// ]]; then
|
if [[ "$HTTPS_PROXY" =~ ^https?:// ]] || [[ "$HTTPS_PROXY" =~ ^https?:// ]] || [[ "$PROXY_HOST" =~ ^https?:// ]]; then
|
||||||
HTTPS_PROXY="${HTTPS_PROXY:-${https_proxy:-$PROXY_HOST}}" gosu moviepilot:moviepilot playwright install chromium
|
HTTPS_PROXY="${HTTPS_PROXY:-${https_proxy:-$PROXY_HOST}}" gosu moviepilot:moviepilot playwright install chromium
|
||||||
else
|
else
|
||||||
gosu moviepilot:moviepilot playwright install chromium
|
gosu moviepilot:moviepilot playwright install chromium
|
||||||
fi
|
fi
|
||||||
|
# 启动PostgreSQL服务
|
||||||
|
if [ "${DB_TYPE:-sqlite}" = "postgresql" ]; then
|
||||||
|
INFO "→ 启动PostgreSQL服务..."
|
||||||
|
|
||||||
|
# 使用配置目录下的postgresql子目录作为数据目录
|
||||||
|
POSTGRESQL_DATA_DIR="${CONFIG_DIR}/postgresql"
|
||||||
|
POSTGRESQL_LOG_DIR="${CONFIG_DIR}/postgresql/logs"
|
||||||
|
|
||||||
|
# 创建PostgreSQL数据目录和日志目录
|
||||||
|
mkdir -p "${POSTGRESQL_DATA_DIR}" "${POSTGRESQL_LOG_DIR}"
|
||||||
|
|
||||||
|
# 初始化PostgreSQL数据目录
|
||||||
|
if [ ! -f "${POSTGRESQL_DATA_DIR}/postgresql.conf" ]; then
|
||||||
|
INFO "初始化PostgreSQL数据目录..."
|
||||||
|
chown -R postgres:postgres "${POSTGRESQL_DATA_DIR}" "${POSTGRESQL_LOG_DIR}"
|
||||||
|
su - postgres -c "initdb -D '${POSTGRESQL_DATA_DIR}'"
|
||||||
|
|
||||||
|
# 配置PostgreSQL
|
||||||
|
echo "host all all 0.0.0.0/0 md5" >> "${POSTGRESQL_DATA_DIR}/pg_hba.conf"
|
||||||
|
echo "listen_addresses = '*'" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "port = ${DB_POSTGRESQL_PORT:-5432}" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "log_destination = 'stderr'" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "logging_collector = on" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "log_directory = '${POSTGRESQL_LOG_DIR}'" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "log_rotation_age = 1d" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
echo "log_rotation_size = 100MB" >> "${POSTGRESQL_DATA_DIR}/postgresql.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 确保目录权限正确
|
||||||
|
chown -R postgres:postgres "${POSTGRESQL_DATA_DIR}" "${POSTGRESQL_LOG_DIR}"
|
||||||
|
|
||||||
|
# 启动PostgreSQL服务
|
||||||
|
su - postgres -c "pg_ctl -D '${POSTGRESQL_DATA_DIR}' -l '${POSTGRESQL_LOG_DIR}/postgresql.log' start"
|
||||||
|
|
||||||
|
# 等待PostgreSQL启动
|
||||||
|
INFO "等待PostgreSQL服务启动..."
|
||||||
|
until su - postgres -c "pg_isready -h localhost -p ${DB_POSTGRESQL_PORT:-5432}"; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# 创建数据库和用户
|
||||||
|
INFO "创建PostgreSQL数据库和用户..."
|
||||||
|
su - postgres -c "psql -c \"CREATE USER ${DB_POSTGRESQL_USERNAME:-moviepilot} WITH PASSWORD '${DB_POSTGRESQL_PASSWORD:-moviepilot}';\" 2>/dev/null || true"
|
||||||
|
su - postgres -c "psql -c \"CREATE DATABASE ${DB_POSTGRESQL_DATABASE:-moviepilot} OWNER ${DB_POSTGRESQL_USERNAME:-moviepilot};\" 2>/dev/null || true"
|
||||||
|
su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE ${DB_POSTGRESQL_DATABASE:-moviepilot} TO ${DB_POSTGRESQL_USERNAME:-moviepilot};\" 2>/dev/null || true"
|
||||||
|
|
||||||
|
INFO "PostgreSQL服务启动完成,数据目录: ${POSTGRESQL_DATA_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
# 证书管理
|
# 证书管理
|
||||||
source /app/docker/cert.sh
|
source /app/docker/cert.sh
|
||||||
# 启动前端nginx服务
|
# 启动前端nginx服务
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ aiofiles~=24.1.0
|
|||||||
aiopathlib~=0.6.0
|
aiopathlib~=0.6.0
|
||||||
asynctempfile~=0.5.0
|
asynctempfile~=0.5.0
|
||||||
aiosqlite~=0.21.0
|
aiosqlite~=0.21.0
|
||||||
|
psycopg2-binary~=2.9.10
|
||||||
|
asyncpg~=0.30.0
|
||||||
jieba~=0.42.1
|
jieba~=0.42.1
|
||||||
rsa~=4.9
|
rsa~=4.9
|
||||||
redis~=6.2.0
|
redis~=6.2.0
|
||||||
|
|||||||
Reference in New Issue
Block a user