fix(billing): tolerate ReflectionTypeLoadException during init #19
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/billing-init-reflection"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Backport of
7f84d4d9to release/1.0.6.ConfigureBillingService() walks AppDomain.CurrentDomain.GetAssemblies()
and calls Assembly.GetTypes() on each. In CI under xunit v3, one of
those assemblies has a type that fails to resolve, so GetTypes() throws
ReflectionTypeLoadException. The exception was unhandled, so after
Clearing the collections at the top of the method, the exception
escaped before the RegisterBilling<> calls could re-populate
BillingService.Billing.
Symptom in CI: the test
Yavsc.BillingServiceTests.ConfigureBillingService_CanBeCalledTwiceWithoutThrowing
fails with 'Assert.Equal() Failure: Expected 3, Actual 0' because the
second ConfigureBillingService() call replays the exact same failure
on the same loaded assembly, leaving BillingService.Billing empty.
Fix: catch ReflectionTypeLoadException and use the partial Types()
list (the successfully-resolved subset); also catch broader assembly
load failures (FileNotFoundException, etc.) with continue. The fix
is best-effort: the user-settings populating loop and the final
RegisterBilling<> calls are both after the reflective phase and run
independently of what was (or wasn't) successfully loaded.
ConfigureBillingService() walks AppDomain.CurrentDomain.GetAssemblies() and calls Assembly.GetTypes() on each. If any of the loaded assemblies has a type that fails to resolve (a flaky dependency, an AddOn with a broken reference, a test dependency that's been rewritten after compile), GetTypes() throws ReflectionTypeLoadException (or, less commonly, FileNotFoundException / TypeLoadException for the assembly itself). In CI on the forgejo-runner (and especially in test discovery under xunit v3), one such assembly is loaded somewhere between test runs and silently throws. The exception is not handled, so: 1. Collections are Cleared at the top of ConfigureBillingService(). 2. The reflection loop throws before reaching the RegisterBilling<HairCutQuery/HairMultiCutQuery/RdvQuery> calls. 3. BillingService.Billing ends up empty (Count = 0). 4. The second ConfigureBillingService() call sees the same assembly loaded (xunit v3 keeps the AppDomain warm for the whole suite), throws identically, and the test Yavsc.BillingServiceTests.ConfigureBillingService_CanBeCalledTwiceWithoutThrowing fails with 'Assert.Equal() Failure: Expected 3, Actual 0'. Fix: catch ReflectionTypeLoadException and use the partial .Types() list (the successfully-resolved subset), and use a broader catch (with continue) for any other assembly-level load failure. The lost user-settings types are not material; they are derived from ApplicationDbContext in a separate loop right after, and the RegisterBilling<>() calls that populate BillingService.Billing run last, after both reflective phases have completed best-effort. The test still passes locally because the local test environment loads a clean set of assemblies; only the CI runner (with its extra test-time tooling) hits this path.MERGE