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 ittakes 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 yourapplication:

  1. import 'dart:async';
  2. import 'dart:isolate';
  3. import 'package:angel_framework/angel_framework.dart';
  4. import 'package:angel_production/angel_production.dart';
  5.  
  6. main(List<String> args) => Runner('example', configureServer).run(args);
  7.  
  8. Future configureServer(Angel app) async {
  9. app.get('/', (req, res) => 'Hello, production world!');
  10.  
  11. app.get('/crash', (req, res) {
  12. // We'll crash this instance deliberately, but the Runner will auto-respawn for us.
  13. Timer(const Duration(seconds: 3), Isolate.current.kill);
  14. return 'Crashing in 3s...';
  15. });
  16. }

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

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

Message Passing

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

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

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

  1. // Use the injected `pub_sub.Client` to send messages.
  2. var client = app.container.make<pub_sub.Client>();
  3.  
  4. // We can listen for an event to perform some behavior.
  5. //
  6. // Here, we use message passing to synchronize some common state.
  7. var onGreetingChanged = await client.subscribe('user_upgraded');
  8. onGreetingChanged
  9. .cast<User>()
  10. .listen((user) {
  11. // Do something...
  12. });

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 injectedinto each instance:

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

Command-line Options

The Runner class supplies options like the following:

  1. Tobes-MacBook-Air:production thosakwe$ dart example/main.dart --help
  2. ____________ ________________________
  3. ___ |__ | / /_ ____/__ ____/__ /
  4. __ /| |_ |/ /_ / __ __ __/ __ /
  5. _ ___ | /| / / /_/ / _ /___ _ /___
  6. /_/ |_/_/ |_/ ____/ /_____/ /_____/
  7. A batteries-included, full-featured, full-stack framework in Dart.
  8. https://angel-dart.github.io
  9. Options:
  10. -h, --help Print this help information.
  11. --[no-]respawn Automatically respawn crashed application instances.
  12. (defaults to on)
  13. --use-zone Create a new Zone for each request.
  14. --quiet Completely mute logging.
  15. --ssl Listen for HTTPS instead of HTTP.
  16. --http2 Listen for HTTP/2 instead of HTTP/1.1.
  17. -a, --address The address to listen on.
  18. (defaults to "127.0.0.1")
  19. -j, --concurrency The number of isolates to spawn.
  20. (defaults to "4")
  21. -p, --port The port to listen on.
  22. (defaults to "3000")
  23. --certificate-file The PEM certificate file to read.
  24. --certificate-password The PEM certificate file password.
  25. --key-file The PEM key file to read.
  26. --key-password The PEM key file password.