@@ -25,10 +25,10 @@ public MerchantRuntime(IApiClient apiClient,
2525 this . Metrics = metrics ;
2626 }
2727
28- private TokenResponse CurrentServiceToken ;
29- private TokenResponse CurrentUserToken ;
30- private ( String clientId , String clientSecret ) ServiceClientCredentials ;
31- private ( String clientId , String clientSecret ) PosClientCredentials ;
28+ private TokenResponse ? CurrentServiceToken ;
29+ private TokenResponse ? CurrentUserToken ;
30+ private ( String clientId , String clientSecret ) ServiceClientCredentials = default ! ;
31+ private ( String clientId , String clientSecret ) PosClientCredentials = default ! ;
3232 public async Task RunAsync ( ( String clientId , String clientSecret ) serviceClient , ( String clientId , String clientSecret ) posClient , MerchantConfig config , CancellationToken cancellationToken )
3333 {
3434 Logger . LogInformation ( $ "MerchantRuntime started for { config . MerchantName } ") ;
@@ -131,23 +131,28 @@ private async Task StartupSequence(MerchantConfig cfg,
131131 return ;
132132 }
133133
134+ TokenResponse userToken = this . CurrentUserToken
135+ ?? throw new InvalidOperationException ( $ "User token was not initialized for merchant { cfg . MerchantName } .") ;
136+ TokenResponse serviceToken = this . CurrentServiceToken
137+ ?? throw new InvalidOperationException ( $ "Service token was not initialized for merchant { cfg . MerchantName } .") ;
138+
134139 // 2. Load products
135- Result < List < Product > > productsResult = await ApiClient . GetProductList ( cfg , this . CurrentUserToken , cancellationToken ) ;
140+ Result < List < Product > > productsResult = await ApiClient . GetProductList ( cfg , userToken , cancellationToken ) ;
136141 if ( productsResult . IsFailed ) {
137142 Logger . LogWarning ( $ "Failed to get product list for merchant { cfg . MerchantName } during startup sequence.") ;
138143 return ;
139144 }
140145 cfg . Products = productsResult . Data ;
141146
142147 // 3. Balance
143- Result < decimal > balanceResult = await ApiClient . GetBalance ( cfg , this . CurrentServiceToken , cancellationToken ) ;
148+ Result < decimal > balanceResult = await ApiClient . GetBalance ( cfg , serviceToken , cancellationToken ) ;
144149 if ( balanceResult . IsFailed ) {
145150 Logger . LogWarning ( $ "Failed to get balance for merchant { cfg . MerchantName } during startup sequence.") ;
146151 return ;
147152 }
148153 await Repository . UpdateBalance ( cfg . MerchantId , cfg . MerchantName , balanceResult . Data ) ;
149154 // 4. get the merchant record
150- var merchant = await ApiClient . GetMerchant ( cfg , this . CurrentUserToken , cancellationToken ) ;
155+ var merchant = await ApiClient . GetMerchant ( cfg , userToken , cancellationToken ) ;
151156 cfg . Merchant = merchant . Data ;
152157 }
153158
@@ -156,21 +161,29 @@ private async Task RunMainLoop(MerchantConfig cfg,
156161 TimeSpan saleInterval = TimeSpan . FromSeconds ( cfg . SaleIntervalSeconds ) ;
157162
158163 while ( ! token . IsCancellationRequested ) {
159- Merchant merchant = await this . Repository . GetMerchant ( cfg . MerchantId ) ;
164+ Merchant merchant = await this . Repository . GetMerchant ( cfg . MerchantId )
165+ ?? throw new InvalidOperationException ( $ "Merchant { cfg . MerchantId } was not found.") ;
160166 // Wait until the merchant's configured opening time
161167 DateTime currentTime = DateTime . Now ;
162168
163169 // Get the current days opening and closing time
164170 TimeSpan openingTime ;
165171 TimeSpan closingTime ;
166- Boolean found = cfg . Merchant . OpeningHours . TryGetValue ( DateTime . Now . DayOfWeek , out var openingHours ) ;
172+ MerchantResponse merchantConfig = cfg . Merchant
173+ ?? throw new InvalidOperationException ( $ "Merchant details were not loaded for { cfg . MerchantName } .") ;
174+
175+ Boolean found = merchantConfig . OpeningHours . TryGetValue ( DateTime . Now . DayOfWeek , out var openingHours ) ;
167176 if ( found == false ) {
168177 // fallback to the configured default opening and closing time if no specific hours for the day of week
169178 openingTime = cfg . OpeningTime . ToTimeSpan ( ) ;
170179 closingTime = cfg . ClosingTime . ToTimeSpan ( ) ;
171180 }
172181 else {
173182 // We have opening and closing times for the current day of week, so use those
183+ if ( openingHours is null )
184+ {
185+ throw new InvalidOperationException ( $ "Opening hours were not configured for { cfg . MerchantName } on { DateTime . Now . DayOfWeek } .") ;
186+ }
174187 openingTime = TimeSpan . ParseExact ( openingHours . Opening , "hhmm" , null ) ;
175188 closingTime = TimeSpan . ParseExact ( openingHours . Closing , "hhmm" , null ) ;
176189 }
@@ -214,7 +227,9 @@ private async Task RunMainLoop(MerchantConfig cfg,
214227 }
215228 else
216229 {
217- await ApiClient . SendLogon ( cfg , this . CurrentUserToken , merchant . TransactionNumber , token ) ;
230+ TokenResponse userToken = this . CurrentUserToken
231+ ?? throw new InvalidOperationException ( $ "User token was not initialized for merchant { cfg . MerchantName } .") ;
232+ await ApiClient . SendLogon ( cfg , userToken , merchant . TransactionNumber , token ) ;
218233 //_lastDailyLogonDate = now.Date;
219234 await this . Repository . UpdateLastLogon ( cfg . MerchantId , cfg . MerchantName , now ) ;
220235 Logger . LogInformation ( $ "Performed daily logon for merchant { cfg . MerchantName } on { now : yyyy-MM-dd} ") ;
@@ -235,9 +250,13 @@ private async Task DoSaleCycle(MerchantConfig cfg,Int32 transactionNumber, Cance
235250 Result tokenResult = await this . GetServiceToken ( cancellationToken ) ;
236251 if ( tokenResult . IsFailed )
237252 return ;
253+ TokenResponse serviceToken = this . CurrentServiceToken
254+ ?? throw new InvalidOperationException ( $ "Service token was not initialized for merchant { cfg . MerchantName } .") ;
238255 tokenResult = await this . GetUserToken ( cfg , cancellationToken ) ;
239256 if ( tokenResult . IsFailed )
240257 return ;
258+ TokenResponse userToken = this . CurrentUserToken
259+ ?? throw new InvalidOperationException ( $ "User token was not initialized for merchant { cfg . MerchantName } .") ;
241260
242261 decimal balance = await Repository . GetBalance ( cfg . MerchantId ) ;
243262
@@ -254,7 +273,7 @@ private async Task DoSaleCycle(MerchantConfig cfg,Int32 transactionNumber, Cance
254273 bool induceFail = NextDouble ( ) < cfg . FailureInjectionProbability ;
255274 decimal saleValue = induceFail ? balance + 10 : value ;
256275
257- Result < SaleResponse > result = await ApiClient . SendSale ( cfg , this . CurrentUserToken , product , saleValue , transactionNumber , cancellationToken ) ;
276+ Result < SaleResponse > result = await ApiClient . SendSale ( cfg , userToken , product , saleValue , transactionNumber , cancellationToken ) ;
258277
259278 if ( result . IsFailed )
260279 {
@@ -278,7 +297,7 @@ private async Task DoSaleCycle(MerchantConfig cfg,Int32 transactionNumber, Cance
278297 this . Metrics . SetBalance ( cfg . MerchantId , newBalance ) ;
279298 if ( newBalance < cfg . DepositThreshold )
280299 {
281- await ApiClient . SendDeposit ( cfg , this . CurrentServiceToken , cfg . DepositAmount , cancellationToken ) ;
300+ await ApiClient . SendDeposit ( cfg , serviceToken , cfg . DepositAmount , cancellationToken ) ;
282301 await Repository . UpdateBalance ( cfg . MerchantId , cfg . MerchantName , newBalance + cfg . DepositAmount ) ;
283302 newBalance = await Repository . GetBalance ( cfg . MerchantId ) ;
284303 this . Metrics . SetBalance ( cfg . MerchantId , newBalance ) ;
@@ -296,9 +315,11 @@ private async Task DoReconciliation(MerchantConfig cfg, CancellationToken cancel
296315 Result tokenResult = await this . GetUserToken ( cfg , cancellationToken ) ;
297316 if ( tokenResult . IsFailed )
298317 return ;
318+ TokenResponse userToken = this . CurrentUserToken
319+ ?? throw new InvalidOperationException ( $ "User token was not initialized for merchant { cfg . MerchantName } .") ;
299320
300321 List < OperatorTotal > totals = await Repository . GetTotals ( cfg . MerchantId ) ;
301- await ApiClient . SendReconciliation ( cfg , this . CurrentUserToken , totals , cancellationToken ) ;
322+ await ApiClient . SendReconciliation ( cfg , userToken , totals , cancellationToken ) ;
302323
303324 // Clear totals
304325 await this . Repository . UpdateLastEndOfDay ( cfg . MerchantId , cfg . MerchantName , DateTime . Now ) ;
0 commit comments