npm package: @nhtio/adonis-milicron
Description: A simple cron daemon for AdonisJS
Author: Jak Giveon
Latest version: 1.20250618.0

# Adonis Milicron

A simple cron daemon for Adonis

## Supported cron expressions

### Crontab format

```text
  *    *    *    *    *    *    *
  ┬    ┬    ┬    ┬    ┬    ┬    ┬
  │    │    │    │    │    │    |
  │    │    │    │    │    │    └ day of week (0 - 7, 1L - 7L) (0 or 7 is Sun)
  │    │    │    │    │    └───── month (1 - 12)
  │    │    │    │    └────────── day of month (1 - 31, L)
  │    │    │    └─────────────── hour (0 - 23)
  │    │    └──────────────────── minute (0 - 59)
  |    └───────────────────────── second (0 - 59, optional)
  └────────────────────────────── millisecond (0 - 999, optional)*
 ```

**Important Note**: While the millisecond field accepts values of 0-999, the resolution of the cron daemon is limited to 10ms, meaning that the job may trigger up to 10ms before or 10ms after the expressions's defined time.

Additionally, the library also accepts mixed use of ranges and range increments (except for `W`). The parsing on the [cron-parser](https://www.npmjs.com/package/cron-parser) library, with modifications to allow supporting of milisecond expressions.

#### Examples

* `* * * * * * *` - Every 10ms
* `*/2 * * * * * *` - Every 10ms (due to the 10ms resolution)
* `*/100 * * * * *` - Every 100ms
* `0 * * * * * *` - Every second
* `0 0 * * * * *` - Every minute

For more information on the crontab format, see [crontab.guru](https://crontab.guru/) or [cronjob.xyz](https://cronjob.xyz/).
Note that these don't accept the exact same syntax as this library, as they do not accept the millisecond or seconds fields.

### Crontab aliases

* `@yearly` - Once a year, at midnight on the morning of January 1st
* `@monthly` - Once a month, at midnight on the morning of the first day of the month
* `@weekly` - Once a week, at midnight on Sunday morning
* `@daily` - Once a day, at midnight
* `@hourly` - Once an hour, at the beginning of the hour

### Unix Timestamp (seconds)

A unix timestamp in seconds can be used to specify a single time to run the job.
**Important Note**: It is highly recommended to use the `$once` method with unix timestamps instead of `$on` in order to clear the callback after the job has run.

## Getting Started

### Installation

Install the package using your preferred package manager:

```bash
npm install @nhtio/adonis-milicron
```

Run the Adonis configuration command to set up the package:

```bash
node ace configure @nhtio/adonis-milicron
```

## Accessing the Cron Daemon

You can access the cron daemon through one of the following methods:

### 1. As an Importable Service

```typescript
import cron from '@nhtio/adonis-milicron/services/main';

// Example usage
cron.$on('* * * * *', () => {
  // this runs once per minute
})
```

### 2. As an Attribute of the Application

```typescript
import { default as app } from "@adonisjs/core/services/app";

// Access the event bus
cron.$on('* * * * *', () => {
  // this runs once per minute
})
```

### 3. Using Container Services

```typescript
import { default as app } from "@adonisjs/core/services/app";

// Resolve the event bus from the IoC container
const cron = await app.container.make('cron');
cron.$on('* * * * *', () => {
  // this runs once per minute
})
```

## Using

### Instance Methods

| Method                           | Description                                                                                                                                                                                                               | Documentation                                                                                          |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `$on`                            | Adds a new cron job to the daemon. Uses [EventEmitter.on](https://nodejs.org/docs/latest-v16.x/api/events.html#emitteroneventname-listener) under the hood                                                                | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#_on)                               |
| `$once`                          | Adds a new cron job to the daemon, but only runs it once. Uses [EventEmitter.once](https://nodejs.org/docs/latest-v16.x/api/events.html#emitteronceeventname-listener) under the hood                                     | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#_once)                             |
| `$off`                           | Removes a cron job from the daemon. Uses [EventEmitter.off](https://nodejs.org/docs/latest-v16.x/api/events.html#emitteroffeventname-listener) under the hood                                                             | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#_off)                              |
| `$clear`                         | Removes all callbacks from either a specific crontab or the entire daemon. Uses [EventEmitter.removeAllListeners](https://nodejs.org/docs/latest-v16.x/api/events.html#emitterremovealllistenerseventname) under the hood | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#_clear)                            |
| `start`                          | Starts the daemon if not already started.                                                                                                                                                                                 | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#start)                             |
| `stop`                           | Stops the daemon if not already stopped.                                                                                                                                                                                  | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#stop)                              |
| `restart`                        | Stops and starts the daemon.                                                                                                                                                                                              | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#restart)                           |
| `crontabMatchesDateTime`         | Checks if a crontab expression matches a given Luxon DateTime object                                                                                                                                                      | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#crontabMatchesDateTime)            |
| `getNextRunTimeForCrontab`       | Calculate the next run time for a crontab expression                                                                                                                                                                      | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#getnextruntimeforcrontab-1)        |
| `getNextRunTimeForParsedCrontab` | Calculate the next run time for a parsed crontab expression                                                                                                                                                               | [Documentation](https://millicron.nht.io//api/classes/MilliCron.html#getnextruntimeforparsedcrontab-1) |
| `getParsedCronExpression`        | Returns either a Luxon DateTime object or a [CronTabObject](https://millicron.nht.io/api/interfaces/CronTabObject.html) with the matching configuration.                                                                  | [Documentation](https://millicron.nht.io/api/classes/MilliCron.html#getParsedCronExpression)           |

### Instance Properties

| Property  | Type                   | Description                                     |
| --------- | ---------------------- | ----------------------------------------------- |
| `running` | **readonly** `boolean` | Whether or not the daemon is currently running. |

## FAQ's

**Q: Why is the resolution limited to 10ms?**
This is mostly a limitation of the `setTimeout` function which is used to handle the `ticks`. As noted in [MDN's Documentation](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified), most browsers will enforce a minimum timeout of 4ms once a nested call to `setTimeout` has been scheduled 5 times.
Ticks can also be delayed if the OS / browser is busy with other tasks. While there can be cases where 10ms is not sufficient, it is a reasonable compromise between performance and accuracy.

## Credits and Acknowledgements

This library leverages the capabilities of the [Luxon](https://moment.github.io/luxon/) library for proficient parsing and matching of date and time. The foundation of the cron parsing functionality is built upon the [cron-parser](https://www.npmjs.com/package/cron-parser) library, albeit with custom modifications to accommodate millisecond expressions. The design and functionality of this library owe a significant debt to the inspiration derived from [node-cron](https://www.npmjs.com/package/cron).

---

Adonis Milicron is a commercial work product released under the MIT License and is provided as-is with no warranty or guarantee of support.

Copyright © 2025-present New Horizon Technology LTD