call method

Future<Result<T, AppFailure>> call(
  1. Params params, {
  2. CancelToken? cancelToken,
})

Execute the use case with the given params.

Prefer using the call syntax: await useCase(params) instead of: await useCase.call(params)

Returns a Result that is either:

Implementation

Future<Result<T, AppFailure>> call(
  Params params, {
  CancelToken? cancelToken,
}) async {
  final startTime = DateTime.now();
  final traceCtx = (
    traceId: TraceObserver.instance.currentTraceId,
    spanId: TraceObserver.instance.currentSpanId,
  );

  // Shared metadata bag — hooks can write in pre, read in success/failure
  final hookMetadata = <String, dynamic>{};

  HookRegistry.instance.dispatch(
    HookContext(
      useCaseName: '$runtimeType',
      params: params,
      timestamp: startTime,
      traceId: traceCtx.traceId,
      spanId: traceCtx.spanId,
      metadata: hookMetadata,
    ),
    HookPhase.pre,
  );

  try {
    // Check for cancellation before starting
    cancelToken?.throwIfCancelled();

    final value = await execute(params, cancelToken);

    logger.fine('$runtimeType completed successfully');

    HookRegistry.instance.dispatch(
      HookContext(
        useCaseName: '$runtimeType',
        params: params,
        result: value,
        duration: DateTime.now().difference(startTime),
        timestamp: startTime,
        traceId: traceCtx.traceId,
        spanId: traceCtx.spanId,
        metadata: hookMetadata,
      ),
      HookPhase.success,
    );

    return Result.success(value);
  } on CancelledException catch (e) {
    logger.info('$runtimeType was cancelled: ${e.message}');
    return Result.failure(CancellationFailure(e.message));
  } on AppFailure catch (e) {
    logger.warning('$runtimeType failed with AppFailure: $e');
    FailureReporterRegistry.instance.reportFailure(
      e,
      stackTrace: e.stackTrace,
      attributes: {'usecase': '$runtimeType'},
    );

    HookRegistry.instance.dispatch(
      HookContext(
        useCaseName: '$runtimeType',
        params: params,
        failure: e,
        duration: DateTime.now().difference(startTime),
        timestamp: startTime,
        traceId: traceCtx.traceId,
        spanId: traceCtx.spanId,
        metadata: hookMetadata,
      ),
      HookPhase.failure,
    );

    return Result.failure(e);
  } catch (e, stackTrace) {
    logger.severe('$runtimeType failed unexpectedly', e, stackTrace);
    final failure = AppFailure.from(e, stackTrace);
    FailureReporterRegistry.instance.reportFailure(
      failure,
      stackTrace: stackTrace,
      attributes: {'usecase': '$runtimeType'},
    );

    HookRegistry.instance.dispatch(
      HookContext(
        useCaseName: '$runtimeType',
        params: params,
        failure: failure,
        duration: DateTime.now().difference(startTime),
        timestamp: startTime,
        traceId: traceCtx.traceId,
        spanId: traceCtx.spanId,
        metadata: hookMetadata,
      ),
      HookPhase.failure,
    );

    return Result.failure(failure);
  }
}