neat_periodic_task 1.0.0+2

Neat Periodic Task Scheduling #

When writing long-running processes such as a web-server in Dart it is often useful to run maintenance operations in a periodic background task. This package provides an auxiliary framework for reliably running such tasks.

Disclaimer: This is not an officially supported Google product.

Backup tasks, database maintenance operations, garbage collection of cloud storage, pre-computed data aggregations are often tasks that can't be done on-line every time a request arrives at a web-server. While doing the task more than once isn't a problem, it is wasteful to run it too often and could lead to performance degradation or an expensive cloud bill.

One solution is off-load such tasks to a clouding scheduling system similar to cron, but such services typically require out-of-band configuration. Further more, a scheduling service needs a way to trigger your task, requiring that the web server exposes a public web API for triggering the task.

However, if the web-server is a set of long-processes serving traffic, the web-server could simply run the task on a loop with a long delay. That is effectively what this package facilitates. Obviously, this package has few more tricks such as.

  • Run a periodic task on a loop.
  • Limit maximum run-time to prevent a hanging loop.
  • Retry failed task executions after a timeout.
  • Catch and log all exceptions/errors from the task.
  • (Optionally) prevent concurrent tasks using status in a storage service that supports optimistic concurrency (eg. Cloud Datastore, Google Cloud Storage).
  • Print log messages liveness monitoring of the periodic tasks.

Example #

import 'dart:io';
import 'package:neat_periodic_task/neat_periodic_task.dart';

void main() async {
  // Create a periodic task that prints 'Hello World' every 30s
  final scheduler = NeatPeriodicTaskScheduler(
    interval: Duration(seconds: 30),
    name: 'hello-world',
    timeout: Duration(seconds: 5),
    task: () async => print('Hello World'),
    minCycle: Duration(seconds: 5),
  );

  scheduler.start();
  await ProcessSignal.sigterm.watch().first;
  await scheduler.stop();
}

Monitoring #

When a NeatPeriodicTaskScheduler is created it is given a task name. When the scheduler is running the following log messages is written to package logging.

  • '### [ALIVE] neat-periodic-task: "<name>"', when task status is verified to be idle,
  • '### [START] neat-periodic-task: "<name>"', when task is started,
  • '### [FAILED] neat-periodic-task: "<name>"', when task has failed, and,
  • '### [FINISHED] neat-periodic-task: "<name>"', when task is finished.

To be alerted when a task consistently fails to run, it is sufficient to alert if the log message '### [ALIVE] neat-periodic-task: "<name>"' is absent from logs for more than 24 hours. This message is printed when the status is checked and the scheduler decided not to run the task because it was completely successfully less than interval time ago.

A simple robust monitoring strategy is to alert if the message '### [ALIVE] neat-periodic-task: "<name>"' have not occurred in 24 hours. This works regardless of the interval length, and will fire alerts even if the server fails to boot.

If the task is intended to run frequently it is also possible to monitor for '### [FINISHED] neat-periodic-task: "<name>"'. Simply alert if this message does not appear at-least once every 3 * interval.

v1.0.0+2 #

  • Relaxed dependency constraint on json_annotation to allow both version 2.0.0 and 3.0.0.

v1.0.0+1 #

  • Relaxed dependency constraints on retry to allow both 2.x and 3.x.

v1.0.0 #

  • Initial release.

example/main.dart

// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:async';
import 'dart:io';
import 'package:neat_periodic_task/neat_periodic_task.dart';

Future<void> main() async {
  // Create a periodic task that prints 'Hello World' every 30s
  final scheduler = NeatPeriodicTaskScheduler(
    interval: Duration(seconds: 30),
    name: 'hello-world',
    timeout: Duration(seconds: 5),
    task: () async => print('Hello World'),
    minCycle: Duration(seconds: 5),
  );

  scheduler.start();
  await ProcessSignal.sigterm.watch().first;
  await scheduler.stop();
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  neat_periodic_task: ^1.0.0+2

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:neat_periodic_task/neat_periodic_task.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
36
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
68
Learn more about scoring.

We analyzed this package on Sep 20, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.5.0
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:neat_periodic_task/neat_periodic_task.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
collection ^1.14.11 1.14.12
json_annotation >=2.0.0 <4.0.0 3.0.0
logging ^0.11.3+2 0.11.3+2
meta ^1.1.7 1.1.7
retry >=2.0.0 <4.0.0 3.0.0+1
slugid ^1.0.0 1.0.0+1
Transitive dependencies
charcode 1.1.2
convert 2.1.1
typed_data 1.1.6
Dev dependencies
build_runner ^1.3.1
build_verify ^1.1.1
json_serializable ^3.2.0
pedantic ^1.4.0
test ^1.5.1