139 lines
3.8 KiB
Python
139 lines
3.8 KiB
Python
# tasks/listed_tasks.py
|
|
|
|
import threading
|
|
import queue
|
|
from database.db import get_connection
|
|
from services.core.log_service import log_service
|
|
from gui.global_signals import global_signals
|
|
|
|
stop_event = threading.Event()
|
|
dialog_semaphore = None # sẽ khởi tạo dựa trên setting
|
|
|
|
|
|
def stop_listed_task():
|
|
"""Dừng toàn bộ task"""
|
|
stop_event.set()
|
|
log_service.info("[Task] Stop signal sent")
|
|
|
|
|
|
def get_settings():
|
|
"""Lấy setting từ DB"""
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("SELECT key, value FROM settings")
|
|
rows = cursor.fetchall()
|
|
conn.close()
|
|
return {row["key"]: row["value"] for row in rows}
|
|
|
|
|
|
def get_pending_items(limit=1000):
|
|
"""Lấy danh sách pending listed items"""
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute(f"""
|
|
SELECT l.id, l.account_id, l.product_id, l.listed_at, l.status
|
|
FROM listed l
|
|
JOIN accounts a ON l.account_id = a.id
|
|
WHERE l.status='pending'
|
|
AND a.is_active=1
|
|
ORDER BY l.listed_at ASC
|
|
LIMIT {limit}
|
|
""")
|
|
rows = cursor.fetchall()
|
|
conn.close()
|
|
return rows
|
|
|
|
|
|
def process_item(row):
|
|
"""Xử lý 1 item: mở dialog trên main thread và update DB"""
|
|
listed_id, account_id, product_id, listed_at, status = row
|
|
log_service.info(f"[Task] Processing listed_id={listed_id}")
|
|
|
|
if stop_event.is_set():
|
|
log_service.info("[Task] Stop signal received, skip item")
|
|
return
|
|
|
|
# --- Đợi semaphore để giới hạn số dialog ---
|
|
dialog_semaphore.acquire()
|
|
|
|
# --- Tạo event để chờ dialog xong ---
|
|
finished_event = threading.Event()
|
|
|
|
# Callback khi dialog xong
|
|
def on_dialog_finished(finished_account_id):
|
|
if finished_account_id == account_id:
|
|
finished_event.set()
|
|
global_signals.dialog_finished.disconnect(on_dialog_finished)
|
|
dialog_semaphore.release()
|
|
|
|
global_signals.dialog_finished.connect(on_dialog_finished)
|
|
|
|
# --- Emit signal mở dialog trên main thread ---
|
|
global_signals.open_login_dialog.emit(account_id)
|
|
|
|
# --- Chờ dialog hoàn tất ---
|
|
finished_event.wait()
|
|
|
|
# --- Update DB ---
|
|
conn = get_connection()
|
|
cursor = conn.cursor()
|
|
cursor.execute("UPDATE listed SET status='listed' WHERE id=?", (listed_id,))
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
log_service.info(f"[Task] Finished listed_id={listed_id}")
|
|
|
|
|
|
def worker_thread(q: queue.Queue):
|
|
while not stop_event.is_set():
|
|
try:
|
|
row = q.get(timeout=1)
|
|
except queue.Empty:
|
|
break
|
|
try:
|
|
process_item(row)
|
|
except Exception as e:
|
|
log_service.error(f"[Task] Exception in worker: {e}")
|
|
finally:
|
|
q.task_done()
|
|
|
|
|
|
def process_all_listed():
|
|
"""
|
|
Entry point: tạo queue và 2 worker thread (hoặc theo setting)
|
|
"""
|
|
log_service.info("[Task] Start processing all listed items")
|
|
|
|
settings = get_settings()
|
|
max_workers = int(settings.get("MAX_CONCURRENT_LISTING", 2))
|
|
global dialog_semaphore
|
|
dialog_semaphore = threading.Semaphore(max_workers)
|
|
|
|
# --- Lấy pending items ---
|
|
items = get_pending_items(limit=1000)
|
|
if not items:
|
|
log_service.info("[Task] No pending items")
|
|
global_signals.listed_finished.emit()
|
|
return
|
|
|
|
# --- Tạo queue ---
|
|
q = queue.Queue()
|
|
for row in items:
|
|
q.put(row)
|
|
|
|
# --- Tạo worker threads ---
|
|
threads = []
|
|
for _ in range(max_workers):
|
|
t = threading.Thread(target=worker_thread, args=(q,))
|
|
t.start()
|
|
threads.append(t)
|
|
|
|
# --- Chờ queue xong ---
|
|
q.join()
|
|
stop_event.set()
|
|
for t in threads:
|
|
t.join()
|
|
|
|
log_service.info("[Task] All listed items processed")
|
|
global_signals.listed_finished.emit()
|