job<T> static method

Future<T> job<T>(
  1. String name,
  2. FutureOr<T> body(), {
  3. String? step,
  4. Object? id,
  5. String? queue,
})

Runs body as a job: work a request handed off, run later by a queue's worker. It runs under step — the step of the request that queued it, which the queue keeps with the job (FlutterwareServer.step) — or, with none, under the current zone's; and as a request of its own, so what it writes, sends and runs gathers beneath one line of the world's trace: job thumbnail on jobs, done in 1.2 s, 31 statements.

// Where the request queues it:
await queue.add(Job('thumbnail', file: id, step: FlutterwareServer.step));
// Where a worker runs it:
await FlutterwareServer.job('thumbnail', () => thumbnail(job.file),
    step: job.step, id: job.id, queue: 'jobs');

Reports a job event as it starts and another as it ends, with how long it took and what it threw; the error is rethrown.

body starts at once, in the caller's turn: like any async function it runs synchronously up to its first await. Work that must come after its caller — a webhook delivered once the request that fired it has answered, as a webhook service would — goes in a Future: unawaited(Future(() => FlutterwareServer.job('deliver', …))).

Implementation

static Future<T> job<T>(
  String name,
  FutureOr<T> Function() body, {
  String? step,
  Object? id,
  String? queue,
}) => runZoned(() async {
  var said = {'name': name, 'id': ?id?.toString(), 'queue': ?queue};
  event('job', said);
  var watch = Stopwatch()..start();
  Object? error;
  try {
    return await body();
  } catch (e) {
    error = e;
    rethrow;
  } finally {
    event('job', {
      ...said,
      'ms': watch.elapsedMicroseconds / 1000,
      if (error != null) 'error': '$error',
    });
  }
}, zoneValues: {requestIdKey: 'job-${++_jobs}', stepKey: ?step});