change how we calculate active jobs, probably will remove it from pa_job_engine, safer with threads I think. But, mostyle, added in client / server socket comms between web FE and job manager, with better job creation message (including link to job detail) and when you view job detail it auto-refreshes every few seconds until job complete)
This commit is contained in:
4
files.py
4
files.py
@@ -61,7 +61,7 @@ def files():
|
|||||||
def scannow():
|
def scannow():
|
||||||
job=NewJob("scannow" )
|
job=NewJob("scannow" )
|
||||||
st.SetAlert("success")
|
st.SetAlert("success")
|
||||||
st.SetMessage("Created job to scan for new files")
|
st.SetMessage("scanning for new files in: <a href=/job/{}>Job #{}</a> (Click the link to follow progress)".format( job.id, job.id) )
|
||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@@ -71,7 +71,7 @@ def scannow():
|
|||||||
def forcescan():
|
def forcescan():
|
||||||
job=NewJob("forcescan" )
|
job=NewJob("forcescan" )
|
||||||
st.SetAlert("success")
|
st.SetAlert("success")
|
||||||
st.SetMessage("Created job to force scan & rebuild data for files")
|
st.SetMessage("force scan & rebuild data for files in: <a href=/job/{}>Job #{}</a> (Click the link to follow progress)".format( job.id, job.id) )
|
||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|||||||
18
job.py
18
job.py
@@ -7,6 +7,8 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||||||
from status import st, Status
|
from status import st, Status
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import pytz
|
import pytz
|
||||||
|
import socket
|
||||||
|
from shared import PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT
|
||||||
|
|
||||||
class Joblog(db.Model):
|
class Joblog(db.Model):
|
||||||
id = db.Column(db.Integer, db.Sequence('ill_id_seq'), primary_key=True )
|
id = db.Column(db.Integer, db.Sequence('ill_id_seq'), primary_key=True )
|
||||||
@@ -42,9 +44,8 @@ class Job(db.Model):
|
|||||||
# Utility classes for Jobs
|
# Utility classes for Jobs
|
||||||
################################################################################
|
################################################################################
|
||||||
def GetNumActiveJobs():
|
def GetNumActiveJobs():
|
||||||
ret = db.engine.execute("select num_active_jobs from pa_job_manager").first();
|
ret = db.engine.execute("select count(1) from job where pa_job_state != 'Completed'").first()
|
||||||
if( ret != None ):
|
return ret.count
|
||||||
return ret.num_active_jobs
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# NewJob takes a name (which will be matched in pa_job_manager.py to run
|
# NewJob takes a name (which will be matched in pa_job_manager.py to run
|
||||||
@@ -57,6 +58,17 @@ def NewJob(name, num_passes="1", num_files="0", wait_for=None ):
|
|||||||
db.session.add(job)
|
db.session.add(job)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("Waking up PA Job Manager")
|
||||||
|
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT))
|
||||||
|
s.sendall(b'Hello, world')
|
||||||
|
s.close()
|
||||||
|
except Exception as e:
|
||||||
|
st.SetAlert("danger")
|
||||||
|
st.SetMessage("Failed to connect to job manager, has it crashed? Exception was:{}".format(e))
|
||||||
|
return job
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# /jobs -> show current settings
|
# /jobs -> show current settings
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from sqlalchemy import Column, Integer, String, Sequence, Float, ForeignKey, Dat
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from shared import DB_URL
|
from shared import DB_URL, PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import pytz
|
import pytz
|
||||||
import time
|
import time
|
||||||
@@ -29,6 +29,8 @@ import exifread
|
|||||||
import base64
|
import base64
|
||||||
import numpy
|
import numpy
|
||||||
import cv2
|
import cv2
|
||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
|
||||||
# an Manager, which the Session will use for connection resources
|
# an Manager, which the Session will use for connection resources
|
||||||
some_engine = create_engine(DB_URL)
|
some_engine = create_engine(DB_URL)
|
||||||
@@ -169,6 +171,7 @@ class FileData():
|
|||||||
AddLogForJob(job, "Found new file: {}".format(fname) )
|
AddLogForJob(job, "Found new file: {}".format(fname) )
|
||||||
else:
|
else:
|
||||||
AddLogForJob(job, "DEBUG: {} - {} is OLDER than {}".format( file, stat.st_ctime, last_import_date ), file )
|
AddLogForJob(job, "DEBUG: {} - {} is OLDER than {}".format( file, stat.st_ctime, last_import_date ), file )
|
||||||
|
time.sleep(0.4)
|
||||||
settings.last_import_date = time.time()
|
settings.last_import_date = time.time()
|
||||||
session.commit()
|
session.commit()
|
||||||
return self
|
return self
|
||||||
@@ -297,14 +300,17 @@ def RunJob(job):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def HandleJobs():
|
def HandleJobs():
|
||||||
print("PA job manager is scanning for jobs")
|
global pa_eng
|
||||||
|
|
||||||
|
print("PA job manager is scanning for new jobs to process")
|
||||||
pa_eng.state = 'Scanning Jobs'
|
pa_eng.state = 'Scanning Jobs'
|
||||||
jobs=GetJobs()
|
jobs=GetJobs()
|
||||||
pa_eng.num_active_jobs=0
|
pa_eng.num_active_jobs=0
|
||||||
pa_eng.num_completed_jobs=0
|
pa_eng.num_completed_jobs=0
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
if job.pa_job_state != 'Completed':
|
if job.pa_job_state != 'Completed':
|
||||||
RunJob(job)
|
threading.Thread(target=RunJob, args=(job,)).start()
|
||||||
|
print ("HandleJobs setting num_active jobs to +1")
|
||||||
pa_eng.num_active_jobs = pa_eng.num_active_jobs + 1
|
pa_eng.num_active_jobs = pa_eng.num_active_jobs + 1
|
||||||
else:
|
else:
|
||||||
pa_eng.num_completed_jobs = pa_eng.num_completed_jobs +1
|
pa_eng.num_completed_jobs = pa_eng.num_completed_jobs +1
|
||||||
@@ -346,4 +352,10 @@ if __name__ == "__main__":
|
|||||||
print( "Failed to initialise PA Job Manager: {}".format(e) )
|
print( "Failed to initialise PA Job Manager: {}".format(e) )
|
||||||
session.rollback()
|
session.rollback()
|
||||||
HandleJobs()
|
HandleJobs()
|
||||||
print("Exiting for now: {}".format( pa_eng ))
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind((PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT))
|
||||||
|
s.listen()
|
||||||
|
while True:
|
||||||
|
conn, addr = s.accept()
|
||||||
|
print("Connection from: {} so HandleJobs".format(addr))
|
||||||
|
HandleJobs()
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
DB_URL = 'postgresql+psycopg2://pa:for_now_pa@mara.ddp.net:55432/pa'
|
DB_URL = 'postgresql+psycopg2://pa:for_now_pa@mara.ddp.net:55432/pa'
|
||||||
|
PA_JOB_MANAGER_HOST="192.168.0.2"
|
||||||
|
PA_JOB_MANAGER_PORT=55430
|
||||||
|
|||||||
17
tables.sql
17
tables.sql
@@ -56,13 +56,10 @@ insert into person_refimg_link values ( 2, 2 );
|
|||||||
insert into person_refimg_link values ( 3, 3 );
|
insert into person_refimg_link values ( 3, 3 );
|
||||||
insert into person_refimg_link values ( 4, 4 );
|
insert into person_refimg_link values ( 4, 4 );
|
||||||
insert into settings values ( (select nextval('settings_id_seq')), '/home/ddp/src/photoassistant/images_to_process/#c:/Users/cam/Desktop/code/python/photoassistant/photos/#/home/ddp/src/photoassistant/new_img_dir/', 0 );
|
insert into settings values ( (select nextval('settings_id_seq')), '/home/ddp/src/photoassistant/images_to_process/#c:/Users/cam/Desktop/code/python/photoassistant/photos/#/home/ddp/src/photoassistant/new_img_dir/', 0 );
|
||||||
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Full Import', 'Completed', 4, 4, 157, 157, 'last_fake_data.img', null, 'Completed' );
|
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Full Import', 'Completed', 3, 3, 157, 157, 'fake_data.img', null, 'Completed' );
|
||||||
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Full Import', 'Processing AI', 4, 3, 157, 45, 'fake_data.img', null, 'Running' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 1: Started Scanning Files' );
|
||||||
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Scan Files', 'New', 3, 0, 157, 0, '', null, 'New' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 1: Finished Scanning Files' );
|
||||||
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Gen Hashes', 'New', 3, 0, 157, 0, '', 3, 'New' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 2: Started Generating Hashes and thumbnails' );
|
||||||
insert into job values ( (select nextval('job_id_seq')), now(), now(), 'Process AI', 'New', 3, 0, 157, 0, '', 4, 'New' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 2: Finished Generating Hashes and thumbnails' );
|
||||||
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Started Scanning Files' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 3: Started Processing AI' );
|
||||||
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Finished Scanning Files' );
|
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Pass 3: Finished Processing AI' );
|
||||||
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Started Generating Hashes and thumbnails' );
|
|
||||||
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Finished Generating Hashes and thumbnails' );
|
|
||||||
insert into joblog values ( (select nextval('joblog_id_seq')), 1, now(), 'Started Processing AI for "Cam"' );
|
|
||||||
|
|||||||
@@ -79,8 +79,9 @@
|
|||||||
</div class="nav-item dropdown">
|
</div class="nav-item dropdown">
|
||||||
<div class="nav-item ml-5">
|
<div class="nav-item ml-5">
|
||||||
<a href="{{url_for('jobs')}}"}}<span class="navbar-text">Active Jobs:
|
<a href="{{url_for('jobs')}}"}}<span class="navbar-text">Active Jobs:
|
||||||
{% if GetNumActiveJobs() != None %}
|
{% set num_active_jobs = GetNumActiveJobs() %}
|
||||||
<span class="badge badge-danger text-white"}}>4</span>
|
{% if num_active_jobs > 0 %}
|
||||||
|
<span class="badge badge-danger text-white"}}>{{num_active_jobs}}</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge">0</span>
|
<span class="badge">0</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -67,3 +67,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div class="containter">
|
</div class="containter">
|
||||||
{% endblock main_content %}
|
{% endblock main_content %}
|
||||||
|
{% block script_content %}
|
||||||
|
<script>
|
||||||
|
{% if job.pa_job_state != "Completed" %}
|
||||||
|
setTimeout(function(){ window.location.reload(1); }, 3000 )
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
{% endblock script_content %}
|
||||||
|
|||||||
Reference in New Issue
Block a user