Added scheduler logic

This commit is contained in:
David Maisonave
2024-08-07 22:05:03 -04:00
parent 5d7d4bc80d
commit 3d7aa6333c
4 changed files with 69 additions and 16 deletions

View File

@@ -1,4 +1,4 @@
# FileMonitor: Ver 0.6.0 (By David Maisonave)
# FileMonitor: Ver 0.6.1 (By David Maisonave)
FileMonitor is a [Stash](https://github.com/stashapp/stash) plugin which updates Stash if any changes occurs in the Stash library paths.
### Using FileMonitor as a plugin
@@ -24,6 +24,7 @@ FileMonitor is a [Stash](https://github.com/stashapp/stash) plugin which updates
- `pip install stashapp-tools --upgrade`
- `pip install pyYAML`
- `pip install watchdog`
- `pip install schedule`
### Installation
- Follow **Requirements** instructions.

View File

@@ -3,13 +3,10 @@
# Get the latest developers version from following link: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/FileMonitor
# Note: To call this script outside of Stash, pass --url and the Stash URL.
# Example: python filemonitor.py --url http://localhost:9999
import os
import time
import pathlib
import argparse
import os, time, pathlib, argparse
from StashPluginHelper import StashPluginHelper
from watchdog.observers import Observer # This is also needed for event attributes
import watchdog # pip install watchdog # https://pythonhosted.org/watchdog/
from watchdog.observers import Observer # This is also needed for event attributes
from threading import Lock, Condition
from multiprocessing import shared_memory
from filemonitor_config import config # Import settings from filemonitor_config.py
@@ -72,20 +69,51 @@ STASHPATHSCONFIG = plugin.STASH_CONFIGURATION['stashes']
stashPaths = []
for item in STASHPATHSCONFIG:
stashPaths.append(item["path"])
stashPaths.append(SPECIAL_FILE_DIR)
plugin.Trace(f"(stashPaths={stashPaths})")
if plugin.DRY_RUN:
plugin.Log("Dry run mode is enabled.")
plugin.Trace(f"(SCAN_MODIFIED={SCAN_MODIFIED}) (SCAN_ON_ANY_EVENT={SCAN_ON_ANY_EVENT}) (RECURSIVE={RECURSIVE})")
# ToDo: Add logic here for reoccurring scheduler
def runTask(task):
if task['task'] == "Clean":
plugin.STASH_INTERFACE.metadata_clean(paths=stashPaths, dry_run=plugin.DRY_RUN)
elif task['task'] == "Generate":
plugin.STASH_INTERFACE.metadata_generate()
elif task['task'] == "Backup":
plugin.STASH_INTERFACE.call_GQL("mutation { backupDatabase(input: {download: false})}")
elif task['task'] == "Scan":
plugin.STASH_INTERFACE.metadata_scan(paths=stashPaths)
# elif task['task'] == "Create Tags":
# plugin.STASH_INTERFACE.run_plugin_task(plugin_id="pathParser", task_name="Create Tags")
elif task['task'] == "Auto Tag":
plugin.Warn("Auto Tag is not implemented!!!")
else:
plugin.STASH_INTERFACE.run_plugin_task(plugin_id=task['pluginId'], task_name=task['task'])
def reoccurringScheduler():
import schedule # pip install schedule # https://github.com/dbader/schedule
for task in plugin.pluginConfig['task_reoccurring_scheduler']:
if task['hours'] > 0:
plugin.Log(f"Adding to reoccurring scheduler task '{task['task']}' at {task['hours']} hour(s) interval")
schedule.every(task['hours']).hours.do(runTask, task)
if plugin.pluginConfig['turnOnScheduler']:
reoccurringScheduler()
FileMonitorPluginIsOnTaskQue = plugin.CALLED_AS_STASH_PLUGIN
StopLibraryMonitorWaitingInTaskQueue = False
JobIdInTheQue = 0
def isJobWaitingToRun():
global StopLibraryMonitorWaitingInTaskQueue
global JobIdInTheQue
global FileMonitorPluginIsOnTaskQue
FileMonitorPluginIsOnTaskQue = False
jobIsWaiting = False
i = 1
while i < 999:
while True:
jobDetails = plugin.STASH_INTERFACE.find_job(i)
if jobDetails:
plugin.Trace(f"(Job ID({i})={jobDetails})")
@@ -93,13 +121,15 @@ def isJobWaitingToRun():
if jobDetails['description'] == "Running plugin task: Stop Library Monitor":
StopLibraryMonitorWaitingInTaskQueue = True
JobIdInTheQue = i
return True
jobIsWaiting = True
elif jobDetails['status'] == "RUNNING" and jobDetails['description'] == "Running plugin task: Start Library Monitor":
FileMonitorPluginIsOnTaskQue = True
else:
plugin.Trace(f"Last job {i}")
break
i += 1
JobIdInTheQue = 0
return False
return jobIsWaiting
if plugin.CALLED_AS_STASH_PLUGIN:
plugin.Trace(f"isJobWaitingToRun() = {isJobWaitingToRun()})")
@@ -188,6 +218,7 @@ def start_library_monitor():
for path in stashPaths:
observer.schedule(event_handler, path, recursive=RECURSIVE)
plugin.Trace(f"Observing {path}")
observer.schedule(event_handler, SPECIAL_FILE_DIR, recursive=RECURSIVE)
observer.start()
JobIsRunning = False
PutPluginBackOnTaskQueAndExit = False
@@ -198,9 +229,12 @@ def start_library_monitor():
with mutex:
while not shouldUpdate:
if plugin.CALLED_AS_STASH_PLUGIN and isJobWaitingToRun():
if FileMonitorPluginIsOnTaskQue:
plugin.Log(f"Another task (JobID={JobIdInTheQue}) is waiting on the queue. Will restart FileMonitor to allow other task to run.")
JobIsRunning = True
break
else:
plugin.Warn("Not restarting because FileMonitor is no longer on Task Queue")
if shm_buffer[0] != CONTINUE_RUNNING_SIG:
plugin.Log(f"Breaking out of loop. (shm_buffer[0]={shm_buffer[0]})")
break
@@ -229,7 +263,7 @@ def start_library_monitor():
plugin.STASH_INTERFACE.metadata_clean(paths=TmpTargetPaths, dry_run=plugin.DRY_RUN)
if RUN_GENERATE_CONTENT:
plugin.STASH_INTERFACE.metadata_generate()
if plugin.CALLED_AS_STASH_PLUGIN and shm_buffer[0] == CONTINUE_RUNNING_SIG:
if plugin.CALLED_AS_STASH_PLUGIN and shm_buffer[0] == CONTINUE_RUNNING_SIG and FileMonitorPluginIsOnTaskQue:
PutPluginBackOnTaskQueAndExit = True
else:
plugin.Trace("Nothing to scan.")

View File

@@ -1,6 +1,6 @@
name: FileMonitor
description: Monitors the Stash library folders, and updates Stash if any changes occurs in the Stash library paths.
version: 0.6.0
version: 0.6.1
url: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/FileMonitor
settings:
recursiveDisabled:

View File

@@ -9,7 +9,7 @@ config = {
# Enable to monitor changes in file system for modification flag. This option is NOT needed for Windows, because on Windows changes are triggered via CREATE, DELETE, and MOVE flags. Other OS may differ.
"scanModified": False,
# Timeout in seconds. This is how often it will check if another job (Task) is in the queue.
"timeOut": 60, # Not needed when running in command line mode.
"timeOut": 15, # Not needed when running in command line mode.
# Enable to exit FileMonitor by creating special file in plugin folder\working
"createSpecFileToExit": True,
# Enable to delete special file imediately after it's created in stop process
@@ -17,6 +17,24 @@ config = {
# Enable to run metadata clean task after file deletion.
"runCleanAfterDelete": False,
# Enable to turn on scheduler_task_list
"turnOnScheduler": True,
# Reoccurring scheduler task list. To activate schedule, change number from zero to the number of hours interval
"task_reoccurring_scheduler": [
# Example: To perform a 'Clean' task every 48 hours, change zero to 48
# Hours Conversion: 24=Daily, 168=Weekly, 720=Monthly, 1440=Bi-Monthly, 2160=Quarterly, 8760=Yearly
{"task" : "Clean", "hours" : 48}, # Maintenance Clean (every 2 days)
{"task" : "Generate", "hours" : 168}, # Generated Content (Weekly)
{"task" : "Backup", "hours" : 720}, # Backup Backup (Monthly)
{"task" : "Scan", "hours" : 168}, # Library Scan (Weekly)
# {"task" : "Create Tags", "hours" : 24},# Requires plugin [Path Parser]
{"task" : "Create Tags", "pluginId" : "pathParser", "hours" : 24}, # Requires plugin [Path Parser]
{"task" : "Auto Tag", "hours" : 0}, # !!! Not yet implemented!!!
{"task" : "MyTaskHere", "pluginId" : "MyPluginId", "hours" : 0}, # Place holder for custom task.
],
# Maximum backups to keep. When scheduler is enabled, and the Backup runs, delete older backups after reaching maximum backups.
"BackupsMax" : 6, # Not yet implemented!!!
# When enabled, if CREATE flag is triggered, DupFileManager task is called if the plugin is installed.
"onCreateCallDupFileManager": False, # Not yet implemented!!!!