@@ -6,6 +6,7 @@ use std::fs;
66use std:: time:: Duration ;
77
88use crate :: engine:: error:: DynResult ;
9+ use crate :: retry:: { execute_with_retries_if, RetryConfig } ;
910use base64:: { prelude:: BASE64_STANDARD , Engine } ;
1011use cached:: proc_macro:: cached;
1112use chrono:: { DateTime , Utc } ;
@@ -155,13 +156,26 @@ impl ValidationResponse {
155156 }
156157}
157158
158- #[ cached]
159+ // `result = true` makes the cached macro store only successful validations;
160+ // transient `Err`s are NOT cached, so a one-off network blip on the very first
161+ // call doesn't poison every subsequent license check in the process.
162+ //
163+ // On top of that, retry only the transient `LicenseValidation` variant
164+ // (network / timeout against license.pathway.com) via `execute_with_retries_if`.
165+ // `InsufficientLicenseEntitlements` and other non-transient errors fail the
166+ // predicate, propagate immediately, and don't burn retry budget.
167+ #[ cached( result = true ) ]
159168fn check_license_key_entitlements (
160169 license_key : String ,
161170 entitlements : Vec < String > ,
162171) -> Result < ValidationResponse , Error > {
163- KeygenLicenseChecker :: new ( PATHWAY_LICENSE_SERVER . to_string ( ) )
164- . check_entitlements ( & license_key, entitlements)
172+ let checker = KeygenLicenseChecker :: new ( PATHWAY_LICENSE_SERVER . to_string ( ) ) ;
173+ execute_with_retries_if (
174+ || checker. check_entitlements ( & license_key, entitlements. clone ( ) ) ,
175+ |e| matches ! ( e, Error :: LicenseValidation ( _) ) ,
176+ RetryConfig :: default ( ) ,
177+ 3 ,
178+ )
165179}
166180
167181struct KeygenLicenseChecker {
0 commit comments