Skip to content

feat: enable connection pooling via shared http.Client and reuse RealtimeStore across GTFS functions - #77

Merged
aaronbrethorst merged 11 commits into
OneBusAway:mainfrom
0xaboomar:refactor/reuse-http-client-realtime-store
Aug 8, 2025
Merged

aaronbrethorst merged 11 commits into
OneBusAway:mainfrom
0xaboomar:refactor/reuse-http-client-realtime-store

Conversation

@0xaboomar

Copy link
Copy Markdown
Member

This PR introduces the following major refactors:

  • Create and configure a shared http.Client with connection pooling to be reused across the application.
  • Encapsulate GTFS-RT data into a thread-safe RealtimeStore struct.
  • Ensure realtime data is fetched once per server and passed to all dependent functions (e.g., telemetry, invalid vehicles, out-of-bounds tracking).
  • Remove redundant GTFS-RT API calls and centralize fetch-and-parse logic in FetchAndStoreGTFSRTFeed.

To Do:

  • The Go SDK provides its own HTTP client for GetAgenciesWithCoverage; explore whether it can be configured to reuse connections via a shared http.Transport or injected client.

@0xaboomar
0xaboomar force-pushed the refactor/reuse-http-client-realtime-store branch from a5167a1 to b909208 Compare July 26, 2025 15:41
@coveralls

coveralls commented Jul 26, 2025 •

Copy link
Copy Markdown

Coverage Status

coverage: 49.204% (-5.0%) from 54.223%
when pulling 89289fd on Abo-Omar-74:refactor/reuse-http-client-realtime-store
into fb33cf1 on OneBusAway:main.

@0xaboomar 0xaboomar changed the title feat: use shared http.Client and RealtimeStore across GTFS functions feat: enable connection pooling via shared http.Client and reuse RealtimeStore across GTFS functions Jul 26, 2025
@aaronbrethorst
aaronbrethorst requested a review from Copilot July 26, 2025 22:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements connection pooling and realtime data sharing to eliminate redundant GTFS-RT API calls. The refactor centralizes GTFS-RT data fetching and enables multiple functions to reuse the same parsed data.

  • Creates a shared HTTP client with connection pooling for improved performance across all API calls
  • Introduces thread-safe RealtimeStore to share parsed GTFS-RT data between functions
  • Refactors metrics collection to fetch GTFS-RT data once and pass it to dependent functions

Reviewed Changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
internal/utils/helpers.go Adds GTFS-RT data hashing utility for test validation
internal/utils/customTime.go Adds custom time type with YYYYMMDD JSON marshaling
internal/utils/cache.go Adds generic file I/O functions for map serialization
internal/gtfs/realtime_store.go Creates thread-safe store for sharing GTFS-RT data
internal/gtfs/gtfs_bundles.go Refactors GTFS-RT fetching to store data and extract service date logic
internal/metrics/gtfs-realtime-bindings.go Updates functions to use shared realtime store and vehicle tracking
internal/app/client.go Implements pooled HTTP client with optimized connection settings
internal/app/app.go Adds new dependencies to application structure
cmd/watchdog/main.go Integrates new components and context-based lifecycle management
Comments suppressed due to low confidence (1)

internal/utils/customTime.go:8

  • The constant name YYYYMMDD should follow Go naming conventions and be either exported (capitalized) or unexported (lowercase). Since it's used only within this package, consider renaming it to 'yyyymmdd' or if it needs to be exported, add a comment explaining its purpose.
const YYYYMMDD = "20060102"

Comment thread internal/utils/helpers.go Outdated
Comment thread internal/metrics/gtfs-realtime-bindings_test.go Outdated
Comment thread internal/metrics/gtfs-realtime-bindings_test.go Outdated
Comment thread internal/metrics/gtfs-realtime-bindings_test.go Outdated
Comment thread internal/metrics/gtfs-realtime-bindings.go Outdated
Comment thread internal/config/config.go Outdated
Comment thread internal/config/config.go Outdated
Comment thread internal/config/config.go Outdated
Comment thread internal/app/app.go Outdated
Comment thread cmd/watchdog/main.go Outdated
@aaronbrethorst

