@@ -32,6 +32,7 @@ class AppDependencies {
3232 static AppDependencies get instance => _instance;
3333
3434 bool _isInitialized = false ;
35+ Exception ? _initializationError;
3536 final _log = Logger ('AppDependencies' );
3637
3738 // --- Late-initialized fields for all dependencies ---
@@ -64,132 +65,146 @@ class AppDependencies {
6465 ///
6566 /// This method is idempotent; it will only run the initialization logic once.
6667 Future <void > init () async {
68+ // If initialization previously failed, re-throw the original error.
69+ if (_initializationError != null ) {
70+ throw _initializationError! ;
71+ }
72+
6773 if (_isInitialized) return ;
6874
6975 _log.info ('Initializing application dependencies...' );
7076
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+ }
193208 }
194209
195210 /// Disposes of resources, such as closing the database connection.
0 commit comments