Skip to content

JobsManager is a lightweight, database-driven job scheduling service built on top of APScheduler and MySQL.

License

Notifications You must be signed in to change notification settings

kylechenoO/JobsManager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

JobsManager

Author: Kyle

Email: kyle@hacking-linux.com

Version: 0.0.1

Overview

JobsManager is a lightweight, database-driven job scheduling service built on top of APScheduler and MySQL.

It is designed as a long-running service and focuses on:

  • Persistent job scheduling
  • Explicit, database-controlled reloads
  • Clear separation between job management and scheduler runtime
  • Predictable behavior suitable for production environments

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ bin/JobsManager.py  β”‚
β”‚ Service entry point β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ JobsManagerService  β”‚
β”‚ Scheduler runtime   β”‚
β”‚ - APScheduler       β”‚
β”‚ - reload logic      β”‚
β”‚ - signal handling   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Task                β”‚
β”‚ Job management API  β”‚
β”‚ - add / update      β”‚
β”‚ - remove / list     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Job                 β”‚
β”‚ Job definition      β”‚
β”‚ - cron schedule     β”‚
β”‚ - shell command     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure

JobsManager/
β”œβ”€β”€ bin/
β”‚   β”œβ”€β”€ JobsManager.py
β”‚   └── TaskSample.py
β”œβ”€β”€ etc/
β”‚   └── global.json
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ Config.py
β”‚   β”œβ”€β”€ Job.py
β”‚   β”œβ”€β”€ JobsManagerService.py
β”‚   β”œβ”€β”€ Log.py
β”‚   β”œβ”€β”€ MySQL.py
β”‚   └── Task.py
β”œβ”€β”€ log/
β”‚   └── jobsmanager.log
β”œβ”€β”€ systemd/
β”‚   └── jobsmanager.service
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ pyproject.toml
└── README.md

Core Components

JobsManagerService

lib/JobsManagerService.py

The scheduler runtime service responsible for:

  • Initializing APScheduler with a MySQL-backed job store
  • Managing scheduler lifecycle (start / stop)
  • Detecting database changes
  • Reloading scheduler state safely
  • Handling graceful shutdown via system signals

Task

lib/Task.py

A lightweight wrapper around APScheduler providing job management APIs:

  • Add, update, remove scheduled jobs
  • Translate Job definitions into cron triggers
  • Execute shell commands with timeout control

Job

lib/Job.py

A pure data model describing a scheduled job:

  • Job identifier
  • Shell command
  • Cron-style schedule fields
  • Execution timeout

Scheduler Reload and Database Coordination

JobsManager uses MySQL as the single source of truth for job persistence and scheduler reload coordination.

Reloads are explicit, rate-limited, and controlled by database state.

Runtime & Reload Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ JobsManager.py            β”‚
β”‚ Service entry point       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ JobsManagerService        β”‚
β”‚ runtime loop              β”‚
β”‚ - poll DB                 β”‚
β”‚ - reload if needed        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
        check  β”‚
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_update_info            β”‚
β”‚ reload marker table       β”‚
β”‚ - updated = 0 ?           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
     full      β”‚
     reload    β”‚
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ APScheduler               β”‚
β”‚ SQLAlchemyJobStore        β”‚
β”‚ - load jobs from MySQL    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Reload Control Logic

  • Job changes do not directly reload the scheduler
  • A marker row is inserted into jm_update_info with updated = 0
  • The scheduler polls for pending markers
  • Reload is triggered only when pending markers exist
  • Reloads are serialized using a lock
  • Scheduler state is rebuilt from database state

Logging and Observability

JobsManager supports file-based and database-backed logging.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Application / Scheduler   β”‚
β”‚ - lifecycle events        β”‚
β”‚ - reload operations       β”‚
β”‚ - job execution           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Logging subsystem         β”‚
β”‚ - file handler            β”‚
β”‚ - MySQL handler           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_syslog                 β”‚
β”‚ persistent logs           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Database Schema

This section describes the logical schema (ER-style) of JobsManager tables. DDL definitions are intentionally omitted from this README.

jm_syslog

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_syslog                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ id               (PK)        β”‚
β”‚ created_at                   β”‚
β”‚ level                        β”‚
β”‚ logger_name                  β”‚
β”‚ message                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Purpose:                     β”‚
β”‚ - Persistent system logging  β”‚
β”‚ - Reload and runtime logs    β”‚
β”‚ - Execution error logs       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

jm_update_info

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_update_info               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ id               (PK)        β”‚
β”‚ updated                      β”‚
β”‚ insert_time                  β”‚
β”‚ update_time                  β”‚
β”‚ jobs_before_update           β”‚
β”‚ jobs_after_update            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Purpose:                     β”‚
β”‚ - Signal scheduler reloads   β”‚
β”‚ - Track change context       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Table Interaction Summary

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Job / Task Management     β”‚
β”‚ - add / update / remove   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
        insert β”‚  updated = 0
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_update_info            β”‚
β”‚ reload marker             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
        poll   β”‚
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ JobsManagerService        β”‚
β”‚ - detect updates          β”‚
β”‚ - trigger reload          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
       log     β”‚
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ jm_syslog                 β”‚
β”‚ persistent logs           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Job Definition and Parameters

Jobs are defined using the Job data model.

Signature

Job(
    id: str,
    command: str,
    second: str = "*",
    minute: str = "*",
    hour: str = "*",
    day: str = "*",
    month: str = "*",
    day_of_week: str = "*",
    timeout: int = 60
)

Required Parameters

  • id: Unique job identifier
  • command: Shell command executed using subprocess.run(..., shell=True)

Optional Parameters

  • second, minute, hour, day, month, day_of_week: Cron-style schedule fields (default "*")
  • timeout: Max execution time in seconds (default 60)

Example

job = Job(
    id="job_echo",
    command='echo "hello world"',
    minute="*/5",
    timeout=10
)

Running JobsManager

Manual Start

python bin/JobsManager.py

systemd Deployment

cp systemd/jobsmanager.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable jobsmanager
systemctl start jobsmanager

Managing Jobs

bin/TaskSample.py demonstrates job operations such as list/add/update/remove.

Design Principles

  • Database is the source of truth
  • Reloads are explicit and controlled
  • Scheduler state is always rebuildable
  • Observability is a first-class concern
  • Designed for long-running supervised services

License

MIT License

About

JobsManager is a lightweight, database-driven job scheduling service built on top of APScheduler and MySQL.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published