Copy link
Copy Markdown
Member

@Abo-Omar-74 Be sure to run go fmt ./...!

@0xaboomar

Copy link
Copy Markdown
Member Author

I have applied Copilot's suggestions

@0xaboomar
0xaboomar force-pushed the refactor/reuse-http-client-realtime-store branch from 2a9c3b4 to 054dc49 Compare July 27, 2025 04:46
- add `NewPooledClient` to configure reusable HTTP client for periodic API polling
- add `RealtimeStore` to cache GTFS-RT data and avoid redundant API calls
- inject `Client` and `RealtimeStore` into `Application` struct for shared access
- add `NewPooledClient` to configure efficient HTTP client for polling APIs
- add `NewRealtimeStore` to hold parsed GTFS-RT data safely across goroutines
- inject both into `Application` struct for reuse across handlers
- use `Client` in `LoadConfigFromURL` to fetch remote config using shared client
- fetch GTFS-RT data once in FetchObaAPIMetrics and store it in RealtimeStore
- pass RealtimeStore to FetchAndStoreGTFSRTFeed, CheckVehicleCountMatch,
  TrackVehicleTelemetry, and TrackInvalidVehiclesAndStoppedOutOfBounds
- avoids redundant API calls and ensures consistent data across checks
…nfig

- update function signatures to accept *http.Client as argument
- update test files to pass the client explicitly when calling these functions
…S-RT data

- CountVehiclePositions, TrackVehicleTelemetry, and TrackInvalidVehiclesAndStoppedOutOfBounds now read from RealtimeStore
- avoids redundant API calls by relying on previously fetched GTFS-RT data
- update tests: add TestMain to initialize and share RealtimeStore across related metric tests
- Relocates setupGtfsRtServer, getFixturePath, and readFixture to gtfs for reuse
…GTFSRTFeed

- pass shared *http.Client and *RealtimeStore to avoid redundant API calls
- update function signature to support external dependency injection
- replaces old FetchGTFSRTFeed with unified FetchAndStoreGTFSRTFeed
- update test logic and function signature
- add HashRealtimeData helper for deterministic equality in tests of FetchAndStoreGTFSRTFeed
@0xaboomar
0xaboomar force-pushed the refactor/reuse-http-client-realtime-store branch from 054dc49 to 880b478 Compare July 27, 2025 06:41
- Adds a Prometheus histogram metric named `http_outgoing_request_duration_seconds`
to track the duration (in seconds) of outgoing HTTP requests to external APIs.
- Wraps HTTP transport with latencyTrackingRoundTripper
- Records duration of outgoing requests using Prometheus histogram
- Labels metrics by normalized URL, HTTP method, and status code
- Enables visibility into external API response times
@0xaboomar
0xaboomar force-pushed the refactor/reuse-http-client-realtime-store branch from 89e4b85 to 89289fd Compare July 29, 2025 09:45
@0xaboomar

Copy link
Copy Markdown
Member Author

Follow Up

Add internal performance metrics

The changes introduce internal latency instrumentation for outgoing HTTP requests to external APIs and improve visibility into memory usage. These metrics enhance observability without adding significant system load.

Tracking external API Response Times

  • Added latencyTrackingRoundTripper to wrap the HTTP transport and measure request duration.
  • Introduced http_outgoing_request_duration_seconds Prometheus histogram, labeled by URL, method, and status code.
  • Integrated the instrumented transport into the pooled HTTP client used across the app.

Memory Usage Tracking

Memory usage is tracked via Prometheus's default /metrics handler, utilizing Go’s built-in metrics, which update as the application runs, eliminating the need for a custom polling goroutine.

@aaronbrethorst aaronbrethorst left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work 👍

@aaronbrethorst
aaronbrethorst merged commit 14006a8 into OneBusAway:main Aug 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants