Skip to content

Commit

Permalink
Merge pull request #18 from zhongwencool/bump-up-1.0.0
Browse files Browse the repository at this point in the history
Bump up 1.0.0
  • Loading branch information
zhongwencool authored Apr 29, 2024
2 parents 25aa584 + 8731460 commit 750115b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 41 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix:
otp: ['23.3.4', '24.0.3']
otp: ['24.3', '25.3', '26.2']
rebar3: ['3.20.0', '3.19.0']
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.otp}}
Expand All @@ -23,10 +23,10 @@ jobs:
- run: rebar3 as test ct -c
- run: rebar3 as test cover
- name: Generate code coverage report
if: matrix.otp == '24.0.3' && matrix.rebar3 == '3.20.0'
if: matrix.otp == '26.2' && matrix.rebar3 == '3.20.0'
run: rebar3 as test covertool generate
- name: Upload code coverage to Codecov
if: matrix.otp == '24.0.3' && matrix.rebar3 == '3.20.0'
if: matrix.otp == '26.2' && matrix.rebar3 == '3.20.0'
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
60 changes: 28 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,19 @@
[hex]: https://hex.pm/packages/ecron
[hex-img]: https://img.shields.io/hexpm/v/ecron.svg?style=flat

A lightweight/efficient cron-like job scheduling library for Erlang.
A lightweight and efficient cron-like job scheduling library for Erlang.

