Use static callable for FreeGame scheduler

This commit is contained in:
2026-05-28 18:00:39 +09:00
parent d7066b3489
commit fdd0ca8ead
+41 -36
View File
@@ -5,7 +5,7 @@ import traceback
import requests import requests
from flask import jsonify, render_template from flask import jsonify, render_template
from plugin import PluginModuleBase from plugin import PluginModuleBase
from framework import F, Job from framework import F, Job, scheduler
from .model import ModelFetchLog, ModelFreeGameItem, ModelSetting from .model import ModelFetchLog, ModelFreeGameItem, ModelSetting
from . import scraper from . import scraper
@@ -137,20 +137,20 @@ class Logic(PluginModuleBase):
if sub == "setting_save": if sub == "setting_save":
ret, _ = ModelSetting.setting_save(req) ret, _ = ModelSetting.setting_save(req)
if F.scheduler.is_include(package_name): if F.scheduler.is_include(package_name):
self.scheduler_stop() Logic.scheduler_stop()
self.scheduler_start() Logic.scheduler_start()
elif _truthy(ModelSetting.get("auto_start")): elif _truthy(ModelSetting.get("auto_start")):
self.scheduler_start() Logic.scheduler_start()
ret["ret"] = "success" ret["ret"] = "success"
return jsonify(ret) return jsonify(ret)
if sub == "scheduler_toggle": if sub == "scheduler_toggle":
if req.form["scheduler"] == "true": if req.form["scheduler"] == "true":
self.scheduler_start() Logic.scheduler_start()
else: else:
self.scheduler_stop() Logic.scheduler_stop()
return jsonify({"ret": "success"}) return jsonify({"ret": "success"})
if sub == "execute_once": if sub == "execute_once":
threading.Thread(target=self.scheduler_function, daemon=True).start() threading.Thread(target=Logic.scheduler_function, daemon=True).start()
return jsonify({"ret": "success"}) return jsonify({"ret": "success"})
if sub == "web_list": if sub == "web_list":
ModelFreeGameItem.ensure_schema() ModelFreeGameItem.ensure_schema()
@@ -163,55 +163,59 @@ class Logic(PluginModuleBase):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
return jsonify({"ret": "error", "log": str(e)}) return jsonify({"ret": "error", "log": str(e)})
def scheduler_start(self): @staticmethod
def scheduler_start():
try: try:
interval = ModelSetting.get("auto_interval") or "0 */2 * * *" interval = ModelSetting.get("auto_interval") or "0 */2 * * *"
if F.scheduler.is_include(package_name): if F.scheduler.is_include(package_name):
F.scheduler.remove_job(package_name) scheduler.remove_job(package_name)
job = Job(package_name, package_name, interval, self.scheduler_function, "FreeGame fetch", True) job = Job(package_name, package_name, interval, Logic.scheduler_function, "FreeGame fetch", True)
F.scheduler.add_job_instance(job) scheduler.add_job_instance(job)
logger.info("FreeGame scheduler registered: %s", interval) logger.info("FreeGame scheduler registered: %s", interval)
except Exception as e: except Exception as e:
logger.error("Exception:%s", e) logger.error("Exception:%s", e)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
def scheduler_stop(self): @staticmethod
def scheduler_stop():
try: try:
F.scheduler.remove_job(package_name) scheduler.remove_job(package_name)
except Exception as e: except Exception as e:
logger.error("Exception:%s", e) logger.error("Exception:%s", e)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
def scheduler_function(self): @staticmethod
def scheduler_function():
if not _fetch_lock.acquire(blocking=False): if not _fetch_lock.acquire(blocking=False):
logger.info("FreeGame fetch skipped: already running") logger.info("FreeGame fetch skipped: already running")
return return
try: try:
logger.info("FreeGame scheduled fetch started") with F.app.app_context():
ModelFreeGameItem.ensure_schema() logger.info("FreeGame scheduled fetch started")
enabled_sources = set(_enabled_sources()) ModelFreeGameItem.ensure_schema()
results = scraper.fetch_all() enabled_sources = set(_enabled_sources())
grouped = _split_source_payload(results) results = scraper.fetch_all()
fresh_free_games = [] grouped = _split_source_payload(results)
fresh_free_games = []
for legacy_source in ["humble", "fanatical", "gmg", "directgames"]: for legacy_source in ["humble", "fanatical", "gmg", "directgames"]:
ModelFreeGameItem.replace_source_items(legacy_source, []) ModelFreeGameItem.replace_source_items(legacy_source, [])
for source, items in grouped.items(): for source, items in grouped.items():
if source not in enabled_sources: if source not in enabled_sources:
continue continue
ModelFreeGameItem.replace_source_items(source, items) ModelFreeGameItem.replace_source_items(source, items)
ModelFetchLog(source, "ok", "", len(items)).save() ModelFetchLog(source, "ok", "", len(items)).save()
logger.info("FreeGame source=%s saved=%d", source, len(items)) logger.info("FreeGame source=%s saved=%d", source, len(items))
fresh_free_games.extend(items) fresh_free_games.extend(items)
disabled_sources = [source for source in SOURCE_LABELS if source not in enabled_sources] disabled_sources = [source for source in SOURCE_LABELS if source not in enabled_sources]
if disabled_sources: if disabled_sources:
ModelFreeGameItem.delete_not_in_sources(enabled_sources) ModelFreeGameItem.delete_not_in_sources(enabled_sources)
logger.info("FreeGame fetch completed: free_candidates=%d enabled_sources=%d", len(fresh_free_games), len(enabled_sources)) logger.info("FreeGame fetch completed: free_candidates=%d enabled_sources=%d", len(fresh_free_games), len(enabled_sources))
ModelFetchLog("all", "ok", f"free_candidates={len(fresh_free_games)} enabled_sources={len(enabled_sources)}", len(fresh_free_games)).save() ModelFetchLog("all", "ok", f"free_candidates={len(fresh_free_games)} enabled_sources={len(enabled_sources)}", len(fresh_free_games)).save()
self._notify(fresh_free_games) Logic._notify(fresh_free_games)
except Exception as e: except Exception as e:
logger.error("Exception:%s", e) logger.error("Exception:%s", e)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
@@ -219,7 +223,8 @@ class Logic(PluginModuleBase):
finally: finally:
_fetch_lock.release() _fetch_lock.release()
def _notify(self, games): @staticmethod
def _notify(games):
if _truthy(ModelSetting.get("notify_enabled")) is False: if _truthy(ModelSetting.get("notify_enabled")) is False:
return return
targets = list(games or []) targets = list(games or [])