Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.6.3
- Support `ScheduledTask` management. see: example/jobs.dart.

## 0.6.2

- Added support for intervals like `1-12/2`. [#55](https://github.com/agilord/cron/pull/55) by [ysahn-aplayz](https://github.com/ysahn-aplayz)
Expand Down
124 changes: 124 additions & 0 deletions example/jobs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import 'dart:async';

import 'package:cron/cron.dart';

enum JobAction { run, pause, stop, delete }

enum JobTime {
hourly(expr: '0 * * * *'),
daily(expr: '0 0 * * *'),
weekly(expr: '0 0 * * 0'),
monthly(expr: '0 0 1 * *'),
yearly(expr: '0 0 1 1 *'),
midday12t(expr: '0 12 * * *'),
midday13t(expr: '0 13 * * * '),
afternoon15t(expr: '0 15 * * * '),
afternoon16t(expr: '0 16 * * * '),
every1mins(expr: '*/1 * * * *'),
every2mins(expr: '*/2 * * * *'),
every3mins(expr: '*/3 * * * *'),
every5mins(expr: '*/5 * * * *'),
expression(expr: '0 * * * *'),
;

final String expr;
const JobTime({
required this.expr,
});
}

class Job {
JobTime time;
JobAction action;
String name;
String id;

Job(
{required this.action,
required this.time,
required this.name,
required this.id});

void cancel() {
action = JobAction.stop;
print('job closed.');
}

Job call() {
print('begin:${DateTime.now()}');

Future.delayed(Duration(seconds: 5)).then((value) {
print('action:$action, name:$name');
print('__end:${DateTime.now()}');
});

return this;
}
}

void main() {
final jobName = 'jobTest';
final jobId = 'job1234';

final task = Job(
action: JobAction.run,
time: JobTime.every1mins,
name: jobName,
id: jobId,
);

final cron = Cron();
final schedule = Schedule.parse(task.time.expr)..name = jobId;

// ignore: implicit_call_tearoffs
cron.schedule(schedule, task); // append

print('startup, state:${task.action}, name:${task.name}, ${DateTime.now()}');
// no.1, runAt, 1mins = 60secs
// no.2, runAt, 2mins
Future.delayed(Duration(seconds: 70)).then((value) {
task.action = JobAction.pause;
task.name = jobName + task.action.name.toUpperCase();
});

// no.3, runAt, 3mins
Future.delayed(Duration(seconds: 130)).then((value) {
final idx = cron.indexWhere((e) => e.schedule.name == jobId);
print('find jobId:$jobId, index:$idx, ${DateTime.now()}');

if (idx != -1) {
task.action = JobAction.run;
task.name = jobName + task.action.name.toUpperCase();
task.name += '_UPDATE';
task.time = JobTime.every2mins;

final sched = Schedule.parse(task.time.expr);
// ignore: implicit_call_tearoffs
final st = cron.schedule(sched, task, false); // not append
cron.updateAt(idx, st);
}
});

// no.4, RunAt, 6mins
Future.delayed(Duration(minutes: 6)).then((value) {
final count = cron.count;
if (count > 0) {
task.action = JobAction.delete;
task.name = jobName + task.action.name.toUpperCase();
task.name += '_DELETE';

final len1 = cron.count;
cron.removeAt(0);
final len2 = cron.count;
print('remove index:0, length $len1 to $len2. ${DateTime.now()}');
}
});

// no.5, 10mins after close.
Future.delayed(Duration(minutes: 10)).then((value) {
print('shutdown. ${DateTime.now()}');
cron.close().then((value) {
task.cancel();
});
});
}
46 changes: 41 additions & 5 deletions lib/cron.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,28 @@ abstract class Cron {
/// A cron-like time-based job scheduler.
factory Cron() => _Cron();

/// Schedules a [task] running specified by the [schedule].
ScheduledTask schedule(Schedule schedule, Task task);
/// Schedules a [task] running specified by the [schedule], if [append].
ScheduledTask schedule(Schedule schedule, Task task, [bool append = false]);

/// Closes the cron instance and doesn't accept new tasks anymore.
Future close();

/// Update ScheduledTask [st] at position [index] in this list _schedules.
void updateAt(int index, ScheduledTask st) {}

/// Remove the ScheduledTask at position [index] from list _schedules.
void removeAt(int index) {}

/// The first index in the list _schedules if [test] is true,
/// if not found returns -1.
/// ```dart
/// // search schedule name = 'sched1234' in cron instance.
/// final index = cron.indexWhere((e) => e.schedule.name == 'sched1234');
/// ```
int indexWhere(bool Function(ScheduledTask e) test, [int start = 0]) => -1;

/// the number of ScheduledTask in the list _schedules.
int get count => 0;
}

/// The cron schedule.
Expand All @@ -47,6 +64,9 @@ class Schedule {
/// The weekdays a Task should be started.
final List<int>? weekdays;

/// extra data, schedule name
late String name = '';

/// Test if this schedule should run at the specified time.
bool shouldRunAt(DateTime time) {
if (seconds?.contains(time.second) == false) return false;
Expand Down Expand Up @@ -168,11 +188,27 @@ class _Cron implements Cron {
final _schedules = <_ScheduledTask>[];

@override
ScheduledTask schedule(Schedule schedule, Task task) {
int get count => _schedules.length;

@override
int indexWhere(bool Function(ScheduledTask) test, [int start = 0]) =>
_schedules.indexWhere(test, start);

@override
void removeAt(int index) => _schedules.removeAt(index);

@override
void updateAt(int i, ScheduledTask st) =>
_schedules[i] = st as _ScheduledTask;

@override
ScheduledTask schedule(Schedule schedule, Task task, [bool append = true]) {
if (_closed) throw Exception('Closed.');
final st = _ScheduledTask(schedule, task);
_schedules.add(st);
_scheduleNextTick();
if (append) {
_schedules.add(st);
_scheduleNextTick();
}
return st;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/constraint_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ List<int>? parseConstraint(dynamic constraint) {
/// format and cannot be parsed or processed.
class ScheduleParseException extends FormatException {
/// Creates a new `FormatException` with an optional error [message].
ScheduleParseException([String message = '']) : super(message);
ScheduleParseException([super.message]);
}
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: cron
description: A time-based job scheduler similar to cron. Run tasks periodically at fixed times or intervals.
version: 0.6.2
version: 0.6.3
repository: https://github.com/agilord/cron

topics:
Expand All @@ -11,7 +11,7 @@ topics:
- cron-time

environment:
sdk: '>=2.12.0 <4.0.0'
sdk: '>=2.17.0 <4.0.0'

dependencies:
clock: ^1.1.1
Expand Down