All ecron's jobs is assigned to one single gen_server process, just run as same as the [stdlib's timer](http://erlang.org/doc/man/timer.html).
## Overview
Ecron is designed to manage scheduled jobs within a single gen_server process, similar to the standard library's [stdlib's timer](http://erlang.org/doc/man/timer.html). It uses an ordered_set ETS table to organize jobs by the next run time, ensuring efficient execution. Unlike traditional cron, Ecoron does not poll the system every second, which reduces message overhead and process usage.

It organizes the jobs to be run in an ordered_set ets with the next time to run as key.
This way, you only need one process that calculates the time to wait until the next task should be executed,
then spawn the process to execute that task.
more detail see [Implementation](#Implementation).

`ecron` does not poll the system on a second-by-second basis like cron does.
The advantage of not doing this is to avoid lots of messages flying around.

All jobs are managed in one process, rather than running one job per process,
which saves lots of processes and avoids taking up a lot of memory.
After all, most of the time the process is waiting(do nothing but eat memory).

It offers:

* Both cron-like scheduling and interval-based scheduling.
* Well tested by [PropTest](https://github.com/proper-testing/proper) [![codecov](https://codecov.io/gh/zhongwencool/ecron/branch/master/graph/badge.svg?token=FI9WAQ6UG5)](https://codecov.io/gh/zhongwencool/ecron).
* Using gen_server timeout(`receive after`) at any given time (rather than reevaluating upcoming jobs every second/minute).
### Key Features
- Supports both cron-like and interval-based scheduling.
- Well-tested with [PropTest](https://github.com/proper-testing/proper) [![codecov](https://codecov.io/gh/zhongwencool/ecron/branch/master/graph/badge.svg?token=FI9WAQ6UG5)](https://codecov.io/gh/zhongwencool/ecron).
- Utilizes gen_server timeout mechanism for precise timing.
- Efficient process management, avoiding high memory usage.

You can find a collection of general practices in [Full Erlang Examples](https://github.com/zhongwencool/ecron/blob/master/examples/titan_erlang) and [Full Elixir Examples](https://github.com/zhongwencool/ecron/blob/master/examples/titan_elixir).

Expand All @@ -43,12 +35,14 @@ You can find a collection of general practices in [Full Erlang Examples](https:/
```elixir
# mix.exs
def deps do
[{:ecron, "~> 0.6"}]
[{:ecron, "~> 1.0.0"}]
end
```

## Basic Usage

Configure Ecoron in your sys.config file with timezone and job specifications:

```erlang
%% sys.config
[
Expand Down Expand Up @@ -89,14 +83,8 @@ You can find a collection of general practices in [Full Erlang Examples](https:/
* Global jobs depend on [global](http://erlang.org/doc/man/global.html), only allowed to be added statically, [check this for more detail](https://github.com/zhongwencool/ecron/blob/master/doc/global.md).

## Supervisor Tree Usage
`ecron` starts with a standalone process(`ecron_local`) to manage all jobs by default,
but you can also set up your own job management process for each application,
which has the advantage that you can precisely control its start time and stop timing.
This has the advantage that you can precisely control when it starts and when it stops.
The Jobs between various applications do not affect each other.

`ecron` must be included in your application's supervision tree.
All of your configuration is passed into the supervisor:
Ecron can be integrated into your application's supervision tree for better control over its lifecycle:
```erlang
%%config/sys.config
[{your_app, [{crontab_jobs, [
Expand Down Expand Up @@ -129,6 +117,8 @@ init(_Args) ->
```
## Advanced Usage
Ecron allows for advanced scheduling and manipulation of cron jobs:
```erlang
%% Same as: Spec = "0 * 0-5,18 * * 0-5",
Spec = #{second => [0],
Expand Down Expand Up @@ -156,7 +146,8 @@ EveryMFA = {io, format, ["Runs every 120 second.~n"]},
```
## Debug Support
There are some function to get information for debugging jobs.
Ecron provides functions to assist with debugging:
````erlang
1> ecron:deactivate(CrontabName).
ok
Expand Down Expand Up @@ -201,7 +192,9 @@ ok
}
````
## Implementation
The local_jobs workflow is as follows:
Ecron uses an efficient approach to manage job execution times and intervals:
1. The top supervisor `ecron_sup` starts firstly.
2. then `ecron_sup` starts a child `ecron`(gen_server worker).
3. `ecron` will look for configuration `{local_jobs, Jobs}` at initialization.
Expand Down Expand Up @@ -233,8 +226,9 @@ Additionally, you can use `ecron:statistic(Name)` to see the job's latest 16 res
[Check this for global_jobs workflow](https://github.com/zhongwencool/ecron/blob/master/doc/global.md#Implementation).
## Telemetry
Ecron publish events through telemetry, you can handle those events by [this guide](https://github.com/zhongwencool/ecron/blob/master/doc/telemetry.md),
such as you can monitor events dispatch duration and failures to create alerts which notify somebody.
Ecron publishes events through telemetry, allowing for monitoring and alerting,
You can handle those events by [this guide](https://github.com/zhongwencool/ecron/blob/master/doc/telemetry.md).
## CRON Expression Format
Expand Down Expand Up @@ -309,19 +303,21 @@ Entry | Description | Equivalent
## Intervals
You may also execute job at fixed intervals, starting at the time it's added or cron is run.
This is supported by formatting the cron spec like this:
Ecron also supports scheduling jobs at fixed intervals:
```shell
@every <duration>
```
For example, "@every 1h30m10s" would indicate a schedule that activates after 1 hour, 30 minutes, 10 seconds, and then every interval after that.
For example, @every 1h30m10s schedules a job to run every 1 hour, 30 minutes, and 10 seconds.
>Note: The interval doesn't take the job runtime into account.
>For example, if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
>it only has 2 minutes of idle time between each run.
## Test
This command will run property-based tests, common tests, and generate a coverage report with verbose output.
```shell
$ rebar3 do proper -c, ct -c, cover -v
```
4 changes: 2 additions & 2 deletions examples/titan_erlang/apps/titan/src/stateless_cron.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ add_every_4am_job() ->
%% by ecron:add_with_time/5
add_limited_start_end_time_job2() ->
MFA = {?MODULE, inspect, ["at minute 23 past every 2nd hour from 0 through 20."]},
Start = {{10, 0, 0}}, %% time or `unlimited`
Start = {10, 0, 0}, %% time or `unlimited`
End = unlimited, %% time or `unlimited`
ecron:add_with_time(make_ref(), "0 23 0-20/2 * * *", MFA, Start, End).

Expand Down Expand Up @@ -85,4 +85,4 @@ predict_datetime_by_spec(Spec, N) ->

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Debug Functions End
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 changes: 1 addition & 1 deletion src/ecron.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{application, ecron,
[{description, "cron-like/crontab job scheduling library"},
{vsn, "0.6.1"},
{vsn, "1.0.0"},
{registered, [ecron_sup, ecron_local, ecron_monitor]},
{mod, {ecron_app, []}},
{applications, [kernel, stdlib, telemetry]},
Expand Down
4 changes: 2 additions & 2 deletions src/ecron.erl
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
-type parse_error() ::
invalid_time | invalid_spec | month | day_of_month | day_of_week | hour | minute | second.

-type start_at() :: unlimited | calendar:datetime().
-type end_at() :: unlimited | calendar:datetime().
-type start_at() :: unlimited | calendar:time().
-type end_at() :: unlimited | calendar:time().
-type option() :: {singleton, boolean()} | {max_count, pos_integer() | unlimited}.
-type options() :: [option()].

Expand Down

0 comments on commit 750115b

Please sign in to comment.