{"id":19332167,"url":"https://github.com/4t145/tsuki-scheduler","last_synced_at":"2025-04-22T23:32:49.603Z","repository":{"id":242917173,"uuid":"810781355","full_name":"4t145/tsuki-scheduler","owner":"4t145","description":"A simple, light wight, composable and extensible scheduler for every runtime.","archived":false,"fork":false,"pushed_at":"2025-03-17T08:20:42.000Z","size":97,"stargazers_count":29,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T05:12:43.005Z","etag":null,"topics":["cron","rust","schedule","scheduler","time","timer"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4t145.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}},"created_at":"2024-06-05T10:47:02.000Z","updated_at":"2025-03-29T16:00:40.000Z","dependencies_parsed_at":"2024-06-25T09:02:14.009Z","dependency_job_id":null,"html_url":"https://github.com/4t145/tsuki-scheduler","commit_stats":null,"previous_names":["4t145/tsuki-scheduler"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Ftsuki-scheduler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Ftsuki-scheduler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Ftsuki-scheduler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4t145%2Ftsuki-scheduler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4t145","download_url":"https://codeload.github.com/4t145/tsuki-scheduler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250340536,"owners_count":21414569,"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","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","rust","schedule","scheduler","time","timer"],"created_at":"2024-11-10T02:44:17.413Z","updated_at":"2025-04-22T23:32:49.596Z","avatar_url":"https://github.com/4t145.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tsuki-Scheduler\n[![Crates.io Version](https://img.shields.io/crates/v/tsuki-scheduler)](https://crates.io/crates/tsuki-scheduler)\n![Release status](https://github.com/4t145/tsuki-scheduler/actions/workflows/test-and-release.yml/badge.svg)\n[![docs.rs](https://img.shields.io/docsrs/tsuki-scheduler)](https://docs.rs/tsuki-scheduler)\n\nA simple, light wight, composable and extensible scheduler for every runtime.\n```text\nScheduler = Schedule × Runtime\n```\n\n## Usage\n\nThis small crate can help you running tasks in \n\n- tokio\n- async-std\n- new thread\n- local\n- promise\n- and more as long as the way to create a task in this runtime is implemented.\n\nwith a combination of\n\n- cron schedule\n- once or periodically\n- after or before some time\n- utc date-time iterator\n- and more as long as it implement a trait `Schedule`.\n\nFor a more detailed document, check the [rust doc](https://docs.rs/tsuki-scheduler).\n\n```shell\ncargo add tsuki-scheduler\n```\n\nor \n\n```toml\ntsuki-scheduler = \"0.1\"\n```\n### Create scheduler\n```rust\nuse tsuki_scheduler::prelude::*;\nlet mut scheduler = Scheduler::new(Tokio);\nlet mut scheduler = Scheduler::new(AsyncStd);\nlet mut scheduler = Scheduler::new(Promise);\nlet mut scheduler = Scheduler::new(Thread);\n\n// or you may use the async wrapper\nlet mut scheduler_runner = AsyncSchedulerRunner::\u003cTokio\u003e::default();\nlet client = scheduler_runner.client();\n```\n\n### Compose schedules\nWhat if I want to create a very complex schedule like this:\n\n1. Firstly it will run at 10 seconds later.\n2. And then, it will run at every hour's 10th minute.\n3. Meanwhile, it will run every 80 minutes.\n4. Though, it won't run within 30 minutes after the last run.\n5. Finally, it will stop running after 100 days later.\n\nAnd you can actually do it:\n```rust\nuse tsuki_scheduler::prelude::*;\nuse chrono::TimeDelta;\n\nlet start_time = now() + TimeDelta::seconds(10);\nlet schedule = Once::new(start_time)\n    .then(\n        Cron::utc_from_cron_expr(\"00 10 * * * *\")\n            .expect(\"invalid cron\")\n            .or(Period::new(\n                TimeDelta::minutes(80),\n                start_time + TimeDelta::minutes(80),\n            ))\n            .throttling(TimeDelta::minutes(30)),\n    )\n    .before(start_time + TimeDelta::days(100));\n```\n\nFor some case you want to use a certain type for all schedule, you can use `Box\u003cdyn Schedule\u003e`, and there's a builder api for it.\n```rust\nuse tsuki_scheduler::prelude::*;\nuse chrono::{Utc, TimeDelta};\nlet cron_list = Vec::\u003cCron\u003cUtc\u003e\u003e::new();\n// add some cron expr\n\n// ...\n\n// build schedule\nlet start_time = now() + TimeDelta::seconds(10);\nlet mut schedule_builder = Once::new(start_time).dyn_builder()\n    .then(\n        Cron::utc_from_cron_expr(\"00 10 * * * *\")\n            .expect(\"invalid cron\")\n            .or(Period::new(\n                TimeDelta::minutes(80),\n                start_time + TimeDelta::minutes(80),\n            ))\n            .throttling(TimeDelta::minutes(30)),\n    )\n    .before(start_time + TimeDelta::days(100));\n// collect all cron expr\nschedule_builder = cron_list.into_iter().fold(schedule_builder, ScheduleDynBuilder::or);\nlet schedule = schedule_builder.build();\n\n```\n\n### Add executes and delete tasks\n```rust\nuse tsuki_scheduler::prelude::*;\nlet mut scheduler = Scheduler::new(Tokio);\nlet hello_tsuki_task = Task::new_async(\n    Cron::local_from_cron_expr(\"*/2 * * * * *\").unwrap(),\n    |\n        task_uid: TaskUid, \n        // you can extract any numbers of args as it can be extracted from struct `TaskRun`\n        // time: Dtu\n    | async move {\n        println!(\"Hello, {task_uid} tsuki!\");\n    },\n);\nlet id = TaskUid::uuid();\nscheduler.add_task(id, hello_tsuki_task);\nscheduler.execute_by_now();\nscheduler.delete_task(id);\n```\n\n### Manage the handles\nYou may ignore all the task handles, if you want to manage the handles, implement your own manager by implementing the trait `HandleManager`.\n\n### Async runtime\nIn a async runtime, you may spawn a task for scheduler to execute periodically driven by event loop. This crate provides an implementation, you can check the [example](examples/tokio.rs) for tokio runtime.\n\n## Feature flags\n|flag|description|\n|:---|:----------|\n|uuid|allow to create TaskUid by uuid-v4 |\n|cron|allow to create a schedule described by a cron expression |\n|tokio|enable tokio runtime |\n|async_std|enable async_std runtime |\n|thread|enable thread runtime |\n|promise|enable js promise runtime |\n|async-scheduler|a default async wrapper for async runtime|\n\n\n## Alternative crates\n* [`tokio-cron-scheduler`](https://github.com/mvniekerk/tokio-cron-scheduler)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4t145%2Ftsuki-scheduler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4t145%2Ftsuki-scheduler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4t145%2Ftsuki-scheduler/lists"}