{"id":30323918,"url":"https://github.com/pardnchiu/go-cron","last_synced_at":"2025-08-17T22:20:19.083Z","repository":{"id":300572190,"uuid":"1006513718","full_name":"pardnchiu/go-cron","owner":"pardnchiu","description":"A lightweight Golang scheduler supporting standard cron expressions, custom descriptors, custom intervals, and task dependencies. Easily write schedules using Go.","archived":false,"fork":false,"pushed_at":"2025-07-28T13:38:58.000Z","size":69,"stargazers_count":31,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-01T10:56:04.791Z","etag":null,"topics":["cron","cron-scheduler","golang","pardnchiu","scheduler","srp","standard-library","task-dependencies","task-scheduler"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pardnchiu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2025-06-22T12:49:07.000Z","updated_at":"2025-07-29T19:21:29.000Z","dependencies_parsed_at":"2025-06-22T13:40:51.396Z","dependency_job_id":"c67cc805-3ad6-4e4b-819c-6d5dae49a3fc","html_url":"https://github.com/pardnchiu/go-cron","commit_stats":null,"previous_names":["pardnchiu/go-cron-job","pardnchiu/go-cron"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/pardnchiu/go-cron","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnchiu%2Fgo-cron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnchiu%2Fgo-cron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnchiu%2Fgo-cron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnchiu%2Fgo-cron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pardnchiu","download_url":"https://codeload.github.com/pardnchiu/go-cron/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnchiu%2Fgo-cron/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270915437,"owners_count":24667335,"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-08-17T02:00:09.016Z","response_time":129,"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":["cron","cron-scheduler","golang","pardnchiu","scheduler","srp","standard-library","task-dependencies","task-scheduler"],"created_at":"2025-08-17T22:20:15.163Z","updated_at":"2025-08-17T22:20:19.074Z","avatar_url":"https://github.com/pardnchiu.png","language":"Go","funding_links":[],"categories":["Job Scheduler"],"sub_categories":["Search and Analytic Databases"],"readme":"\u003e [!NOTE]\n\u003e This README was translated by ChatGPT 4o\n# Cron Scheduler\n\n\u003e Lightweight Golang scheduler supporting standard cron expressions, custom descriptors, custom intervals, and task dependencies. Easy scheduling with Go\u003cbr\u003e\n\u003e Originally designed for the scheduling functionality used in threat score decay calculations for [pardnchiu/go-ip-sentry](https://github.com/pardnchiu/go-ip-sentry)\n\n[![pkg](https://pkg.go.dev/badge/github.com/pardnchiu/go-cron.svg)](https://pkg.go.dev/github.com/pardnchiu/go-cron)\n[![card](https://goreportcard.com/badge/github.com/pardnchiu/go-cron)](https://goreportcard.com/report/github.com/pardnchiu/go-cron)\n[![codecov](https://img.shields.io/codecov/c/github/pardnchiu/go-cron)](https://app.codecov.io/github/pardnchiu/go-cron)\n[![version](https://img.shields.io/github/v/tag/pardnchiu/go-cron?label=release)](https://github.com/pardnchiu/go-cron/releases)\n[![license](https://img.shields.io/github/license/pardnchiu/go-cron)](LICENSE)\u003cbr\u003e\n[![readme](https://img.shields.io/badge/readme-EN-white)](README.md)\n[![readme](https://img.shields.io/badge/readme-ZH-white)](README.zh.md)\n\n- [Core Features](#core-features)\n  - [Flexible Syntax](#flexible-syntax)\n  - [Task Dependencies](#task-dependencies)\n  - [Efficient Architecture](#efficient-architecture)\n- [Flowchart](#flowchart)\n- [Dependencies](#dependencies)\n- [Usage](#usage)\n  - [Installation](#installation)\n  - [Initialization](#initialization)\n    - [Basic Usage](#basic-usage)\n    - [Task Dependencies](#task-dependencies-1)\n- [Configuration](#configuration)\n- [Supported Formats](#supported-formats)\n  - [Standard](#standard)\n  - [Custom](#custom)\n- [Available Functions](#available-functions)\n  - [Scheduler Management](#scheduler-management)\n  - [Task Management](#task-management)\n- [Task Dependencies](#task-dependencies-2)\n  - [Basic Usage](#basic-usage-1)\n  - [Dependency Examples](#dependency-examples)\n  - [Task Status](#task-status)\n- [Timeout Mechanism](#timeout-mechanism)\n  - [Features](#features)\n- [Upcoming Features](#upcoming-features)\n  - [Enhanced Task Dependencies](#enhanced-task-dependencies)\n  - [Task Completion Trigger Refactor](#task-completion-trigger-refactor)\n- [License](#license)\n- [Star](#star)\n- [Author](#author)\n\n## Core Features\n\n### Flexible Syntax\nSupports standard cron expressions, custom descriptors (`@hourly`, `@daily`, `@weekly`, etc.), and custom interval (`@every`) syntax. Zero learning curve - if you know cron expressions, you can use it.\n\n### Task Dependencies\nSupports prerequisite dependency tasks, multiple dependencies, dependency timeout control, and failure handling mechanisms.\n\n### Efficient Architecture\nUses Golang standard library `heap`, focusing on core functionality. Min-heap based task scheduling with concurrent task execution and management, featuring panic recovery and dynamic task add/remove capabilities, ensuring optimal performance in high-volume task scenarios.\n\n## Flowchart\n\n\u003cdetails\u003e\n\u003csummary\u003eMain Process\u003c/summary\u003e \n\n```mermaid\nflowchart TD\n  A[Initialize] --\u003e B{Is Running?}\n  B --\u003e|No| B0[Start Execution]\n    B0 --\u003e C[Calculate Initial Tasks]\n    C --\u003e D[Initialize Tasks]\n    D --\u003e E[Start Main Loop]\n      E --\u003e H{Check Heap Status}\n      E --\u003e|No Tasks\u003cbr\u003eWait for Events| Q\n      E --\u003e|Has Tasks\u003cbr\u003eSet Next Task Timer| Q\n  B --\u003e|Yes\u003cbr\u003eWait for Trigger| Q[Listen Events]\n  \n  Q --\u003e R{Event Type}\n  R --\u003e|Timer Expired| R1[Execute Due Tasks]\n  R --\u003e|Add Task| R2[Add to Heap]\n  R --\u003e|Remove Task| R3[Remove from Heap]\n  R --\u003e|Stop Signal| R4[Cleanup and Exit]\n  \n  R1 --\u003e S[Pop Task from Heap]\n  S --\u003e R5[Calculate Next Execution Time]\n  R5 --\u003e E\n  S --\u003e T{Check if Enabled}\n  T --\u003e|Disabled| T0[Skip Task]\n  T0 --\u003e E\n  T --\u003e|Enabled| T1[Execute Task Function]\n  \n  R2 --\u003e V[Parse Schedule]\n  V --\u003e W[Create Task Object]\n  W --\u003e X[Add to Heap]\n  \n  R3 --\u003e Y[Find Task by ID]\n  Y --\u003e Z[Mark as Disabled]\n  Z --\u003e AA[Remove from Heap]\n  \n  X --\u003e E\n  AA --\u003e E\n  \n  R4 --\u003e BB[Wait for Running Tasks to Complete]\n  BB --\u003e CC[Close Channels]\n  CC --\u003e DD[Scheduler Stopped]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDependency Process\u003c/summary\u003e\n\n```mermaid\nflowchart TD\n    A[Task Added to Execution Queue] --\u003e B{Check Dependencies}\n    B --\u003e|No Dependencies| B0[Skip Dependency Process]\n      B0 --\u003e Z[End]\n    B --\u003e|Has Dependencies| B1{Dependencies Complete?}\n      B1 --\u003e|No| B10[Wait for Dependencies]\n        B10 --\u003e C{Dependency Wait Timeout?}\n          C --\u003e|No| C0[Continue Waiting]\n            C0 --\u003e D{Dependency Resolved?}\n              D --\u003e|Failed\u003cbr\u003eMark Failed| V\n              D --\u003e|Completed| B11\n              D --\u003e|Still Waiting| B10\n          C --\u003e|Yes\u003cbr\u003eMark Failed| V\n      B1 --\u003e|Yes| B11[Execute]\n        B11 --\u003e|Mark Running| E{Task Timeout Exists?}\n          E --\u003e|No| E0[Execute Action]\n            E0 --\u003e R{Execution Result}\n              R --\u003e|Success\u003cbr\u003eMark Complete| V[Update Task Result]\n              R --\u003e|Error\u003cbr\u003eMark Failed| V\n              R --\u003e|Panic\u003cbr\u003eRecover and Mark Failed| V\n          E --\u003e|Yes| E1{Task Timeout?}\n            E1 --\u003e|Timeout\u003cbr\u003eMark Failed\u003cbr\u003eTrigger Timeout Action| V\n            E1 --\u003e|Not Timeout| E0\n      B1 --\u003e|Failed\u003cbr\u003eMark Failed| V\n    \n    V --\u003e X[Record Execution Result]\n    X --\u003e Y[Notify Dependent Tasks]\n    Y --\u003e Z[End]\n```\n\n\u003c/details\u003e\n\n## Dependencies\n\n- ~~[`github.com/pardnchiu/go-logger`](https://github.com/pardnchiu/go-logger)~~ (\u003c v0.3.1)\u003cbr\u003e\n  For performance and stability, non-standard library packages are deprecated from `v0.3.1`, now using `log/slog`\n\n## Usage\n\n### Installation\n\n\u003e [!NOTE]\n\u003e Latest commit may change, recommended to use tagged versions\u003cbr\u003e\n\u003e Commits containing only documentation updates or non-functional changes will be rebased later\n\n```bash\ngo get github.com/pardnchiu/go-cron@[VERSION]\n\ngit clone --depth 1 --branch [VERSION] https://github.com/pardnchiu/go-cron.git\n```\n\n### Initialization\n\n#### Basic Usage\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"log\"\n  \"time\"\n  \n  cron \"github.com/pardnchiu/go-cron\"\n)\n\nfunc main() {\n  // Initialize (optional configuration)\n  scheduler, err := cron.New(cron.Config{\n    Location: time.Local,\n  })\n  if err != nil {\n    log.Fatal(err)\n  }\n  \n  // Start scheduler\n  scheduler.Start()\n  \n  // Add tasks\n  id1, _ := scheduler.Add(\"@daily\", func() {\n    fmt.Println(\"Daily execution\")\n  }, \"Backup task\")\n  \n  id2, _ := scheduler.Add(\"@every 5m\", func() {\n    fmt.Println(\"Execute every 5 minutes\")\n  })\n  \n  // View task list\n  tasks := scheduler.List()\n  fmt.Printf(\"Currently have %d tasks\\n\", len(tasks))\n  \n  // Remove specific task\n  scheduler.Remove(id1)\n  \n  // Remove all tasks\n  scheduler.RemoveAll()\n  \n  // Graceful shutdown\n  ctx := scheduler.Stop()\n  \u003c-ctx.Done()\n}\n```\n\n#### Task Dependencies\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"log\"\n  \"time\"\n  \n  cron \"github.com/pardnchiu/go-cron\"\n)\n\nfunc main() {\n  scheduler, err := cron.New(cron.Config{})\n  if err != nil {\n    log.Fatal(err)\n  }\n  \n  scheduler.Start()\n  defer func() {\n    ctx := scheduler.Stop()\n    \u003c-ctx.Done()\n  }()\n  \n  // Task A: Data preparation\n  taskA, _ := scheduler.Add(\"0 1 * * *\", func() error {\n    fmt.Println(\"Preparing data...\")\n    time.Sleep(2 * time.Second)\n    return nil\n  }, \"Data preparation\")\n  \n  // Task B: Data processing  \n  taskB, _ := scheduler.Add(\"0 2 * * *\", func() error {\n    fmt.Println(\"Processing data...\")\n    time.Sleep(3 * time.Second)\n    return nil\n  }, \"Data processing\")\n  \n  // Task C: Report generation (depends on A and B)\n  taskC, _ := scheduler.Add(\"0 3 * * *\", func() error {\n    fmt.Println(\"Generating report...\")\n    time.Sleep(1 * time.Second)\n    return nil\n  }, \"Report generation\", []Wait{{ID: taskA}, {ID: taskB}})\n  \n  // Task D: Email sending (depends on C)\n  _, _ = scheduler.Add(\"0 4 * * *\", func() error {\n    fmt.Println(\"Sending email...\")\n    return nil\n  }, \"Email notification\", []Wait{{ID: taskC}})\n  \n  time.Sleep(10 * time.Second)\n}\n```\n\n## Configuration\n```go\ntype Config struct {\n  Location *time.Location // Timezone setting (default: time.Local)\n}\n```\n\n## Supported Formats\n\n### Standard\n\u003e 5-field format: `minute hour day month weekday`\u003cbr\u003e\n\u003e Supports range syntax `1-5` and `1,3,5`\n\n```go\n// Every minute\nscheduler.Add(\"* * * * *\", task)\n\n// Daily at midnight\nscheduler.Add(\"0 0 * * *\", task)\n\n// Every 15 minutes\nscheduler.Add(\"*/15 * * * *\", task)\n\n// First day of month at 6 AM\nscheduler.Add(\"0 6 1 * *\", task)\n\n// Monday to Wednesday, and Friday\nscheduler.Add(\"0 0 * * 1-3,5\", task)\n```\n\n### Custom\n```go\n// January 1st at midnight\nscheduler.Add(\"@yearly\", task)\n\n// First day of month at midnight\nscheduler.Add(\"@monthly\", task)\n\n// Every Sunday at midnight\nscheduler.Add(\"@weekly\", task)\n\n// Daily at midnight\nscheduler.Add(\"@daily\", task)\n\n// Every hour on the hour\nscheduler.Add(\"@hourly\", task)\n\n// Every 30 seconds (minimum interval: 30 seconds)\nscheduler.Add(\"@every 30s\", task)\n\n// Every 5 minutes\nscheduler.Add(\"@every 5m\", task)\n\n// Every 2 hours\nscheduler.Add(\"@every 2h\", task)\n\n// Every 12 hours\nscheduler.Add(\"@every 12h\", task)\n```\n\n## Available Functions\n\n### Scheduler Management\n\n- `New()` - Create new scheduler instance\n  ```go\n  scheduler, err := cron.New(config)\n  ```\n  - Sets up task heap and communication channels\n\n- `Start()` - Start scheduler instance\n  ```go\n  scheduler.Start()\n  ```\n  - Starts the scheduling loop\n\n- `Stop()` - Stop scheduler\n  ```go\n  ctx := scheduler.Stop()\n  \u003c-ctx.Done() // Wait for all tasks to complete\n  ```\n  - Sends stop signal to main loop\n  - Returns context that completes when all running tasks finish\n  - Ensures graceful shutdown without interrupting tasks\n\n### Task Management\n\n- `Add()` - Add scheduled task\n  ```go\n  // Basic usage (no return value)\n  taskID, err := scheduler.Add(\"0 */2 * * *\", func() {\n    // Task logic\n  })\n\n  // Task with error return (supports dependencies)\n  taskID, err := scheduler.Add(\"@daily\", func() error {\n    // Task logic\n    return nil\n  }, \"Backup task\")\n\n  // Task with timeout control\n  taskID, err := scheduler.Add(\"@hourly\", func() error {\n    // Long-running task\n    time.Sleep(10 * time.Second)\n    return nil\n  }, \"Data processing\", 5*time.Second)\n\n  // Task with timeout callback\n  taskID, err := scheduler.Add(\"@daily\", func() error {\n    // Potentially timeout-prone task\n    return heavyProcessing()\n  }, \"Critical backup\", 30*time.Second, func() {\n    log.Println(\"Backup task timed out, please check system status\")\n  })\n\n  // Task with dependencies\n  taskID, err := scheduler.Add(\"@daily\", func() error {\n    // Task that depends on other tasks\n    return processData()\n  }, \"Data processing\", []Wait{{ID: taskA}, {ID: taskB}})\n\n  // Task with dependencies and timeout\n  taskID, err := scheduler.Add(\"@daily\", func() error {\n    return generateReport()\n  }, \"Report generation\", []Wait{\n    {ID: taskA, Delay: 30 * time.Second},\n    {ID: taskB, Delay: 45 * time.Second},\n  })\n  ```\n  - Parses schedule syntax\n  - Generates unique task ID for management\n  - Supports variadic parameter configuration\n    - `string`: Task description\n    - `time.Duration`: Task execution timeout\n    - `func()`: Callback function triggered on timeout\n    - `[]Wait`: Dependency task configuration (recommended format)\n    - `[]int64`: Dependency task ID list (will be removed after v2.0)\n  - Supports two action function types\n    - `func()`: No error return, doesn't support dependencies\n    - `func() error`: Has error return, supports dependencies\n\n- `Remove()` - Cancel task schedule\n  ```go\n  scheduler.Remove(taskID)\n  ```\n  - Removes task from scheduling queue\n  - Safe to call regardless of scheduler state\n\n- `RemoveAll()` - Remove all tasks\n  ```go\n  scheduler.RemoveAll()\n  ```\n  - Immediately removes all scheduled tasks\n  - Doesn't affect currently running tasks\n\n- `List()` - Get task list\n  ```go\n  tasks := scheduler.List()\n  ```\n\n## Task Dependencies \n\n### Basic Usage\n- No dependencies: Execute directly\n- Has dependencies: Execute through worker pool and dependency manager\n  - Single dependency: Task B executes after Task A completes\n  - Multiple dependencies: Task C waits for both Task A and B to complete\n  - Dependency task timeout: Maximum time to wait for dependency completion (default 1 minute)\n\n### Dependency Examples\n\n**Failure handling strategies**:\n```go\n// Skip: Continue execution when dependency fails\ntaskC, _ := scheduler.Add(\"0 3 * * *\", func() error {\n    fmt.Println(\"Generating report...\")\n    return nil\n}, \"Report generation\", []Wait{\n    {ID: taskA, State: Skip},  // Skip when taskA fails\n    {ID: taskB, State: Stop},  // Stop when taskB fails (default)\n})\n```\n\n**Custom timeout**:\n```go\n// Set independent wait time for each dependency\ntaskC, _ := scheduler.Add(\"0 3 * * *\", func() error {\n    fmt.Println(\"Generating report...\")\n    return nil\n}, \"Report generation\", []Wait{\n    {ID: taskA, Delay: 30 * time.Second},  // Wait 30 seconds\n    {ID: taskB, Delay: 45 * time.Second},  // Wait 45 seconds\n})\n```\n\n**Combined usage**:\n```go\n// Combine failure strategies with custom timeout\ntaskC, _ := scheduler.Add(\"0 3 * * *\", func() error {\n    fmt.Println(\"Generating report...\")\n    return nil\n}, \"Report generation\", []Wait{\n    {ID: taskA, Delay: 30 * time.Second, State: Skip},\n    {ID: taskB, Delay: 45 * time.Second, State: Stop},\n})\n```\n\n### Task Status\n```go\nconst (\n    TaskPending     // Waiting\n    TaskRunning     // Running \n    TaskCompleted   // Completed\n    TaskFailed      // Failed / Timeout\n)\n```\n\n## Timeout Mechanism\nWhen execution time exceeds the set `Delay`:\n- Interrupts task execution\n- Triggers `OnDelay` function (if set)\n- Logs timeout\n- Continues with next schedule\n\n### Features\n- Timeout implemented using `context.WithTimeout`\n- Timeout doesn't affect other task execution\n- If action completes before timeout, timeout won't trigger\n\n## Upcoming Features\n\n### Enhanced Task Dependencies\n\n- Status callbacks: Add `OnTimeout` and `OnFailed` callback functions for monitoring and responding to dependency task exception states\n\n### Task Completion Trigger Refactor\n\n- Event-driven: Replace current polling with fully `channel`-based approach to reduce CPU usage\n- Dependency awakening: Implement active notification mechanism when dependency tasks complete, eliminating ineffective polling checks\n\n## License\n\nThis project is licensed under [MIT](LICENSE).\n\n## Star\n\n[![Star](https://api.star-history.com/svg?repos=pardnchiu/go-cron\u0026type=Date)](https://www.star-history.com/#pardnchiu/go-cron\u0026Date)\n\n## Author\n\n\u003cimg src=\"https://avatars.githubusercontent.com/u/25631760\" align=\"left\" width=\"96\" height=\"96\" style=\"margin-right: 0.5rem;\"\u003e\n\n\u003ch4 style=\"padding-top: 0\"\u003e邱敬幃 Pardn Chiu\u003c/h4\u003e\n\n\u003ca href=\"mailto:dev@pardn.io\" target=\"_blank\"\u003e\n  \u003cimg src=\"https://pardn.io/image/email.svg\" width=\"48\" height=\"48\"\u003e\n\u003c/a\u003e \u003ca href=\"https://linkedin.com/in/pardnchiu\" target=\"_blank\"\u003e\n  \u003cimg src=\"https://pardn.io/image/linkedin.svg\" width=\"48\" height=\"48\"\u003e\n\u003c/a\u003e\n\n***\n\n©️ 2025 [邱敬幃 Pardn Chiu](https://pardn.io)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpardnchiu%2Fgo-cron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpardnchiu%2Fgo-cron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpardnchiu%2Fgo-cron/lists"}