ryacron 0.1.0

A YAML-driven local cron runner with a Cargo Lambda executor
Documentation
# ryacron

`ryacron` is a Rust-based cron runner inspired by [`yacron`](https://github.com/gjcarneiro/yacron).

The current MVP focuses on a practical local use case: acting as a lightweight EventBridge emulator that invokes Cargo Lambda functions on a cron schedule.

## Status

This project is intentionally small for now.

- YAML-driven job definitions
- Global timezone per config file
- 6-field cron expressions via `tokio-cron-scheduler`
- Cargo Lambda execution backend
- Payload from file or generated EventBridge-like event
- Per-job timeout
- Per-job max concurrent runs with skip-on-limit behavior

The long-term direction is to keep the project name and config model generic while allowing more execution backends in the future.

## Installation

```bash
cargo build
```

## Usage

Run the scheduler with a YAML config file:

```bash
cargo run -- run --config ./ryacron.yaml
```

If you already built the binary:

```bash
./target/debug/ryacron run --config ./ryacron.yaml
```

The process keeps running until you stop it with `Ctrl-C`.

## Configuration

Example:

```yaml
timezone: Asia/Tokyo

jobs:
  - name: batch_job_a
    schedule: "0 * * * * *"
    function: batch_job_q
    payload:
      file: examples/eventbridge.json
    timeout_seconds: 600
    max_concurrent_runs: 1

  - name: batch_job_b
    schedule: "0 */5 * * * *"
    function: batch_job_b
    payload:
      generate_eventbridge_scheduled_event: true
    timeout_seconds: 600
    max_concurrent_runs: 5
```

### Top-level fields

- `timezone`: IANA timezone name such as `Asia/Tokyo` or `UTC`
- `jobs`: list of scheduled jobs

### Job fields

- `name`: human-readable job name
- `schedule`: cron expression in `sec min hour dom mon dow` format
- `function`: Cargo Lambda function name passed to `cargo lambda invoke`
- `payload`: optional payload source
- `timeout_seconds`: optional timeout in seconds
- `max_concurrent_runs`: optional positive integer, defaults to `1`

### Payload modes

`payload` may specify exactly one of the following:

```yaml
payload:
  file: path/to/event.json
```

or

```yaml
payload:
  generate_eventbridge_scheduled_event: true
```

If `payload` is omitted, `ryacron` invokes the function without `--data-file`.

## Concurrency control

`max_concurrent_runs` controls how many invocations of the same job may run at once.

- If omitted, the default is `1`
- If the job is already running `max_concurrent_runs` times, the next scheduled invoke is skipped
- `1` matches the old "no overlap" behavior

Example:

```yaml
jobs:
  - name: batch_job
    schedule: "0 * * * * *"
    function: batch-job
    max_concurrent_runs: 5
```

In this example, up to 5 concurrent `cargo lambda invoke` processes may run for `batch_job`. If 5 are already running, the next tick is skipped.

## Cron format

`ryacron` currently requires exactly 6 cron fields:

```text
sec min hour day-of-month month day-of-week
```

Examples:

- `"0 * * * * *"`: every minute
- `"0 */5 * * * *"`: every 5 minutes
- `"30 0 9 * * 1-5"`: 09:00:30 on weekdays

5-field cron expressions are rejected in the current MVP.

## EventBridge-like generated payload

When `generate_eventbridge_scheduled_event: true` is used, `ryacron` generates a minimal event payload with these fields:

- `id`
- `time`
- `source`
- `detail-type`
- `resources`
- `detail`

This is meant for local development and testing, not strict AWS EventBridge parity.

## Validation rules

At startup, `ryacron` validates:

- YAML syntax
- timezone value
- cron format
- payload shape
- payload file existence
- `max_concurrent_runs >= 1`

Invalid configuration causes startup to fail with a non-zero exit code.

## Logging behavior

The scheduler writes simple human-readable logs to standard output and standard error, including:

- scheduler start and stop
- job start
- job success or failure
- timeout
- overlap skip

## Current limitations

- only one executor backend: Cargo Lambda CLI
- no hot reload
- no separate `validate` command yet
- no per-job timezone
- no persistent execution history
- no strict `yacron` compatibility guarantee

## Development

Format and test locally:

```bash
cargo fmt
cargo test
```

Show CLI help:

```bash
cargo run -- --help
```

## License

This project is licensed under the terms of the [LICENSE](LICENSE) file.