debug_log: таблица + логи на каждом шаге _chunk_upload, v1.19
This commit is contained in:
+30
-8
@@ -17,6 +17,15 @@ from api import api_bp
|
||||
|
||||
load_dotenv()
|
||||
|
||||
import time as _time
|
||||
|
||||
def _log(step, detail=""):
|
||||
"""Писать отладочный лог в таблицу debug_log."""
|
||||
try:
|
||||
db.execute("INSERT INTO debug_log (step, detail) VALUES (%s,%s)", (step, str(detail)[:500]))
|
||||
except:
|
||||
pass # не мешать основному потоку
|
||||
|
||||
|
||||
def _save_file_to_db(filename, file_bytes, mime, contract_id, conn=None):
|
||||
"""Сохранить файл в БД. Если conn передан — использовать его, иначе свои подключения."""
|
||||
@@ -136,35 +145,42 @@ class ContractsApp:
|
||||
chunk_data = chunk_file.read()
|
||||
mime = mimeutil.guess_mime(filename) or "application/octet-stream"
|
||||
|
||||
_log("chunk_start", f"{filename} idx={chunk_index}/{total_chunks} size={len(chunk_data)} cid={cid}")
|
||||
|
||||
# Сохранить чанк в БД (ON CONFLICT — идемпотентно)
|
||||
db.execute(
|
||||
rc, err = db.execute(
|
||||
"INSERT INTO chunks (upload_id, chunk_index, chunk_data, filename, mime, total_chunks, cid) "
|
||||
"VALUES (%s,%s,%s,%s,%s,%s,%s) ON CONFLICT (upload_id, chunk_index) DO NOTHING",
|
||||
(upload_id, chunk_index, chunk_data, filename, mime, total_chunks, cid),
|
||||
)
|
||||
_log("chunk_insert", f"idx={chunk_index} rc={rc} err={err}")
|
||||
|
||||
# Сколько уже получено
|
||||
count_res, _ = db.query(
|
||||
count_res, cerr = db.query(
|
||||
"SELECT COUNT(*) FROM chunks WHERE upload_id=%s", (upload_id,)
|
||||
)
|
||||
received = count_res["rows"][0][0] if count_res else 0
|
||||
_log("chunk_count", f"received={received}/{total_chunks} err={cerr}")
|
||||
|
||||
if received == total_chunks:
|
||||
_log("assembly_start", f"{filename} {total_chunks} chunks, {sum(len(c) if c else 0 for c in [chunk_data])}b this chunk")
|
||||
try:
|
||||
# ОДНО соединение на всю сборку + сохранение
|
||||
conn, err = db.connect()
|
||||
_log("assembly_connect", f"err={err}")
|
||||
if err:
|
||||
return jsonify({"error": f"БД: {err}"}), 500
|
||||
cur = conn.cursor()
|
||||
|
||||
# Собрать все чанки по порядку
|
||||
cur.execute(
|
||||
"SELECT chunk_data FROM chunks WHERE upload_id=%s ORDER BY chunk_index",
|
||||
(upload_id,),
|
||||
)
|
||||
file_bytes = b"".join(r[0] for r in cur.fetchall())
|
||||
all_chunks = cur.fetchall()
|
||||
_log("assembly_select", f"{len(all_chunks)} rows")
|
||||
|
||||
file_bytes = b"".join(r[0] for r in all_chunks)
|
||||
_log("assembly_joined", f"{len(file_bytes)} bytes")
|
||||
|
||||
# Метаданные
|
||||
cur.execute(
|
||||
"SELECT filename, mime, cid FROM chunks WHERE upload_id=%s LIMIT 1",
|
||||
(upload_id,),
|
||||
@@ -173,8 +189,8 @@ class ContractsApp:
|
||||
fname = meta[0] if meta else filename
|
||||
fmime = meta[1] if meta else mime
|
||||
fcid = meta[2] if meta else cid
|
||||
_log("assembly_meta", f"fname={fname} mime={fmime} cid={fcid}")
|
||||
|
||||
# Контракт если нет
|
||||
if fcid:
|
||||
contract_id = fcid
|
||||
else:
|
||||
@@ -183,11 +199,13 @@ class ContractsApp:
|
||||
("б/н " + __import__("datetime").datetime.now().strftime("%Y%m%d-%H%M"), ""),
|
||||
)
|
||||
contract_id = cur.fetchone()[0]
|
||||
_log("assembly_contract", f"new cid={contract_id}")
|
||||
|
||||
conn.commit()
|
||||
_log("assembly_commit", "ok")
|
||||
|
||||
# Сохранить файл через то же соединение
|
||||
doc_id = _save_file_to_db(fname, file_bytes, fmime, str(contract_id), conn=conn)
|
||||
_log("save_file", f"doc_id={doc_id}")
|
||||
if not doc_id:
|
||||
conn.rollback()
|
||||
cur.close()
|
||||
@@ -196,7 +214,9 @@ class ContractsApp:
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
_log("assembly_done", f"cid={contract_id}")
|
||||
except Exception as e:
|
||||
_log("assembly_error", str(e))
|
||||
try: conn.rollback()
|
||||
except: pass
|
||||
try: cur.close()
|
||||
@@ -206,9 +226,11 @@ class ContractsApp:
|
||||
return jsonify({"error": f"Сборка: {e}"}), 500
|
||||
finally:
|
||||
db.execute("DELETE FROM chunks WHERE upload_id=%s", (upload_id,))
|
||||
_log("chunks_cleanup", f"upload_id={upload_id}")
|
||||
|
||||
return jsonify({"contract_id": str(contract_id)})
|
||||
|
||||
_log("chunk_ok", f"idx={chunk_index} received={received}/{total_chunks}")
|
||||
return jsonify({"chunk": chunk_index, "received": received, "total": total_chunks})
|
||||
|
||||
def _show_contract(self, cid):
|
||||
|
||||
Reference in New Issue
Block a user