@@ -32,6 +32,7 @@ class AppDependencies {
32
32
static AppDependencies get instance => _instance;
33
33
34
34
bool _isInitialized = false ;
35
+ Exception ? _initializationError;
35
36
final _log = Logger ('AppDependencies' );
36
37
37
38
// --- Late-initialized fields for all dependencies ---
@@ -64,132 +65,146 @@ class AppDependencies {
64
65
///
65
66
/// This method is idempotent; it will only run the initialization logic once.
66
67
Future <void > init () async {
68
+ // If initialization previously failed, re-throw the original error.
69
+ if (_initializationError != null ) {
70
+ throw _initializationError! ;
71
+ }
72
+
67
73
if (_isInitialized) return ;
68
74
69
75
_log.info ('Initializing application dependencies...' );
70
76
71
- // 1. Initialize Database Connection
72
- _mongoDbConnectionManager = MongoDbConnectionManager ();
73
- await _mongoDbConnectionManager.init (EnvironmentConfig .databaseUrl);
74
- _log.info ('MongoDB connection established.' );
75
-
76
- // 2. Seed Database
77
- final seedingService = DatabaseSeedingService (
78
- db: _mongoDbConnectionManager.db,
79
- log: Logger ('DatabaseSeedingService' ),
80
- );
81
- await seedingService.seedInitialData ();
82
- _log.info ('Database seeding complete.' );
83
-
84
- // 3. Initialize Data Clients (MongoDB implementation)
85
- final headlineClient = HtDataMongodb <Headline >(
86
- connectionManager: _mongoDbConnectionManager,
87
- modelName: 'headlines' ,
88
- fromJson: Headline .fromJson,
89
- toJson: (item) => item.toJson (),
90
- logger: Logger ('HtDataMongodb<Headline>' ),
91
- );
92
- final topicClient = HtDataMongodb <Topic >(
93
- connectionManager: _mongoDbConnectionManager,
94
- modelName: 'topics' ,
95
- fromJson: Topic .fromJson,
96
- toJson: (item) => item.toJson (),
97
- logger: Logger ('HtDataMongodb<Topic>' ),
98
- );
99
- final sourceClient = HtDataMongodb <Source >(
100
- connectionManager: _mongoDbConnectionManager,
101
- modelName: 'sources' ,
102
- fromJson: Source .fromJson,
103
- toJson: (item) => item.toJson (),
104
- logger: Logger ('HtDataMongodb<Source>' ),
105
- );
106
- final countryClient = HtDataMongodb <Country >(
107
- connectionManager: _mongoDbConnectionManager,
108
- modelName: 'countries' ,
109
- fromJson: Country .fromJson,
110
- toJson: (item) => item.toJson (),
111
- logger: Logger ('HtDataMongodb<Country>' ),
112
- );
113
- final userClient = HtDataMongodb <User >(
114
- connectionManager: _mongoDbConnectionManager,
115
- modelName: 'users' ,
116
- fromJson: User .fromJson,
117
- toJson: (item) => item.toJson (),
118
- logger: Logger ('HtDataMongodb<User>' ),
119
- );
120
- final userAppSettingsClient = HtDataMongodb <UserAppSettings >(
121
- connectionManager: _mongoDbConnectionManager,
122
- modelName: 'user_app_settings' ,
123
- fromJson: UserAppSettings .fromJson,
124
- toJson: (item) => item.toJson (),
125
- logger: Logger ('HtDataMongodb<UserAppSettings>' ),
126
- );
127
- final userContentPreferencesClient = HtDataMongodb <UserContentPreferences >(
128
- connectionManager: _mongoDbConnectionManager,
129
- modelName: 'user_content_preferences' ,
130
- fromJson: UserContentPreferences .fromJson,
131
- toJson: (item) => item.toJson (),
132
- logger: Logger ('HtDataMongodb<UserContentPreferences>' ),
133
- );
134
- final remoteConfigClient = HtDataMongodb <RemoteConfig >(
135
- connectionManager: _mongoDbConnectionManager,
136
- modelName: 'remote_configs' ,
137
- fromJson: RemoteConfig .fromJson,
138
- toJson: (item) => item.toJson (),
139
- logger: Logger ('HtDataMongodb<RemoteConfig>' ),
140
- );
141
-
142
- // 4. Initialize Repositories
143
- headlineRepository = HtDataRepository (dataClient: headlineClient);
144
- topicRepository = HtDataRepository (dataClient: topicClient);
145
- sourceRepository = HtDataRepository (dataClient: sourceClient);
146
- countryRepository = HtDataRepository (dataClient: countryClient);
147
- userRepository = HtDataRepository (dataClient: userClient);
148
- userAppSettingsRepository =
149
- HtDataRepository (dataClient: userAppSettingsClient);
150
- userContentPreferencesRepository =
151
- HtDataRepository (dataClient: userContentPreferencesClient);
152
- remoteConfigRepository = HtDataRepository (dataClient: remoteConfigClient);
153
-
154
- final emailClient = HtEmailInMemoryClient (
155
- logger: Logger ('HtEmailInMemoryClient' ),
156
- );
157
- emailRepository = HtEmailRepository (emailClient: emailClient);
158
-
159
- // 5. Initialize Services
160
- tokenBlacklistService = InMemoryTokenBlacklistService (
161
- log: Logger ('InMemoryTokenBlacklistService' ),
162
- );
163
- authTokenService = JwtAuthTokenService (
164
- userRepository: userRepository,
165
- blacklistService: tokenBlacklistService,
166
- uuidGenerator: const Uuid (),
167
- log: Logger ('JwtAuthTokenService' ),
168
- );
169
- verificationCodeStorageService = InMemoryVerificationCodeStorageService ();
170
- authService = AuthService (
171
- userRepository: userRepository,
172
- authTokenService: authTokenService,
173
- verificationCodeStorageService: verificationCodeStorageService,
174
- emailRepository: emailRepository,
175
- userAppSettingsRepository: userAppSettingsRepository,
176
- userContentPreferencesRepository: userContentPreferencesRepository,
177
- uuidGenerator: const Uuid (),
178
- log: Logger ('AuthService' ),
179
- );
180
- dashboardSummaryService = DashboardSummaryService (
181
- headlineRepository: headlineRepository,
182
- topicRepository: topicRepository,
183
- sourceRepository: sourceRepository,
184
- );
185
- permissionService = const PermissionService ();
186
- userPreferenceLimitService = DefaultUserPreferenceLimitService (
187
- remoteConfigRepository: remoteConfigRepository,
188
- log: Logger ('DefaultUserPreferenceLimitService' ),
189
- );
190
-
191
- _isInitialized = true ;
192
- _log.info ('Application dependencies initialized successfully.' );
77
+ try {
78
+ // 1. Initialize Database Connection
79
+ _mongoDbConnectionManager = MongoDbConnectionManager ();
80
+ await _mongoDbConnectionManager.init (EnvironmentConfig .databaseUrl);
81
+ _log.info ('MongoDB connection established.' );
82
+
83
+ // 2. Seed Database
84
+ final seedingService = DatabaseSeedingService (
85
+ db: _mongoDbConnectionManager.db,
86
+ log: Logger ('DatabaseSeedingService' ),
87
+ );
88
+ await seedingService.seedInitialData ();
89
+ _log.info ('Database seeding complete.' );
90
+
91
+ // 3. Initialize Data Clients (MongoDB implementation)
92
+ final headlineClient = HtDataMongodb <Headline >(
93
+ connectionManager: _mongoDbConnectionManager,
94
+ modelName: 'headlines' ,
95
+ fromJson: Headline .fromJson,
96
+ toJson: (item) => item.toJson (),
97
+ logger: Logger ('HtDataMongodb<Headline>' ),
98
+ );
99
+ final topicClient = HtDataMongodb <Topic >(
100
+ connectionManager: _mongoDbConnectionManager,
101
+ modelName: 'topics' ,
102
+ fromJson: Topic .fromJson,
103
+ toJson: (item) => item.toJson (),
104
+ logger: Logger ('HtDataMongodb<Topic>' ),
105
+ );
106
+ final sourceClient = HtDataMongodb <Source >(
107
+ connectionManager: _mongoDbConnectionManager,
108
+ modelName: 'sources' ,
109
+ fromJson: Source .fromJson,
110
+ toJson: (item) => item.toJson (),
111
+ logger: Logger ('HtDataMongodb<Source>' ),
112
+ );
113
+ final countryClient = HtDataMongodb <Country >(
114
+ connectionManager: _mongoDbConnectionManager,
115
+ modelName: 'countries' ,
116
+ fromJson: Country .fromJson,
117
+ toJson: (item) => item.toJson (),
118
+ logger: Logger ('HtDataMongodb<Country>' ),
119
+ );
120
+ final userClient = HtDataMongodb <User >(
121
+ connectionManager: _mongoDbConnectionManager,
122
+ modelName: 'users' ,
123
+ fromJson: User .fromJson,
124
+ toJson: (item) => item.toJson (),
125
+ logger: Logger ('HtDataMongodb<User>' ),
126
+ );
127
+ final userAppSettingsClient = HtDataMongodb <UserAppSettings >(
128
+ connectionManager: _mongoDbConnectionManager,
129
+ modelName: 'user_app_settings' ,
130
+ fromJson: UserAppSettings .fromJson,
131
+ toJson: (item) => item.toJson (),
132
+ logger: Logger ('HtDataMongodb<UserAppSettings>' ),
133
+ );
134
+ final userContentPreferencesClient =
135
+ HtDataMongodb <UserContentPreferences >(
136
+ connectionManager: _mongoDbConnectionManager,
137
+ modelName: 'user_content_preferences' ,
138
+ fromJson: UserContentPreferences .fromJson,
139
+ toJson: (item) => item.toJson (),
140
+ logger: Logger ('HtDataMongodb<UserContentPreferences>' ),
141
+ );
142
+ final remoteConfigClient = HtDataMongodb <RemoteConfig >(
143
+ connectionManager: _mongoDbConnectionManager,
144
+ modelName: 'remote_configs' ,
145
+ fromJson: RemoteConfig .fromJson,
146
+ toJson: (item) => item.toJson (),
147
+ logger: Logger ('HtDataMongodb<RemoteConfig>' ),
148
+ );
149
+
150
+ // 4. Initialize Repositories
151
+ headlineRepository = HtDataRepository (dataClient: headlineClient);
152
+ topicRepository = HtDataRepository (dataClient: topicClient);
153
+ sourceRepository = HtDataRepository (dataClient: sourceClient);
154
+ countryRepository = HtDataRepository (dataClient: countryClient);
155
+ userRepository = HtDataRepository (dataClient: userClient);
156
+ userAppSettingsRepository =
157
+ HtDataRepository (dataClient: userAppSettingsClient);
158
+ userContentPreferencesRepository =
159
+ HtDataRepository (dataClient: userContentPreferencesClient);
160
+ remoteConfigRepository =
161
+ HtDataRepository (dataClient: remoteConfigClient);
162
+
163
+ final emailClient = HtEmailInMemoryClient (
164
+ logger: Logger ('HtEmailInMemoryClient' ),
165
+ );
166
+ emailRepository = HtEmailRepository (emailClient: emailClient);
167
+
168
+ // 5. Initialize Services
169
+ tokenBlacklistService = InMemoryTokenBlacklistService (
170
+ log: Logger ('InMemoryTokenBlacklistService' ),
171
+ );
172
+ authTokenService = JwtAuthTokenService (
173
+ userRepository: userRepository,
174
+ blacklistService: tokenBlacklistService,
175
+ uuidGenerator: const Uuid (),
176
+ log: Logger ('JwtAuthTokenService' ),
177
+ );
178
+ verificationCodeStorageService =
179
+ InMemoryVerificationCodeStorageService ();
180
+ authService = AuthService (
181
+ userRepository: userRepository,
182
+ authTokenService: authTokenService,
183
+ verificationCodeStorageService: verificationCodeStorageService,
184
+ emailRepository: emailRepository,
185
+ userAppSettingsRepository: userAppSettingsRepository,
186
+ userContentPreferencesRepository: userContentPreferencesRepository,
187
+ uuidGenerator: const Uuid (),
188
+ log: Logger ('AuthService' ),
189
+ );
190
+ dashboardSummaryService = DashboardSummaryService (
191
+ headlineRepository: headlineRepository,
192
+ topicRepository: topicRepository,
193
+ sourceRepository: sourceRepository,
194
+ );
195
+ permissionService = const PermissionService ();
196
+ userPreferenceLimitService = DefaultUserPreferenceLimitService (
197
+ remoteConfigRepository: remoteConfigRepository,
198
+ log: Logger ('DefaultUserPreferenceLimitService' ),
199
+ );
200
+
201
+ _isInitialized = true ;
202
+ _log.info ('Application dependencies initialized successfully.' );
203
+ } on Exception catch (e) {
204
+ _log.severe ('Failed to initialize application dependencies' , e);
205
+ _initializationError = e;
206
+ rethrow ;
207
+ }
193
208
}
194
209
195
210
/// Disposes of resources, such as closing the database connection.
0 commit comments