# Path: gengine/base/util.py
# def dt_ago(**kw):
#     return datetime.datetime.utcnow().replace(tzinfo=pytz.utc) - datetime.timedelta(**kw)
# 
# def dt_now():
#     return datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
# 
# Path: gengine/app/cache.py
# def init_caches():
#     global cache_general
#     cache_general = create_cache("general")
# 
#     global cache_achievement_eval
#     cache_achievement_eval = create_cache("achievement_eval")
# 
#     global cache_achievements_by_subject_for_today
#     cache_achievements_by_subject_for_today = create_cache("achievements_by_subject_for_today")
# 
#     global cache_achievements_subjects_levels
#     cache_achievements_subjects_levels = create_cache("achievements_subjects_levels")
# 
#     global cache_translations
#     cache_translations = create_cache("translations")
# 
#     # The Goal evaluation Cache is implemented as a two-level cache (persistent in db, non-persistent as dogpile)
#     global cache_goal_evaluation
#     cache_goal_evaluation = create_cache("goal_evaluation")
# 
#     #global cache_goal_statements
#     #cache_goal_statements = create_memory_cache("goal_statements")


import sys
import logging
import datetime
import os
import pyramid_dogpile_cache
import transaction
    import gengine
    import gengine.app.model as m
    import crontab
from gengine.base.util import dt_ago, dt_now
from sqlalchemy.sql.expression import and_
from zope.sqlalchemy.datamanager import mark_changed
from gengine.app.cache import init_caches
from pyramid.config import Configurator
from pyramid.paster import (
    get_appsettings,
    setup_logging,
)
from pyramid.scripts.common import parse_vars
from sqlalchemy import engine_from_config
    from gengine.metadata import (
        DBSession
    )
    from gengine.app.registries import get_task_registry
                s = item.schedule(date_from=now)
                prev = s.get_next().replace(second=0)
                next = s.get_next().replace(second=0)

                execs = sess.execute(m.t_taskexecutions.select().where(and_(
                    m.t_taskexecutions.c.task_id == task["id"],
                    m.t_taskexecutions.c.canceled_at == None,
                    m.t_taskexecutions.c.finished_at == None,
                )).order_by(m.t_taskexecutions.c.planned_at.desc())).fetchall()

                found = False

                for exec in execs:

                    if exec["planned_at"] >= next:
                        # The next execution is already planned
                        found = True

                    if exec["planned_at"] <= prev and prev < dt_ago(minutes=10) and not exec["locked_at"]:
                        #  The execution is more than 10 minutes in the past and not yet locked (worker not running / overloaded)
                        if next - datetime.timedelta(minutes=10) < dt_now():
                            # The next execution is planned in less than 10 minutes, cancel the other one
                            sess.execute(
                                m.t_taskexecutions.update().values({
                                    'canceled_at': dt_now()
                                }).where({
                                    'id': exec["id"]
                                })
                            )


# Path: gengine/base/util.py
# def dt_ago(**kw):
#     return datetime.datetime.utcnow().replace(tzinfo=pytz.utc) - datetime.timedelta(**kw)
# 
# def dt_now():
#     return datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
# 
# Path: gengine/app/cache.py
# def init_caches():
#     global cache_general
#     cache_general = create_cache("general")
# 
#     global cache_achievement_eval
#     cache_achievement_eval = create_cache("achievement_eval")
# 
#     global cache_achievements_by_subject_for_today
#     cache_achievements_by_subject_for_today = create_cache("achievements_by_subject_for_today")
# 
#     global cache_achievements_subjects_levels
#     cache_achievements_subjects_levels = create_cache("achievements_subjects_levels")
# 
#     global cache_translations
#     cache_translations = create_cache("translations")
# 
#     # The Goal evaluation Cache is implemented as a two-level cache (persistent in db, non-persistent as dogpile)
#     global cache_goal_evaluation
#     cache_goal_evaluation = create_cache("goal_evaluation")
# 
#     #global cache_goal_statements
#     #cache_goal_statements = create_memory_cache("goal_statements")


# Path: gengine/maintenance/scripts/scheduler_beat.py
import sys
import logging
import datetime
import os
import pyramid_dogpile_cache
import transaction
    import gengine
    import gengine.app.model as m
    import crontab
from gengine.base.util import dt_ago, dt_now
from sqlalchemy.sql.expression import and_
from zope.sqlalchemy.datamanager import mark_changed
from gengine.app.cache import init_caches
from pyramid.config import Configurator
from pyramid.paster import (
    get_appsettings,
    setup_logging,
)
from pyramid.scripts.common import parse_vars
from sqlalchemy import engine_from_config
    from gengine.metadata import (
        DBSession
    )
    from gengine.app.registries import get_task_registry

                s = item.schedule(date_from=now)
                prev = s.get_next().replace(second=0)
                next = s.get_next().replace(second=0)

                execs = sess.execute(m.t_taskexecutions.select().where(and_(
                    m.t_taskexecutions.c.task_id == task["id"],
                    m.t_taskexecutions.c.canceled_at == None,
                    m.t_taskexecutions.c.finished_at == None,
                )).order_by(m.t_taskexecutions.c.planned_at.desc())).fetchall()

                found = False

                for exec in execs:

                    if exec["planned_at"] >= next:
                        # The next execution is already planned
                        found = True

                    if exec["planned_at"] <= prev and prev < dt_ago(minutes=10) and not exec["locked_at"]:
                        #  The execution is more than 10 minutes in the past and not yet locked (worker not running / overloaded)
                        if next - datetime.timedelta(minutes=10) < dt_now():
                            # The next execution is planned in less than 10 minutes, cancel the other one
                            sess.execute(
                                m.t_taskexecutions.update().values({
                                    'canceled_at': dt_now()
                                }).where({
                                    'id': exec["id"]
                                })
                            )


                    if exec["locked_at"] and exec["locked_at"] < dt_ago(hours=24):