285 lines
8.3 KiB
Python
285 lines
8.3 KiB
Python
"""
|
|
This module contains DB logic
|
|
"""
|
|
from __future__ import print_function
|
|
|
|
import logging
|
|
import sys
|
|
from datetime import datetime, timedelta
|
|
|
|
from sqlalchemy import (
|
|
Column,
|
|
DateTime,
|
|
Boolean,
|
|
Integer,
|
|
String,
|
|
create_engine,
|
|
inspect,
|
|
)
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from .config_manager import get_config
|
|
|
|
PAGESIZE = 10
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
class Rec(Base):
|
|
"""Entry on the DB"""
|
|
|
|
__tablename__ = "rec"
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String, nullable=True)
|
|
starttime = Column(DateTime, nullable=True)
|
|
endtime = Column(DateTime, nullable=True)
|
|
filename = Column(String, nullable=True)
|
|
ready = Column(Boolean, default=False)
|
|
error = Column(String, nullable=True, default=None)
|
|
|
|
def __init__(self, name="", starttime=None, endtime=None, filename=None):
|
|
self.name = name
|
|
self.starttime = starttime
|
|
self.endtime = endtime
|
|
self.filename = filename
|
|
|
|
def serialize(self):
|
|
"""json-friendly encoding"""
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"starttime": self.starttime,
|
|
"endtime": self.endtime,
|
|
"filename": self.filename,
|
|
"ready": self.ready,
|
|
}
|
|
|
|
def __repr__(self):
|
|
contents = "id:'%s',name:'%s',Start: '%s',End: '%s'" % (
|
|
self.id,
|
|
self.name,
|
|
self.starttime,
|
|
self.endtime,
|
|
)
|
|
if self.filename is not None:
|
|
contents += ",Filename: '%s'" % self.filename
|
|
return "<Rec(%s)>" % contents
|
|
|
|
@property
|
|
def status(self) -> str:
|
|
if self.error is not None:
|
|
return 'ERROR'
|
|
if self.ready:
|
|
return 'DONE'
|
|
return 'WIP'
|
|
|
|
|
|
class RecDB:
|
|
def __init__(self, uri):
|
|
self.engine = create_engine(uri, echo=False)
|
|
self.conn = self.engine.connect()
|
|
self.log = logging.getLogger(name=self.__class__.__name__)
|
|
|
|
logging.getLogger("sqlalchemy.engine").setLevel(logging.FATAL)
|
|
logging.getLogger(
|
|
"sqlalchemy.engine.base.Engine").setLevel(logging.FATAL)
|
|
logging.getLogger("sqlalchemy.dialects").setLevel(logging.FATAL)
|
|
logging.getLogger("sqlalchemy.pool").setLevel(logging.FATAL)
|
|
logging.getLogger("sqlalchemy.orm").setLevel(logging.FATAL)
|
|
|
|
Base.metadata.create_all(self.engine) # create Database
|
|
|
|
Session = sessionmaker(bind=self.engine)
|
|
self.session = Session()
|
|
|
|
self.err = ""
|
|
|
|
def add(self, simplerecord):
|
|
s = self.get_session()
|
|
s.add(simplerecord)
|
|
s.commit()
|
|
self.log.info("New Record: %s" % simplerecord)
|
|
return simplerecord
|
|
|
|
def update(self, id, rec):
|
|
|
|
# TODO: rlist = results list
|
|
_rlist = self._search(_id=id)
|
|
if not len(_rlist) == 1:
|
|
raise ValueError("Too many recs with id=%s" % id)
|
|
|
|
self.log.debug("DB:: Update request %s:%s " % (id, rec))
|
|
self.log.debug("DB:: Update: data before %s" % _rlist[0])
|
|
|
|
# 2013-11-24 22:22:42
|
|
_rlist[0].starttime = rec["starttime"]
|
|
_rlist[0].endtime = rec["endtime"]
|
|
if "name" in rec:
|
|
_rlist[0].name = rec["name"]
|
|
self.log.debug("DB:: Update: data AFTER %s" % _rlist[0])
|
|
|
|
self.get_session(_rlist[0]).commit()
|
|
self.log.debug("DB:: Update complete")
|
|
return _rlist[0]
|
|
|
|
def delete(self, recid):
|
|
|
|
_rlist = self._search(id=recid)
|
|
|
|
if len(_rlist) == 0:
|
|
self.log.info("DB: Delete: no record found!")
|
|
self.err = "No rec found"
|
|
return False
|
|
|
|
if len(_rlist) > 1:
|
|
self.log.warning("DB: Delete: multiple records found!")
|
|
self.err = "multiple ID Found %s" % (_rlist)
|
|
return False
|
|
|
|
s = self.get_session()
|
|
s.delete(_rlist[0])
|
|
self.log.info("Delete: delete complete")
|
|
s.commit()
|
|
return True
|
|
|
|
def commit(self):
|
|
self.log.info("Commit!!")
|
|
self.session.commit()
|
|
|
|
def get_session(self, rec=None):
|
|
if rec is None:
|
|
Session = sessionmaker(bind=self.engine)
|
|
return Session()
|
|
else:
|
|
return inspect(rec).session
|
|
|
|
def get_all(self, page=0, page_size=PAGESIZE):
|
|
return self._search(page=page, page_size=page_size)
|
|
|
|
def get_ongoing(self, page=0, page_size=PAGESIZE):
|
|
query = self._query_page(self._query_ongoing(), page, page_size)
|
|
return query.all()
|
|
|
|
def get_not_completed(self, minseconds=36000):
|
|
query = self._query_ongoing()
|
|
query = self._query_older(timedelta(seconds=minseconds), query)
|
|
return query.all()
|
|
|
|
def get_archive_recent(self):
|
|
query = self._query_saved()
|
|
query = self._query_newer(timedelta(days=15), query)
|
|
query = query.order_by(Rec.starttime.desc())
|
|
return query.all()
|
|
|
|
def _query_ongoing(self, query=None):
|
|
"""
|
|
Not terminated AND recent.
|
|
|
|
The meaning is "a query that makes sense to stop"
|
|
"""
|
|
delta = timedelta(seconds=get_config()["FORGE_MAX_DURATION"])
|
|
return self._query_newer(delta, self._query_not_saved(query))
|
|
|
|
def _query_not_saved(self, query=None):
|
|
"""Still not saved"""
|
|
if query is None:
|
|
query = self.get_session().query(Rec)
|
|
return query.filter(Rec.filename == None)
|
|
|
|
def _query_saved(self, query=None):
|
|
"""saved, regardless of status"""
|
|
if query is None:
|
|
query = self.get_session().query(Rec)
|
|
return query.filter(Rec.filename != None)
|
|
|
|
def _query_newer(self, delta, query=None):
|
|
"""Get Rec older than delta seconds"""
|
|
if query is None:
|
|
query = self.get_session().query(Rec)
|
|
return query.filter(Rec.starttime > datetime.now() - delta)
|
|
|
|
def _query_older(self, delta, query=None):
|
|
"""Get Rec older than delta seconds"""
|
|
if query is None:
|
|
query = self.get_session().query(Rec)
|
|
return query.filter(Rec.starttime < datetime.now() - delta)
|
|
|
|
def _query_page(self, query, page=0, page_size=PAGESIZE):
|
|
if page_size:
|
|
page_size = int(page_size)
|
|
query = query.limit(page_size)
|
|
if page:
|
|
query = query.offset(page * page_size)
|
|
return query
|
|
|
|
def _query_generic(self, query, _id=None, name=None, starttime=None, endtime=None):
|
|
if _id is not None:
|
|
query = query.filter_by(id=_id)
|
|
if name is not None:
|
|
query = query.filter(Rec.name.like("%" + name + "%"))
|
|
if starttime is not None:
|
|
_st = starttime
|
|
query = query.filter(Rec.starttime > _st)
|
|
if endtime is not None:
|
|
_et = endtime
|
|
query = query.filter(Rec.endtime < _et)
|
|
return query
|
|
|
|
def _search(
|
|
self,
|
|
_id=None,
|
|
name=None,
|
|
starttime=None,
|
|
endtime=None,
|
|
page=0,
|
|
page_size=PAGESIZE,
|
|
):
|
|
self.log.debug(
|
|
"DB: Search => id:%s name:%s starttime:%s endtime=%s"
|
|
% (_id, name, starttime, endtime)
|
|
)
|
|
|
|
query = self.get_session().query(Rec)
|
|
query = self._query_generic(query, _id, name, starttime, endtime)
|
|
query = self._query_page(query, page, page_size)
|
|
self.log.debug("Searching: %s" % str(query))
|
|
ret = query.all()
|
|
return ret
|
|
|
|
def get_err(self):
|
|
print("DB error: %s" % (self.err))
|
|
t = self.err
|
|
self.err = ""
|
|
return t
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
def printall(queryres):
|
|
for record in queryres:
|
|
print("Record: %s" % record)
|
|
|
|
db = RecDB()
|
|
_mytime = datetime(2014, 5, 23, 15, 12, 17)
|
|
_endtime = datetime(2014, 5, 24, 17, 45, 17)
|
|
|
|
a = Rec(name="Mimmo1", starttime=_mytime, endtime=_endtime)
|
|
printall(db._search())
|
|
sys.exit("End test job")
|
|
|
|
# a = Rec(name="Mimmo1", starttime=_mytime, endtime=None)
|
|
print("Aggiunto", db.add(a))
|
|
printall(db.get_all(page_size=5, page=0))
|
|
|
|
print("Mimmo ")
|
|
printall(db._search(name="Mimmo1"))
|
|
print("Search")
|
|
printall(db._search(name="Mimmo1", starttime=datetime(2014, 5, 24, 15, 16, 1)))
|
|
a = db.get_by_id(5)
|
|
a.start()
|
|
db.delete(1)
|
|
db.delete(2)
|
|
db.delete(4)
|
|
db.delete(1)
|
|
printall(db._search())
|