feat(backend): separate read and write operations in database

This commit is contained in:
zouxiaochuan 2023-11-14 14:02:56 +08:00
parent 14520165b2
commit 461ff49255
5 changed files with 26 additions and 17 deletions

View File

@ -79,6 +79,7 @@ _DEFAULT_CONFIG = {
# Database config # Database config
"database": { "database": {
"type": "sqlalchemy", "type": "sqlalchemy",
"url_read": f"sqlite:///{SQLITE_PATH}",
"url": f"sqlite:///{SQLITE_PATH}", "url": f"sqlite:///{SQLITE_PATH}",
}, },
# Engine config # Engine config

View File

@ -19,5 +19,5 @@ class Database:
): ):
raise NotImplementedError("'install' Method NOT Implemented.") raise NotImplementedError("'install' Method NOT Implemented.")
def execute(self, sql, params=None): def execute(self, sql, params=None, read_only=False):
raise NotImplementedError("'query' Method NOT Implemented.") raise NotImplementedError("'query' Method NOT Implemented.")

View File

@ -212,6 +212,9 @@ class SQLAlchemy(Database):
def __init__(self, config, admin_password): def __init__(self, config, admin_password):
self.url = config["url"] self.url = config["url"]
self.url_read = config["url_read"]
self.engine = None
self.engine_read = None
self.install(admin_password) self.install(admin_password)
pass pass
@ -224,6 +227,7 @@ class SQLAlchemy(Database):
helper.create_database(self.url) helper.create_database(self.url)
self.engine = create_engine(self.url, future=True) self.engine = create_engine(self.url, future=True)
self.engine_read = create_engine(self.url_read, future=True)
# create all tables # create all tables
DeclarativeBase.metadata.create_all(self.engine) DeclarativeBase.metadata.create_all(self.engine)
@ -235,11 +239,16 @@ class SQLAlchemy(Database):
else: else:
self.engine = create_engine(self.url, future=True) self.engine = create_engine(self.url, future=True)
self.engine_read = create_engine(self.url_read, future=True)
pass pass
def execute(self, sql, params=None, conn=None): def execute(self, sql, params=None, conn=None, read_only=False):
if conn is None: if conn is None:
conn_ = self.engine.connect() if read_only:
conn_ = self.engine_read.connect()
else:
conn_ = self.engine.connect()
pass
pass pass
else: else:
conn_ = conn conn_ = conn

View File

@ -43,7 +43,7 @@ def check_user_exist_exclude(by, value, exclude, conn):
def get_user_info(by, value): def get_user_info(by, value):
rows = context.database.execute(f"SELECT * FROM tb_user WHERE {by} = :{by}", {by: value}) rows = context.database.execute(f"SELECT * FROM tb_user WHERE {by} = :{by}", {by: value}, read_only=True)
if len(rows) == 0: if len(rows) == 0:
return None return None
else: else:
@ -242,7 +242,7 @@ def get_learnware_list(by, value, limit=None, page=None, is_verified=None):
def get_learnware_list_by_user_id(user_id, limit, page): def get_learnware_list_by_user_id(user_id, limit, page):
cnt = context.database.execute( cnt = context.database.execute(
"SELECT COUNT(1) FROM tb_user_learnware_relation WHERE user_id = :user_id", {"user_id": user_id} "SELECT COUNT(1) FROM tb_user_learnware_relation WHERE user_id = :user_id", {"user_id": user_id}, read_only=True
)[0][0] )[0][0]
query = """ query = """
@ -287,6 +287,7 @@ def get_verify_log(user_id, learnware_id):
rows = context.database.execute( rows = context.database.execute(
sql, sql,
{"user_id": user_id, "learnware_id": learnware_id}, {"user_id": user_id, "learnware_id": learnware_id},
read_only=True,
) )
if len(rows) == 0: if len(rows) == 0:
@ -328,7 +329,8 @@ def get_learnware_owners(learnware_ids):
" JOIN tb_user_learnware_relation tb2 ON tb1.id=tb2.user_id WHERE learnware_id in {0}".format( " JOIN tb_user_learnware_relation tb2 ON tb1.id=tb2.user_id WHERE learnware_id in {0}".format(
"(" + ",".join(["'" + learnware_id + "'" for learnware_id in learnware_ids]) + ")" "(" + ",".join(["'" + learnware_id + "'" for learnware_id in learnware_ids]) + ")"
) )
) ),
read_only=True,
) )
rmap = {r[0]: r[1] for r in rows} rmap = {r[0]: r[1] for r in rows}
@ -457,6 +459,7 @@ def get_learnware_timestamps(learnware_ids):
"(" + ",".join(["'" + learnware_id + "'" for learnware_id in learnware_ids]) + ")" "(" + ",".join(["'" + learnware_id + "'" for learnware_id in learnware_ids]) + ")"
), ),
# {"learnware_ids": learnware_ids}, # {"learnware_ids": learnware_ids},
read_only=True,
) )
result = {r[0]: r[1] for r in result} result = {r[0]: r[1] for r in result}
@ -506,6 +509,7 @@ def get_learnware_verify_status(learnware_id):
result = context.database.execute( result = context.database.execute(
"SELECT verify_status FROM tb_user_learnware_relation WHERE learnware_id = :learnware_id", "SELECT verify_status FROM tb_user_learnware_relation WHERE learnware_id = :learnware_id",
{"learnware_id": learnware_id}, {"learnware_id": learnware_id},
read_only=True,
) )
if len(result) == 0: if len(result) == 0:
raise RuntimeError(f"learnware_id {learnware_id} not found") raise RuntimeError(f"learnware_id {learnware_id} not found")
@ -521,7 +525,9 @@ def create_user_token(user_id, token):
def get_user_tokens(user_id) -> List[str]: def get_user_tokens(user_id) -> List[str]:
result = context.database.execute("SELECT token FROM tb_user_token WHERE user_id = :user_id", {"user_id": user_id}) result = context.database.execute(
"SELECT token FROM tb_user_token WHERE user_id = :user_id", {"user_id": user_id}, read_only=True
)
if len(result) == 0: if len(result) == 0:
return [] return []
@ -598,7 +604,9 @@ def get_learnware_count_queued_or_processing():
def check_user_admin(user_id): def check_user_admin(user_id):
result = context.database.execute("SELECT role FROM tb_user WHERE id = :user_id", {"user_id": user_id}) result = context.database.execute(
"SELECT role FROM tb_user WHERE id = :user_id", {"user_id": user_id}, read_only=True
)
if len(result) == 0: if len(result) == 0:
return False return False

View File

@ -100,15 +100,6 @@ class SearchLearnware(flask_restful.Resource):
pass pass
print(msg) print(msg)
try:
print("=" * 60)
if ret not in [None, False]:
lis = ret[1]
for x in lis:
print(x.get_specification().get_semantic_spec()["Name"]["Values"])
print("=" * 60)
except Exception as err:
print(err)
if not status: if not status:
return {"code": 41, "msg": msg}, 200 return {"code": 41, "msg": msg}, 200