Creating + disposing an HttpClient per call is the well-known socket-exhaustion anti-pattern: each disposed client leaves its underlying connection in TIME_WAIT, and under sustained callback volume the host runs out of ephemeral ports. The Scheduler host does not register IHttpClientFactory.
Fix
Add services.AddHttpClient() to the Scheduler host (registers IHttpClientFactory).
Inject IHttpClientFactory into both runners; replace new HttpClient() with _httpClientFactory.CreateClient() (per-call Timeout still set on the returned client). The factory pools and rotates handlers, eliminating the leak.
Acceptance
No new HttpClient() in the Scheduler task runners; both use IHttpClientFactory.CreateClient().
Behaviour unchanged (same timeouts, same requests).
## Problem
`SpikerSoft.EventHandlers.Scheduler` registers its task runners as **singletons**, but they `new HttpClient()` (in a `using`) on **every** `ExecuteAsync`:
- `TaskRunners/HttpCallbackTaskRunner.cs:33` — runs per scheduled HTTP callback (potentially frequent)
- `TaskRunners/GeoIpUpdateTaskRunner.cs:58` — periodic MaxMind download
Creating + disposing an `HttpClient` per call is the well-known socket-exhaustion anti-pattern: each disposed client leaves its underlying connection in `TIME_WAIT`, and under sustained callback volume the host runs out of ephemeral ports. The Scheduler host does **not** register `IHttpClientFactory`.
## Fix
- Add `services.AddHttpClient()` to the Scheduler host (registers `IHttpClientFactory`).
- Inject `IHttpClientFactory` into both runners; replace `new HttpClient()` with `_httpClientFactory.CreateClient()` (per-call `Timeout` still set on the returned client). The factory pools and rotates handlers, eliminating the leak.
## Acceptance
- No `new HttpClient()` in the Scheduler task runners; both use `IHttpClientFactory.CreateClient()`.
- Behaviour unchanged (same timeouts, same requests).
Refs #411 (resource-leak availability bombs).
Resolved in spikersoft-backend PR #113 (merged to master). Registered IHttpClientFactory in the Scheduler host and switched HttpCallbackTaskRunner + GeoIpUpdateTaskRunner to CreateClient() (pooled handlers) instead of new HttpClient() per execution. Guarded by SchedulerTaskRunnerHttpClientFactoryTests + the existing registry tests. Closing.
Resolved in spikersoft-backend PR #113 (merged to `master`). Registered `IHttpClientFactory` in the Scheduler host and switched `HttpCallbackTaskRunner` + `GeoIpUpdateTaskRunner` to `CreateClient()` (pooled handlers) instead of `new HttpClient()` per execution. Guarded by `SchedulerTaskRunnerHttpClientFactoryTests` + the existing registry tests. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
SpikerSoft.EventHandlers.Schedulerregisters its task runners as singletons, but theynew HttpClient()(in ausing) on everyExecuteAsync:TaskRunners/HttpCallbackTaskRunner.cs:33— runs per scheduled HTTP callback (potentially frequent)TaskRunners/GeoIpUpdateTaskRunner.cs:58— periodic MaxMind downloadCreating + disposing an
HttpClientper call is the well-known socket-exhaustion anti-pattern: each disposed client leaves its underlying connection inTIME_WAIT, and under sustained callback volume the host runs out of ephemeral ports. The Scheduler host does not registerIHttpClientFactory.Fix
services.AddHttpClient()to the Scheduler host (registersIHttpClientFactory).IHttpClientFactoryinto both runners; replacenew HttpClient()with_httpClientFactory.CreateClient()(per-callTimeoutstill set on the returned client). The factory pools and rotates handlers, eliminating the leak.Acceptance
new HttpClient()in the Scheduler task runners; both useIHttpClientFactory.CreateClient().Refs #411 (resource-leak availability bombs).
Resolved in spikersoft-backend PR #113 (merged to
master). RegisteredIHttpClientFactoryin the Scheduler host and switchedHttpCallbackTaskRunner+GeoIpUpdateTaskRunnertoCreateClient()(pooled handlers) instead ofnew HttpClient()per execution. Guarded bySchedulerTaskRunnerHttpClientFactoryTests+ the existing registry tests. Closing.