• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Willian199 / dart_ddi / 19001547214

01 Nov 2025 07:24PM UTC coverage: 84.851% (-0.2%) from 85.031%
19001547214

Pull #29

github

web-flow
Merge 1ade3b6b3 into 2d10867f1
Pull Request #29: Doc: Some fixes related to factory state control

446 of 488 new or added lines in 10 files covered. (91.39%)

1 existing line in 1 file now uncovered.

857 of 1010 relevant lines covered (84.85%)

11.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.21
/lib/src/utils/instance_destroy_utils.dart
1
import 'dart:async';
2

3
import 'package:dart_ddi/dart_ddi.dart';
4
import 'package:dart_ddi/src/exception/bean_not_found.dart';
5

6
/// Utility class for destroying instances with proper cleanup and interceptor handling.
7
///
8
/// This class provides methods to safely destroy instances while ensuring proper cleanup of resources,
9
/// calling interceptors, and handling child modules. It manages the destruction process in a controlled manner,
10
/// respecting the `canDestroy` flag and calling appropriate lifecycle hooks.
11
///
12
/// The destruction process includes:
13
/// - Calling interceptors' `onDestroy` method
14
/// - Calling `PreDestroy` mixin if the instance implements it
15
/// - Destroying child modules if the instance is a `DDIModule`
16
/// - Executing the provided apply function to remove the instance from the container
17
final class InstanceDestroyUtils {
18
  /// Destroys an instance with proper cleanup and interceptor handling.
19
  ///
20
  /// This method orchestrates the destruction process, ensuring all cleanup steps are executed in the correct order.
21
  /// It respects the `canDestroy` flag and only proceeds with destruction if it's set to true.
22
  ///
23
  /// - `apply`: Function to remove the instance from the DDI container.
24
  /// - `canDestroy`: Flag indicating whether the instance can be destroyed.
25
  /// - `instance`: The instance to be destroyed (can be null).
26
  /// - `children`: Set of child qualifiers that should be destroyed.
27
  /// - `interceptors`: Set of interceptor qualifiers to call during destruction.
28
  ///
29
  /// The destruction process follows this order:
30
  /// 1. Call interceptors' `onDestroy` method (even if instance is null)
31
  /// 2. If instance implements `PreDestroy`, call `onPreDestroy` and destroy children
32
  /// 3. If instance is a `DDIModule` with children, destroy all children first
33
  /// 4. Execute the apply function to remove from container
34
  ///
35
  /// Example:
36
  /// ```dart
37
  /// await InstanceDestroyUtils.destroyInstance(
38
  ///   apply: () => ddi.remove<MyService>(),
39
  ///   canDestroy: true,
40
  ///   instance: myService,
41
  ///   children: {'child1', 'child2'},
42
  ///   interceptors: {'interceptor1'},
43
  /// );
44
  /// ```
45
  static FutureOr<void> destroyInstance<BeanT extends Object>({
38✔
46
    required void Function() apply,
47
    required BeanT? instance,
48
    required Set<Object> children,
49
    required Set<Object> interceptors,
50
  }) async {
51
    // Should call interceptors even if the instance is null
52
    if (interceptors.isNotEmpty) {
38✔
53
      for (final interceptor in interceptors) {
14✔
54
        try {
55
          if (ddi.isFuture<BeanT>(qualifier: interceptor)) {
14✔
56
            final inter =
NEW
57
                (await ddi.getAsync(qualifier: interceptor)) as DDIInterceptor;
×
58

NEW
59
            await inter.onDestroy(instance);
×
60
          } else {
NEW
61
            final inter = ddi.get(qualifier: interceptor) as DDIInterceptor;
×
62

NEW
63
            inter.onDestroy(instance);
×
64
          }
65
        } on BeanNotFoundException {
7✔
66
          // Ignore BeanNotFoundException interceptor error during destruction
67
        }
68
      }
69
    }
70

71
    if (instance case final clazz? when clazz is PreDestroy) {
31✔
72
      return _runFutureOrPreDestroy<BeanT>(clazz, children, apply);
3✔
73
    } else if (instance is DDIModule) {
38✔
74
      if (children.isNotEmpty) {
3✔
75
        final List<Future<void>> futures = [];
3✔
76
        for (final Object child in children) {
6✔
77
          futures.add(ddi.destroy(qualifier: child) as Future<void>);
9✔
78
        }
79
        return Future.wait(
3✔
80
          futures,
81
          eagerError: true,
82
        ).then(
3✔
83
          (_) => apply(),
6✔
84
        );
85
      }
86
    }
87

88
    _destroyChildren<BeanT>(children);
38✔
89
    apply();
38✔
90
  }
91

92
  /// Destroys all child instances for a given set of child qualifiers.
93
  ///
94
  /// This method iterates through the children set and calls `ddi.destroy` for each child.
95
  /// It's used internally by the main destruction process to ensure all child modules are properly cleaned up.
96
  ///
97
  /// - `children`: Set of child qualifiers to destroy.
98
  ///
99
  /// Example:
100
  /// ```dart
101
  /// InstanceDestroyUtils._destroyChildren({'child1', 'child2'});
102
  /// ```
103
  static FutureOr<void> _destroyChildren<BeanT extends Object>(
38✔
104
      Set<Object> children) {
105
    for (final Object child in children) {
41✔
106
      ddi.destroy(qualifier: child);
6✔
107
    }
108
  }
109

110
  /// Executes the `onPreDestroy` method for instances that implement `PreDestroy`.
111
  ///
112
  /// This method is called when an instance implements the `PreDestroy` mixin. It ensures that
113
  /// the `onPreDestroy` method is called before the instance is destroyed, and that all children
114
  /// are also destroyed in the process.
115
  ///
116
  /// - `clazz`: The instance implementing `PreDestroy`.
117
  /// - `children`: Set of child qualifiers to destroy.
118
  /// - `apply`: Function to remove the instance from the container.
119
  ///
120
  /// Example:
121
  /// ```dart
122
  /// await InstanceDestroyUtils._runFutureOrPreDestroy(
123
  ///   myService,
124
  ///   {'child1'},
125
  ///   () => ddi.remove<MyService>(),
126
  /// );
127
  /// ```
128
  static Future<void> _runFutureOrPreDestroy<BeanT extends Object>(
3✔
129
      PreDestroy clazz, Set<Object> children, void Function() apply) async {
130
    for (final Object child in children) {
4✔
131
      await ddi.destroy(qualifier: child);
2✔
132
    }
133

134
    await clazz.onPreDestroy();
3✔
135
    apply();
3✔
136
  }
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc