angel_production 1.0.0

production #

Pub

Helpers for concurrency, message-passing, rotating loggers, and other production functionality in Angel.

Screenshot

This will become the de-facto way to run Angel applications in deployed environments, as it takes care of inter-isolate communication, respawning dead processes, and other housekeeping for you automatically.

Most users will want to use the Runner class.

Runner #

Runner is a utility, powered by package:args, that is intended to be the entry point of your application.

Instantiate it as follows, and your file will become a command-line executable that spawns multiple instances of your application:

import 'dart:async';
import 'dart:isolate';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_production/angel_production.dart';

main(List<String> args) => Runner('example', configureServer).run(args);

Future configureServer(Angel app) async {
  app.get('/', (req, res) => 'Hello, production world!');

  app.get('/crash', (req, res) {
    // We'll crash this instance deliberately, but the Runner will auto-respawn for us.
    Timer(const Duration(seconds: 3), Isolate.current.kill);
    return 'Crashing in 3s...';
  });
}

Runner will automatically re-spawn crashed instances, unless --no-respawn is passed. This can prevent your server from entirely going down at the first error, and adds a layer of fault tolerance to your infrastructure.

When combined with systemd, deploying Angel applications on Linux can be very simple.

Message Passing #

The Runner class uses package:pub_sub to coordinate message passing between isolates.

When one isolate sends a message, all other isolates will receive the same message, except for the isolate that sent it.

It is injected into your application's Container as pub_sub.Client, so you can use it as follows:

// Use the injected `pub_sub.Client` to send messages.
var client = app.container.make<pub_sub.Client>();

// We can listen for an event to perform some behavior.
//
// Here, we use message passing to synchronize some common state.
var onGreetingChanged = await client.subscribe('user_upgraded');
onGreetingChanged
    .cast<User>()
    .listen((user) {
      // Do something...
    });

Run-time Metadata #

At run-time, you may want to know information about the currently-running instance, for example, which number instance. For this, the InstanceInfo class is injected into each instance:

var instanceInfo = app.container.make<InstanceInfo>();
print('This is instance #${instanceInfo.id}');

Command-line Options #

The Runner class supplies options like the following:

Tobes-MacBook-Air:production thosakwe$ dart example/main.dart --help
____________   ________________________ 
___    |__  | / /_  ____/__  ____/__  / 
__  /| |_   |/ /_  / __ __  __/  __  /  
_  ___ |  /|  / / /_/ / _  /___  _  /___
/_/  |_/_/ |_/  ____/  /_____/  /_____/

A batteries-included, full-featured, full-stack framework in Dart.

https://angel-dart.github.io

Options:
-h, --help                    Print this help information.
    --[no-]respawn            Automatically respawn crashed application instances.
                              (defaults to on)

    --use-zone                Create a new Zone for each request.
    --quiet                   Completely mute logging.
    --ssl                     Listen for HTTPS instead of HTTP.
    --http2                   Listen for HTTP/2 instead of HTTP/1.1.
-a, --address                 The address to listen on.
                              (defaults to "127.0.0.1")

-j, --concurrency             The number of isolates to spawn.
                              (defaults to "4")

-p, --port                    The port to listen on.
                              (defaults to "3000")

    --certificate-file        The PEM certificate file to read.
    --certificate-password    The PEM certificate file password.
    --key-file                The PEM key file to read.
    --key-password            The PEM key file password.

1.0.0 #

  • Support SSL/HTTP2.
  • Support muting the logger via --quiet.

1.0.0-alpha.1 #

  • Import framework/http.

1.0.0-alpha #

  • Initial version.

example/main.dart

import 'dart:async';
import 'dart:isolate';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_production/angel_production.dart';
import 'package:pub_sub/pub_sub.dart' as pub_sub;

main(List<String> args) => Runner('example', configureServer).run(args);

Future configureServer(Angel app) async {
  // Use the injected `pub_sub.Client` to send messages.
  var client = app.container.make<pub_sub.Client>();
  var greeting = 'Hello! This is the default greeting.';

  // We can listen for an event to perform some behavior.
  //
  // Here, we use message passing to synchronize some common state.
  var onGreetingChanged = await client.subscribe('greeting_changed');
  onGreetingChanged
      .cast<String>()
      .listen((newGreeting) => greeting = newGreeting);

  // Add some routes...
  app.get('/', (req, res) => 'Hello, production world!');

  app.get('/404', (req, res) {
    res.statusCode = 404;
    return res.close();
  });

  // Create some routes to demonstrate message passing.
  app.get('/greeting', (req, res) => greeting);

  // This route will push a new value for `greeting`.
  app.get('/change_greeting/:newGreeting', (req, res) {
    greeting = req.params['newGreeting'] as String;
    client.publish('greeting_changed', greeting);
    return 'Changed greeting -> $greeting';
  });

  // The `Runner` helps with fault tolerance.
  app.get('/crash', (req, res) {
    // We'll crash this instance deliberately, but the Runner will auto-respawn for us.
    Timer(const Duration(seconds: 3), Isolate.current.kill);
    return 'Crashing in 3s...';
  });
}

Use this package as a library

1. Depend on it

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


dependencies:
  angel_production: ^1.0.0

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:angel_production/angel_production.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
76
Health:
Code health derived from static analysis. [more]
98
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
87
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, other

Primary library: package:angel_production/angel_production.dart with components: io, isolate.

Health suggestions

Fix lib/src/runner.dart. (-2.48 points)

Analysis of lib/src/runner.dart reported 5 hints:

line 59 col 7: DO use curly braces for all flow control structures.

line 61 col 7: DO use curly braces for all flow control structures.

line 63 col 7: DO use curly braces for all flow control structures.

line 65 col 7: DO use curly braces for all flow control structures.

line 253 col 9: DO use curly braces for all flow control structures.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev <3.0.0
angel_container ^1.0.0-alpha 1.0.4
angel_framework ^2.0.0-alpha 2.0.4+1
args ^1.0.0 1.5.2
io ^0.3.2 0.3.3
logging ^0.11.3 0.11.3+2
pub_sub ^2.0.0 2.3.0
Transitive dependencies
angel_http_exception 1.1.0
angel_model 1.0.3
angel_route 3.0.6
async 2.3.0
charcode 1.1.2
code_buffer 1.0.1
collection 1.14.12
combinator 1.1.0
convert 2.1.1
crypto 2.1.3
dart2_constant 1.0.2+dart2
file 5.0.10
http2 1.0.0
http_parser 3.1.3
http_server 0.9.8+3
intl 0.16.0
json_rpc_2 2.1.0
matcher 0.12.5
merge_map 1.0.2
meta 1.1.7
mime 0.9.6+3
mock_request 1.0.6
path 1.6.4
quiver 2.0.5
quiver_hashcode 2.0.0
source_span 1.5.5
stack_trace 1.9.3
stream_channel 2.0.0
string_scanner 1.0.5
term_glyph 1.1.0
tuple 1.0.2
typed_data 1.1.6
uuid 2.0.2
Dev dependencies
pedantic ^1.0.0 1.8.0+1