OneShot class

One-shot channels - Promise-like single-value delivery with advanced semantics.

Specialized channels for delivering exactly one value, similar to futures but with more flexible consumption patterns. Perfect for request-response scenarios, async initialization, and promise-like patterns.

Core Features

  • Single-value semantics: Exactly one value can be sent
  • Flexible consumption: Choose between consume-once or multi-reader patterns
  • Promise-like behavior: Similar to futures but with channel semantics
  • Type-safe results: Explicit success/failure handling
  • Zero buffering: Direct producer-to-consumer handoff

Consumption Modes

consumeOnce: true (Default Promise Behavior)

  • First receiver gets the value and consumes it
  • Channel disconnects immediately after consumption
  • Subsequent receivers get RecvErrorDisconnected
  • Perfect for request-response patterns

consumeOnce: false (Broadcast Promise)

  • All receivers (current and future) get the same value
  • Value remains available until explicitly handled
  • Multiple receivers can read the same result
  • Perfect for initialization values or shared results

When to Use OneShot

  • Request-response patterns: Client sends request, waits for single response
  • Async initialization: Wait for setup completion across multiple components
  • Result broadcasting: Share a computed result with multiple consumers
  • Promise coordination: Advanced promise-like patterns with explicit control
  • Resource resolution: Resolve a resource once, use many times
  • Configuration loading: Load config once, access from multiple places

Performance Characteristics

  • Lightweight: Minimal memory footprint (single value storage)
  • Efficient delivery: Direct value handoff for single-value scenarios
  • Good performance: ~381-390ns per operation (see benchmarks)
  • Simple storage: Single memory location for value storage

Usage Patterns

Request-response (consumeOnce: true):

// Client-server request pattern
Future<ApiResponse> makeRequest(ApiRequest request) async {
  final (responseTx, responseRx) = OneShot.channel<ApiResponse>(consumeOnce: true);

  // Send request with response channel
  await requestChannel.send(RequestWithResponse(request, responseTx));

  // Wait for single response
  final result = await responseRx.recv();
  return switch (result) {
    RecvOk(value: final response) => response,
    RecvErrorDisconnected() => throw TimeoutException('Server disconnected'),
    _ => throw StateError('Unexpected result: $result'),
  };
}

// Server side
await for (final requestWithResponse in requestChannel.stream()) {
  final response = await processRequest(requestWithResponse.request);
  await requestWithResponse.responseTx.send(response); // Consumed by one client
}

Shared initialization (consumeOnce: false):

// Global configuration initialization
class ConfigManager {
  static final (configTx, configRx) = OneShot.channel<AppConfig>(consumeOnce: false);
  static bool _initialized = false;

  static Future<void> initialize() async {
    if (_initialized) return;
    _initialized = true;

    final config = await loadConfigFromServer();
    await configTx.send(config); // Available to all readers
  }

  static Future<AppConfig> getConfig() async {
    final result = await configRx.recv();
    return result.valueOrNull!; // Same config for all callers
  }
}

// Multiple components can access the same config
final userConfig = await ConfigManager.getConfig();
final dbConfig = await ConfigManager.getConfig(); // Same instance

Resource resolution pattern:

// Database connection pool initialization
class DatabasePool {
  final (poolTx, poolRx) = OneShot.channel<ConnectionPool>(consumeOnce: false);

  Future<void> initializePool() async {
    final pool = await ConnectionPool.create(
      maxConnections: 10,
      connectionString: connectionString,
    );
    await poolTx.send(pool); // Available to all consumers
  }

  Future<Connection> getConnection() async {
    final result = await poolRx.recv();
    final pool = result.valueOrNull!;
    return await pool.getConnection();
  }
}

Advanced promise coordination:

// Coordinated async operations
class AsyncOperationCoordinator {
  final operations = <String, OneShot>{};

  (OneShotSender<T>, OneShotReceiver<T>) createOperation<T>(String name, {bool shared = false}) {
    final (tx, rx) = OneShot.channel<T>(consumeOnce: !shared);
    operations[name] = (tx, rx);
    return (tx, rx);
  }

  Future<T> waitForOperation<T>(String name) async {
    final (_, rx) = operations[name] as (OneShotSender<T>, OneShotReceiver<T>);
    final result = await rx.recv();
    return result.valueOrNull!;
  }
}

Constructors

OneShot.new()

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Methods

channel<T>({bool consumeOnce = false, String? metricsId}) → (OneShotSender<T>, OneShotReceiver<T>)
Creates a one-shot channel for single-value delivery.