# Project Vision

**This document is intended for developers to understand the flow of the module and be able to help out with
its development. Features and usage may change before its release.**

## Task Types

Tasks are scheduled within the config file, `Config\Tasks.php`, within the `init()` method: 

```php
public function init(Scheduler $schedule)
{
	$schedule->command('foo:bar')->nightly();
}
``` 

There are 5 types of tasks: 

1. Commands. These are CLI commands that are defined by the name defined within their file, like `migrate:create`.

```php
	$schedule->command('foo:bar')->nightly();
``` 

2. Shell commands. These are passed to the system through `exec()` or `shell()`. Need to determine what makes 
sense here. 

```php
	$schedule->shell('cp foo bar')->daily()->at('11:00 pm');
``` 

3. Closures. Anonymous functions can be used to define the action to take, also.

```php
	$schedule->call(function() { 
		// do something.... 
	})->mondays();
```

4. Events. These trigger pre-defined framework [Events](https://codeigniter4.github.io/CodeIgniter4/extending/events.html)
which allows for more dynamic actions to take place from a single Task.

```php
	$schedule->event('reminders')->weekdays()->at('9:00 am');
```

5. URL. These access a remote URL and are handy for interacting with other APIs or coordinating tasks across servers.

```php
	$schedule->url('https://example.com/api/sync_remote_db')->environments('production')->everyTuesday(););
```

> Note that URL Tasks perform a simple GET request; should you need more involved remote calls (like authentication)
they should be written into a separate command.

## Scheduling Tasks

Tasks are scheduled via fluent commands that allow chaining commands together. Some examples of available methods
would be: 

- `cron('/5 * * * *'')` specifies the exact cron syntax to use.
- `daily()` which runs every day at midnight. Optionally pass a time as the only argument, ie. `04:00 am`
- `weekdays()` runs M-F at midnight. Optionally pass a time as the only argument, ie. `04:00 am` 
- `weekends()` runs on Saturday and Sunday at midnight. Optionally pass a time as the only argument, ie. `04:00 am`
- `mondays()` runs every Monday at midnight. Optionally pass a time as the only argument, ie. `04:00 am`
- `everyMinute()`, `everyFiveMinutes()`, allows scheduling some common intervals
- `hourly()` runs the task at the top of every hour
- `environments()` specifies one or more environments the tasks should run in
- `alias()` specifies an alias that the script can be called by, useful when manually running the task. 

## How CRON interacts with the scheduler

In order to have the scheduler work, a cronjob needs to be setup on the server to run every minute against a
command we'll need to create: 

```
* * * * * cd /path-to-your-project && php spark tasks:run
```

## Other classes

The following classes are anticipated to be needed for the main process flow:

**TaskRunner** is called by the main command and handles actually determining which tasks to run and 
running all of the commands.

**Scheduler** is passed into the `init()` method of the config class and handles generating the crontab formats
for all tasks. It houses the commands that are called when scheduling tasks. 

**Task** represents a single task that should be scheduled. These are generated by the Scheduler and passed
to the TaskRunner when they're ready to be run. 

**CronExpression** understands how to interpret a raw crontab expression (* * * * *) and determine if the task 
should run now, as well as provide future/past dates it would run. 

## Commands

In addition to the core functionality, the following features will be availble by commands to help developers:

**tasks:run foo:bar** an optional flag, `--task` can be set to define a single task that should be run right now.
It can take either the name of a command one is associated with, or by the `alias` defined in the setup.

**tasks:list** generates a table with all tasks and the last and next times it is scheduled to run

**tasks::disable** can disable a job from running until `tasks:enable`  is called on it again. Useful
on production servers when something is going wrong. Likely stores a json file in `/writable` to maintain state

**tasks::performance** generates a table to display performance information about all of the last runs. 
See https://github.com/codestudiohq/laravel-totem for inspiration, though we're doing it on the CLI.

## Notifications

The schedular should also provide a few different ways to return information about the jobs. I envision the 
following methods to start: 

**logs** - simply logs the runtime and performance information. Would be nice to do this in a separate log file.

**email** - can notify one of more people of the performance of a single task, or a daily summary of all tasks
at a specified time of day. This would basically be a provided cron task that could be scheduled. So - would 
need a command. Should display list of tasks ran, the time they ran, whether there were errors or not, and 
performance information.  
