onNodeChanges property

  1. @override
Stream<List<TailscaleNode>> get onNodeChanges
override

Emits the full node list on any change (node joined, left, went on/off-line, tags or DNS name changed).

Saves callers from polling nodes on a timer. Derived from the same IPN bus NotifyInitialNetMap subscription as onStateChange; subscribers get the current node inventory as the first emission, then one emission per inventory change.

Implementation

@override
Stream<List<TailscaleNode>> get onNodeChanges =>
    Stream<List<TailscaleNode>>.multi((controller) {
      var canceled = false;
      List<TailscaleNode>? lastEmitted;

      void emitIfChanged(List<TailscaleNode> nodes) {
        if (_sameNodes(lastEmitted, nodes)) return;
        lastEmitted = nodes;
        controller.add(nodes);
      }

      final subscription = _nodesController.stream.listen(
        emitIfChanged,
        onError: controller.addError,
        onDone: controller.close,
      );

      unawaited(() async {
        try {
          final snapshot = _latestNodes ?? await _snapshotNodes();
          if (!canceled) {
            emitIfChanged(snapshot);
          }
        } catch (error, stackTrace) {
          if (!canceled) {
            controller.addError(error, stackTrace);
          }
        }
      }());

      controller.onCancel = () {
        canceled = true;
        return subscription.cancel();
      };
    }, isBroadcast: true);