{"id":31274125,"url":"https://github.com/gitbrincie212/chronographer","last_synced_at":"2025-09-23T22:37:05.749Z","repository":{"id":313489253,"uuid":"1051150044","full_name":"GitBrincie212/ChronoGrapher","owner":"GitBrincie212","description":"ChronoGrapher is a WIP project that aims to implement a flexible multi-language scheduler, allowing for multiple programming languages to interact with one and another or used by only one","archived":false,"fork":false,"pushed_at":"2025-09-22T08:43:13.000Z","size":7007,"stargazers_count":3,"open_issues_count":5,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-09-22T09:29:47.789Z","etag":null,"topics":["automation","chronographer","cron","data-engineering","data-orchestration","data-science","java","javascript","python","python3","rust","rust-crate","rust-lang","rust-library","schedule","scheduler","typescript","workflow-engine","workflow-orchestration"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GitBrincie212.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-05T14:16:21.000Z","updated_at":"2025-09-22T08:43:16.000Z","dependencies_parsed_at":"2025-09-06T12:32:51.513Z","dependency_job_id":"3f52b482-fc18-44d0-a2d4-a3a20ae83f0c","html_url":"https://github.com/GitBrincie212/ChronoGrapher","commit_stats":null,"previous_names":["gitbrincie212/chronolog","gitbrincie212/chronographer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GitBrincie212/ChronoGrapher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GitBrincie212%2FChronoGrapher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GitBrincie212%2FChronoGrapher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GitBrincie212%2FChronoGrapher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GitBrincie212%2FChronoGrapher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GitBrincie212","download_url":"https://codeload.github.com/GitBrincie212/ChronoGrapher/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GitBrincie212%2FChronoGrapher/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276662362,"owners_count":25682027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-23T02:00:09.130Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","chronographer","cron","data-engineering","data-orchestration","data-science","java","javascript","python","python3","rust","rust-crate","rust-lang","rust-library","schedule","scheduler","typescript","workflow-engine","workflow-orchestration"],"created_at":"2025-09-23T22:37:03.032Z","updated_at":"2025-09-23T22:37:05.740Z","avatar_url":"https://github.com/GitBrincie212.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eChronographer (Scheduling \u0026 Orchestration Library)\u003c/h1\u003e\n\u003cimg src=\"./assets/Chronographer Banner.png\" alt=\"Chronographer Banner\" /\u003e\n\n\u003e [!IMPORTANT]  \n\u003e The project is in its infancy, it is not out there, as its being worked on and crafted meticulously. If you plan to\n\u003e contribute to the project, now is the time to provide a good helping hand for the hardworking team. When it comes to\nintegrating with other programming languages, we mainly focus on rust then slowly make the features available in other \nlanguages\n\u003e \n\u003e In addition, the project uses temporary license: **[BSL Business Source License](LICENSE)**, once beta versions roll out, \nthis is when Chronographer will switch to [MIT License](https://opensource.org/license/mit), in the meantime, \nthe license in a nutshell says:\n\u003e - You can view the source, learn from it, and use it for testing and development.\n\u003e - You cannot use this software to run a competing service or product.\n\u003e - The license will automatically convert to the [MIT License](https://opensource.org/license/mit) on \n\u003e the date of the first official beta announcement (made by the owner, GitBrincie212)\n\nChronographer is the **ULTIMATE** unopinionated scheduling library which all developers dreamed of.\nSchedule thousands of tasks with the efficiency of rust while still using it in multiple programming languages\nsuch as \u003cu\u003ePython\u003c/u\u003e, \u003cu\u003eRust\u003c/u\u003e, \u003cu\u003eJavaScript(and TypeScript)\u003c/u\u003e and even \u003cu\u003eJava\u003c/u\u003e. The library is designed to be\nas easy to use as possible while being powerful, flexible and extendable\n\n\u003cimg align=\"center\" src=\"assets/Chronographer Divider.png\" /\u003e\nSince Chronographer is a fully featured scheduling library, it provides many features out of the box by default:\n\n## 🧩 Task Composition\nInstead of thinking a task is just some executable, Chronographer thinks of tasks as components in a group instead, allowing \nthe expression and reuse of complex logic easily while also separating concerns and giving overall flexibility, tasks \nconsist of:\n  - ***Task Metadata:*** The \u003cins\u003eState\u003c/ins\u003e of the task, anything data-related. Internally, this data is mutable, metadata\n  can also be exposed restricting write access to any data, think of it as a global state for the entire task. In most\n  cases, this is optional to provide\n  \u003cbr /\u003e \u003cbr /\u003e\n  - ***Task Frame*** The Task Frame is the core embodiment of a task. It defines \u003cins\u003eWhat\u003c/ins\u003e needs to be done. Think of it \n  as the immutable recipe or the instruction set for a specific unit of work. Task frames can access the metadata of the\n  task, task frames can also be decorated / wrapped, allowing for flexibility with minimal boilerplate footprint and code\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Schedule** This defines \u003cins\u003eWhen\u003c/ins\u003e the task needs to be executed, schedules can be as simple as an\n  interval, to a cron expression and even a calendar. Given a specific time, they calculate based on the time provided, when\n  the task will execute again (they can fail depending on the scenario)\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Scheduling Strategy (Policy)** Defines when the task reschedules (how the task overlaps with others), \n  should it reschedule the same instance now? Should it do it once the instance finishes execution? Should it cancel\n  the previous running task? All these questions are answered by the policy, by default it uses the sequential policy\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Error Handler** This handles gracefully errors when a task fails, it is meant as a recovery from any potential \n  error, examples include rollbacks, cleanups, state reset management, and so on. While the default error handler used is\n  for silently ignoring them, in production environments it is advised to make your own error handler\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Extension** Acts as an extension point for defining more complex task types, by default it is not required,\n   however, in the future distributed crate, this will be used for defining other fields which do not fit in the core\n  crate (single-node use)\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Priority** Defines the importance of a task. Chronographer offers 5 levels of priority which are\n  ``LOW``, ``MEDIUM``, ``HIGH``, ``IMPORTANT``, ``CRITICAL``. These priority levels make Chronographer responsive even under\n  heavy workflow, as it optimizes the execution of tasks, as low priority tasks may execute a bit later, whereas critical\n  tasks in most scenarios will immediately execute\n  \u003cbr /\u003e \u003cbr /\u003e\n  - **Task Dependencies** While for task frames, you can use ``ParallelTaskFrame`` and ``SequentialTaskFrame`` together,\n  there may be cases where you want Task C to wait for Task A and Task B to finish before scheduling it for execution.\n    Chronographer has this area covered as well. By default, there are no task dependencies for tasks\n  \n## 🔄 Task Behavior And Management\nFine grain control over task behavior, listening to lifecycle or local task frame events, controlling how the task\nis rescheduled via scheduling strategies, controlling dependencies of a task... etc. Want to dynamically re-schedule, \nremove or schedule tasks at any point throughout your program? Chronographer has you covered\n\n## 📋 Scheduler Composition\nJust like tasks. Chronographer gives the ability to also restructure schedulers to fit your needs, no need to depend\non the default scheduler implementation, if you need. You can also implement your own, or even use existing components\ndefined by the default scheduler, here are the composites a scheduler requires:\n- **Clock** This is a mechanism for tracking time, while by default it uses the system clock, one can also use a virtual\nclock for simulating scenarios, such as unit testing, benchmarking or stress-testing\n\u003cbr /\u003e \u003cbr /\u003e\n- **Scheduler Engine** The actual core that drives the Scheduler, it sleeps til the earliest task is due, then\ngets the instance from ``TaskStore``, emits relevant events and hands out the task to ``TaskDispatcher``, then repeats\nthe process for the next task\n\u003cbr /\u003e \u003cbr /\u003e\n- **Task Store** It stores a task in some form (either be in-memory or persist them), the scheduler may interact with\nthe task store via getting the earliest task, rescheduling the same task instance or from methods from the scheduler which \nact as wrappers around the task store mechanism\n\u003cbr /\u003e \u003cbr /\u003e\n- **Task Dispatcher** It is the main logic block that handles execution logic, typically when the scheduler hands out a\ntask to the dispatcher, it tries to find the worker (which are units that concurrently execute) with the most minimum work \nit has based on priority level, once it finds it, that is where the task's schedule strategy is executed\n\n## 📡 Language Agnostic Communication\nEmit a task in python, listen to task events in JavaScript, write task logic in rust. No more doing trickery to\nwork around the limitation of a library/framework being limited to one specific programming language. Chronographer is\nthe central hub for scheduling\n\n\u003cimg align=\"center\" src=\"assets/Chronographer Divider.png\" /\u003e\nWhy use Chronographer when other scheduling libraries exist in other programming languages? Some of the highlights / strength points\nwhich you might consider to use Chronographer over other scheduling libraries are:\n\n- **🌐 Multi-language Support:** Chronographer is available in Python, Rust, JavaScript/TypeScript, and Java. \nSwitch between languages without rewriting scheduling logic and learning a new framework. No more trying to combat the limitations of different \nschedulers\n\u003cbr /\u003e \u003cbr /\u003e\n- **🛠️ Extensible:** Chronographer's architecture has extensibility in mind, as such you are not restricted to using the\ndefault implementation of the scheduler, task frames, and even schedules. You can build extensions \nfor Chronographer in your favourite programming language ecosystem\n\u003cbr /\u003e \u003cbr /\u003e\n- **↔️ Horizontal Scaling** Chronographer makes it easy and intuitive to scale the scheduling infrastructure horizontally,\nacross multiple servers located in multiple regions. Chronographer handles multiple timezones and converting them in-between\n\u003cbr /\u003e \u003cbr /\u003e\n- **🚀 Lightweight \u0026 Efficient:** Minimal overhead ensures it won’t bloat your project, while still providing reliable \ntiming and execution for thousands of tasks with the power, flexibility and safety of \u003cu\u003e_Rust_\u003c/u\u003e under the hood as\nits core.\n\u003cbr /\u003e \u003cbr /\u003e\n- **🔧 Developer-Friendly:** Clear API, intuitive task registration, vast documentation, life shouldn't be harder than\nit needs to be. No complications, no trickery, what you write in code is what you will get in the production environment\n\u003cbr /\u003e\u003cbr /\u003e\n- **⏰ Millisecond Precision:** Chronographer is also designed to be millisecond precise, which makes it very practical for\nfrequent scheduled tasks, it maintains this precision even when clogged by multiple tasks\n\u003cbr /\u003e \u003cbr /\u003e\n- **📦 Tiny But Mighty** Tired of large sized packages, taking forever to compile, consuming disk space and so on? We too,\nas such, Chronographer is tiny about **~1MB** in size\n\u003cbr /\u003e \u003cbr /\u003e\n\u003cimg align=\"center\" src=\"assets/Chronographer Divider.png\" /\u003e\nWhen it comes to contributing and forking. Chronographer is free and open source to use, only restricted by the lightweight\n**MIT License** \u003cstrong\u003e(this license only applies to when the project enters beta)\u003c/strong\u003e, contributions\nare welcome with wide open arms as Chronographer is looking to foster a community\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitbrincie212%2Fchronographer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgitbrincie212%2Fchronographer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitbrincie212%2Fchronographer/lists"}