{"id":19608434,"url":"https://github.com/rafaeljesus/crony","last_synced_at":"2025-04-27T20:32:49.388Z","repository":{"id":61627780,"uuid":"88436682","full_name":"rafaeljesus/crony","owner":"rafaeljesus","description":"Cron scheduler as a service :clock530: ","archived":false,"fork":false,"pushed_at":"2017-09-19T14:31:50.000Z","size":7822,"stargazers_count":10,"open_issues_count":2,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-05T03:22:21.231Z","etag":null,"topics":["cron","go","microservices","server"],"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/rafaeljesus.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}},"created_at":"2017-04-16T19:16:18.000Z","updated_at":"2024-05-08T01:03:26.000Z","dependencies_parsed_at":"2022-10-18T17:45:24.354Z","dependency_job_id":null,"html_url":"https://github.com/rafaeljesus/crony","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaeljesus%2Fcrony","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaeljesus%2Fcrony/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaeljesus%2Fcrony/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaeljesus%2Fcrony/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rafaeljesus","download_url":"https://codeload.github.com/rafaeljesus/crony/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251204651,"owners_count":21552261,"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","go","microservices","server"],"created_at":"2024-11-11T10:15:20.597Z","updated_at":"2025-04-27T20:32:49.164Z","avatar_url":"https://github.com/rafaeljesus.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Crony :clock530:\n\n* All the flexibility and power of Cron as a Service.\n* Simple REST protocol, integrating with a web application in a easy and straightforward way.\n* No more wasting time building and managing scheduling infrastructure.\n\n## Basic Concepts\nCrony works by calling back to your application via HTTP GET according to a schedule constructed by you or your application.\n\n## Setup\nEnv vars\n```bash\nexport DATASTORE_URL=\"postgresql://postgres@localhost/crony?sslmode=disable\"\nexport PORT=3000\n```\n\n```sh\nmkdir -p $GOPATH/src/github.com/rafaeljesus\ncd $GOPATH/src/github.com/rafaeljesus\ngit clone https://github.com/rafaeljesus/crony.git\ncd crony\nmake all\n```\n\n## Running server\n```\n./dist/crony\n# =\u003e Starting Crony at port 3000\n```\n\n## Authentication\nThis API does not ship with an authentication layer. You **should not** expose the API to the Internet. This API should be deployed behind a firewall, only your application servers should be allowed to send requests to the API.\n\n## API Endpoints\n- [`GET` /health](#get-health) - Get application health\n- [`GET` /events](#get-events) - Get a list of scheduled events\n- [`POST` /events](#post-events) - Create a event\n- [`GET` /events/:id](#get-eventsid) - Get a single event\n- [`DELETE` /events/:id](#delete-eventsid) - Delete a event\n- [`PATCH` /events/:id](#patch-eventsid) - Update a event\n\n### API Documentation\n#### `GET` `/events`\nGet a list of available events.\n- Method: `GET`\n- Endpoint: `/events`\n- Responses:\n    * 200 OK\n    ```json\n    [\n       {\n          \"id\":1,\n          \"url\":\"your-api/job\",\n          \"expression\": \"0 5 * * * *\",\n          \"status\": \"active\",\n          \"max_retries\": 2,\n          \"retry_timeout\": 3,\n          \"created_at\": \"2016-12-10T14:02:37.064641296-02:00\",\n          \"updated_at\": \"2016-12-10T14:02:37.064641296-02:00\"\n       }\n    ]\n    ```\n    - `id` is the id of the event.\n    - `url`: is the url callback to called.\n    - `expression`: is cron expression format.\n    - `status`: tell if the event is active or paused.\n    - `max_retries`: the number of attempts to send event.\n    - `retry_timeout`: is the retry timeout.\n\n#### `POST` `/events`\nCreate a new event.\n- Method: `POST`\n- Endpoint: `/events`\n- Input:\n    The `Content-Type` HTTP header should be set to `application/json`\n\n    ```json\n   {\n      \"url\":\"your-api/job\",\n      \"expression\": \"0 5 * * * *\",\n      \"status\": \"active\",\n      \"max_retries\": 2,\n      \"retry_timeout\": 3,\n   }\n    ```\n- Responses:\n    * 201 Created\n    ```json\n   {\n      \"url\":\"your-api/job\",\n      \"expression\": \"0 5 * * * *\",\n      \"status\": \"active\",\n      \"max_retries\": 2,\n      \"retry_timeout\": 3,\n      \"updated_at\": \"2016-12-10T14:02:37.064641296-02:00\",\n      \"created_at\": \"2016-12-10T14:02:37.064641296-02:00\"\n   }\n    ```\n    * 422 Unprocessable entity:\n    ```json\n    {\n      \"status\":\"invalid_event\",\n      \"message\":\"\u003creason\u003e\"\n    }\n    ```\n    * 400 Bad Request\n    ```json\n    {\n      \"status\":\"invalid_json\",\n      \"message\":\"Cannot decode the given JSON payload\"\n    }\n    ```\n    Common reasons:\n    - the event job already scheduled. The `message` will be `Event already exists`\n    - the expression must be crontab format.\n    - the retry must be between `0` and `10`\n    - the status must be `active` or `incative`\n\n#### `GET` `/events/:id`\nGet a specific event.\n- Method: `GET`\n- Endpoint: `/events/:id`\n- Responses:\n    * 200 OK\n    ```json\n   {\n      \"url\":\"your-api/job\",\n      \"expression\": \"0 5 * * * *\",\n      \"status\": \"active\",\n      \"max_retries\": 2,\n      \"retry_timeout\": 3,\n      \"updated_at\": \"2016-12-10T14:02:37.064641296-02:00\",\n      \"created_at\": \"2016-12-10T14:02:37.064641296-02:00\"\n   }\n    ```\n    * 404 Not Found\n    ```json\n    {\n      \"status\":\"event_not_found\",\n      \"message\":\"The event was not found\"\n    }\n    ```\n\n#### `DELETE` `/events/:id`\nRemove a scheduled event.\n- Method: `DELETE`\n- Endpoint: `/events/:id`\n- Responses:\n    * 200 OK\n    ```json\n    {\n      \"status\":\"event_deleted\",\n      \"message\":\"The event was successfully deleted\"\n    }\n    ```\n    * 404 Not Found\n    ```json\n    {\n      \"status\":\"event_not_found\",\n      \"message\":\"The event was not found\"\n    }\n    ```\n\n#### `PATCH` `/events/:id`\nUpdate a event.\n- Method: `PATCH`\n- Endpoint: `/events/:id`\n- Input:\n    The `Content-Type` HTTP header should be set to `application/json`\n\n    ```json\n   {\n      \"expression\": \"0 2 * * * *\"\n   }\n    ```\n- Responses:\n    * 200 OK\n    ```json\n   {\n      \"url\":\"your-api/job\",\n      \"expression\": \"0 2 * * * *\",\n      \"status\": \"active\",\n      \"max_retries\": 2,\n      \"retry_timeout\": 3,\n      \"updated_at\": \"2016-12-10T14:02:37.064641296-02:00\",\n      \"created_at\": \"2016-12-10T14:02:37.064641296-02:00\"\n   }\n    ```\n    * 404 Not Found\n    ```json\n    {\n      \"status\":\"event_not_found\",\n      \"message\":\"The event was not found\"\n    }\n    ```\n    * 422 Unprocessable entity:\n    ```json\n    {\n      \"status\":\"invalid_json\",\n      \"message\":\"Cannot decode the given JSON payload\"\n    }\n    ```\n    * 400 Bad Request\n    ```json\n    {\n      \"status\":\"invalid_event\",\n      \"message\":\"\u003creason\u003e\"\n    }\n    ```\n\n## Cron Format\nThe cron expression format allowed is:\n\n|Field name| Mandatory?|Allowed values|Allowed special characters|\n|:--|:--|:--|:--|\n|Seconds      | Yes        | 0-59            | * / , -|\n|Minutes      | Yes        | 0-59            | * / , -|\n|Hours        | Yes        | 0-23            | * / , -|\n|Day of month | Yes        | 1-31            | * / , - ?|\n|Month        | Yes        | 1-12 or JAN-DEC | * / , -|\n|Day of week  | Yes        | 0-6 or SUN-SAT  | * / , - ?|\nmore details about expression format [here](https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format)\n\n## Contributing\n- Fork it\n- Create your feature branch (`git checkout -b my-new-feature`)\n- Commit your changes (`git commit -am 'Add some feature'`)\n- Push to the branch (`git push origin my-new-feature`)\n- Create new Pull Request\n\n## Badges\n[![CircleCI](https://circleci.com/gh/rafaeljesus/crony.svg?style=svg)](https://circleci.com/gh/rafaeljesus/crony)\n[![Go Report Card](https://goreportcard.com/badge/github.com/rafaeljesus/crony)](https://goreportcard.com/report/github.com/rafaeljesus/crony)\n[![](https://images.microbadger.com/badges/image/rafaeljesus/crony.svg)](https://microbadger.com/images/rafaeljesus/crony \"Get your own image badge on microbadger.com\")\n[![](https://images.microbadger.com/badges/version/rafaeljesus/crony.svg)](https://microbadger.com/images/rafaeljesus/crony \"Get your own version badge on microbadger.com\")\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaeljesus%2Fcrony","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaeljesus%2Fcrony","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaeljesus%2Fcrony/lists"}