putAsync method

Future<int> putAsync(
  1. T object, {
  2. PutMode mode = PutMode.put,
})

Puts the given object in the box (persisting it) asynchronously.

The returned future completes with an ID of the object. If it is a new object (its ID property is 0), a new ID will be assigned to the object argument, after the returned Future completes.

In extreme scenarios (e.g. having hundreds of thousands async operations per second), this may fail as internal queues fill up if the disk can't keep up. However, this should not be a concern for typical apps. The returned future may also complete with an error if the put failed for another reason, for example a unique constraint violation. In that case the object's id field remains unchanged (0 if it was a new object).

See also putQueued which doesn't return a Future but a pre-allocated ID immediately, even though the actual database put operation may fail.

Implementation

Future<int> putAsync(T object, {PutMode mode = PutMode.put}) async =>
    // Wrap with [Future.sync] to avoid mixing sync and async errors.
    // Note: doesn't seem to decrease performance at all.
    // https://dart.dev/guides/libraries/futures-error-handling#potential-problem-accidentally-mixing-synchronous-and-asynchronous-errors
    Future.sync(() async {
      if (_hasRelations) {
        throw UnsupportedError(
            'putAsync() is currently not supported on entity '
            '${T.toString()} because it has relations.');
      }
      _async ??= _AsyncBoxHelper(this);

      // Note: we can use the shared flatbuffer object, because:
      // https://dart.dev/codelabs/async-await#execution-flow-with-async-and-await
      // > An async function runs synchronously until the first await keyword.
      // > This means that within an async function body, all synchronous code
      // > before the first await keyword executes immediately.
      _builder.fbb.reset();
      var id = _entity.objectToFB(object, _builder.fbb);
      final newId = _async!.put(id, _builder, mode);
      _builder.resetIfLarge(); // reset before `await`
      if (id == 0) {
        // Note: if the newId future completes with an error, ID isn't set.
        _entity.setId(object, await newId);
      }
      return newId;
    });