Skip to content

refactor: consolidate HTTP clients and improve error handling#60

Merged
JanZachmann merged 4 commits intoomnect:mainfrom
JanZachmann:refactor-http-clients
Nov 7, 2025
Merged

refactor: consolidate HTTP clients and improve error handling#60
JanZachmann merged 4 commits intoomnect:mainfrom
JanZachmann:refactor-http-clients

Conversation

@JanZachmann
Copy link
Contributor

@JanZachmann JanZachmann commented Oct 26, 2025

Summary

This PR consolidates HTTP client creation logic and improves error handling:

  • Centralized Unix socket client creation: New http_client module with unix_socket_client() function that handles both raw paths and unix:// URIs
  • Socket path validation: Added existence check using try_exists() to catch I/O errors before client creation
  • Simplified KeycloakProvider: Replaced global OnceLock singleton with instance field for HTTPS client
  • Improved shutdown sequence: improve shutdown sequence consistency and error handling
  • Comprehensive test coverage: Added integration tests for Unix socket client functionality (3 integration tests + 2 unit tests)

Key Changes

HTTP Client Consolidation

  • Created src/http_client.rs with standalone unix_socket_client() function
  • Handles both raw paths (/socket/api.sock) and URIs (unix:///socket/api.sock)
  • Validates socket existence before creating client to provide early error feedback

Improve shutdown sequence. Problems addressed:

  • Inconsistent cleanup across different shutdown paths (ctrl-c, SIGTERM, server crash, centrifugo crash)
  • Race conditions between service client shutdown and centrifugo termination
  • Mixed error handling (panics vs logging)
  • No guaranteed cleanup order

KeycloakProvider Refactoring

  • Moved HTTPS client from global singleton to instance field
  • KeycloakProvider now owns its reqwest::Client
  • Eliminates global state and improves testability

Test Improvements

  • Added comprehensive unit and integration tests for Unix socket client

Testing

@JanZachmann JanZachmann force-pushed the refactor-http-clients branch 3 times, most recently from 690bb43 to d17f6d4 Compare November 1, 2025 14:12
Problems addressed:
- Inconsistent cleanup across different shutdown paths (ctrl-c, SIGTERM, server crash, centrifugo crash)
- Race conditions between service client shutdown and centrifugo termination
- Mixed error handling (panics vs logging)
- No guaranteed cleanup order

Solution:
- Unified shutdown sequence that runs regardless of exit reason
- Consistent cleanup order: service client → server → centrifugo
- Graceful error handling throughout (no panics)
- Clear debug logging at each step

Benefits:
- Predictable shutdown behavior in all scenarios
- Proper resource cleanup guaranteed
- Better observability with consistent logging
- Safer error handling

Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
JanZachmann added a commit to JanZachmann/omnect-ui that referenced this pull request Nov 6, 2025
This commit addresses all review findings from PR omnect#60 and includes
additional improvements to code quality and test coverage.

Changes:
- Move HTTPS client from global state to KeycloakProvider
  * Remove global HTTPS_CLIENT static variable
  * Add client field to KeycloakProvider struct
  * Move realm_public_key() into KeycloakProvider as instance method

- Refactor workload_client() to use unix_socket_client()
  * Remove duplicate socket client creation logic
  * Delegate to unix_socket_client() after URI parsing

- Improve test quality and clarity
  * Remove redundant HTTPS client tests (no longer testing our code)
  * Remove redundant URI validation tests (covered by unit tests)
  * Remove tests that verify reqwest behavior rather than our code
  * Add clarifying comments to tests about socket existence
  * Fix error message assertion to use exact match

- Replace sleep() with oneshot channels in integration tests
  * Deterministic synchronization instead of arbitrary timeouts
  * 40x faster test execution (0.41s → 0.01s)
  * Eliminates potential race conditions

Test suite improvements:
- Reduced from 14 to 4 integration tests
- All remaining tests are meaningful and test actual functionality
- Clear separation between unit tests and integration tests
- Zero clippy warnings, all tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@JanZachmann JanZachmann requested a review from empwilli November 6, 2025 08:59
Copy link
Contributor

@empwilli empwilli left a comment

Choose a reason for hiding this comment

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

LGTM; still unhappy with the error situation of the socket factory, though :)

@JanZachmann JanZachmann force-pushed the refactor-http-clients branch 2 times, most recently from 16782c1 to 49335ef Compare November 6, 2025 15:45
@JanZachmann JanZachmann changed the title refactor: consolidate HTTP client creation with factory pattern refactor: consolidate HTTP clients and improve error handling Nov 6, 2025
@JanZachmann JanZachmann force-pushed the refactor-http-clients branch from 49335ef to dd95854 Compare November 6, 2025 16:06
@JanZachmann JanZachmann requested a review from empwilli November 6, 2025 16:10
JanZachmann added a commit to JanZachmann/omnect-ui that referenced this pull request Nov 6, 2025
This commit addresses all review findings from PR omnect#60 and includes
additional improvements to code quality and test coverage.

Changes:
- Move HTTPS client from global state to KeycloakProvider
  * Remove global HTTPS_CLIENT static variable
  * Add client field to KeycloakProvider struct
  * Move realm_public_key() into KeycloakProvider as instance method

- Refactor workload_client() to use unix_socket_client()
  * Remove duplicate socket client creation logic
  * Delegate to unix_socket_client() after URI parsing

- Improve test quality and clarity
  * Remove redundant HTTPS client tests (no longer testing our code)
  * Remove redundant URI validation tests (covered by unit tests)
  * Remove tests that verify reqwest behavior rather than our code
  * Add clarifying comments to tests about socket existence
  * Fix error message assertion to use exact match

- Replace sleep() with oneshot channels in integration tests
  * Deterministic synchronization instead of arbitrary timeouts
  * 40x faster test execution (0.41s → 0.01s)
  * Eliminates potential race conditions

Test suite improvements:
- Reduced from 14 to 4 integration tests
- All remaining tests are meaningful and test actual functionality
- Clear separation between unit tests and integration tests
- Zero clippy warnings, all tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@JanZachmann JanZachmann force-pushed the refactor-http-clients branch from dd95854 to b55afda Compare November 6, 2025 17:57
JanZachmann and others added 3 commits November 6, 2025 19:07
This commit introduces HttpClientFactory to centralize HTTP client creation,
eliminating code duplication and ensuring consistent configuration.

New Module: http_client.rs
- HttpClientFactory with three client types:
  - https_client(): Cached HTTPS client for external APIs
  - unix_socket_client(): For local Unix socket communication
  - workload_client(): For IoT Edge workload API

Testing:
- Unit tests: 8 tests covering all three client factory methods
  - test_https_client_is_cached
  - test_https_client_returns_valid_client
  - test_https_client_multiple_calls_same_instance
  - test_workload_client_parses_uri
  - test_workload_client_rejects_invalid_scheme
  - test_unix_socket_client_creates_client
  - test_unix_socket_client_with_relative_path
  - test_unix_socket_client_with_empty_path

- Integration tests: 14 tests in tests/http_client.rs
  - 4 HTTPS tests (marked #[ignore] for reliability)
    - Uses httpbin.org endpoints
    - 10-second timeouts prevent hanging
    - Run with --ignored flag when network available
  - 4 Unix socket tests (always run, use mock servers)
  - 4 Workload client tests (always run, use mock IoT Edge API)
  - 2 error handling tests (HTTPS connection failures)

  Test Reliability: External network tests are ignored by default to prevent
  CI failures from network issues. Local tests (Unix socket, workload client)
  always run and provide core functionality validation.

- Test configuration: Added .cargo/config.toml
  - Set RUST_TEST_THREADS=1 to prevent rate-limiting issues
  - Ensures reliable test execution for external API tests

- Fixed dead_code warning for workload_client when using mock feature
  by adding #[cfg_attr(feature = "mock", allow(dead_code))]

Benefits:
- Eliminates 3 separate OnceLock instances across modules
- Single source of truth for HTTP client configuration
- Shared connection pools improve performance
- Easier to add timeout/retry configuration in future
- Better testability with centralized mocking point
- Comprehensive test coverage with reliable CI execution

Changes by Module:
- keycloak_client.rs: Use HttpClientFactory::https_client()
  - Removed local OnceLock<Client>
  - 4 lines removed, cleaner code

- omnect_device_service_client.rs: Use HttpClientFactory::unix_socket_client()
  - Simplified client creation
  - 3 lines removed

- certificate.rs: Use HttpClientFactory::workload_client()
  - Removed manual URI parsing
  - 8 lines removed, moved to factory

Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
This commit addresses all review findings from PR omnect#60 and includes
additional improvements to code quality and test coverage.

Changes:
- Move HTTPS client from global state to KeycloakProvider
  * Remove global HTTPS_CLIENT static variable
  * Add client field to KeycloakProvider struct
  * Move realm_public_key() into KeycloakProvider as instance method

- Refactor workload_client() to use unix_socket_client()
  * Remove duplicate socket client creation logic
  * Delegate to unix_socket_client() after URI parsing

- Improve test quality and clarity
  * Remove redundant HTTPS client tests (no longer testing our code)
  * Remove redundant URI validation tests (covered by unit tests)
  * Remove tests that verify reqwest behavior rather than our code
  * Add clarifying comments to tests about socket existence
  * Fix error message assertion to use exact match

- Replace sleep() with oneshot channels in integration tests
  * Deterministic synchronization instead of arbitrary timeouts
  * 40x faster test execution (0.41s → 0.01s)
  * Eliminates potential race conditions

Test suite improvements:
- Reduced from 14 to 4 integration tests
- All remaining tests are meaningful and test actual functionality
- Clear separation between unit tests and integration tests
- Zero clippy warnings, all tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@JanZachmann JanZachmann force-pushed the refactor-http-clients branch from b55afda to 9e0df27 Compare November 6, 2025 18:08
JanZachmann added a commit to JanZachmann/omnect-ui that referenced this pull request Nov 6, 2025
This commit addresses all review findings from PR omnect#60 and includes
additional improvements to code quality and test coverage.

Changes:
- Move HTTPS client from global state to KeycloakProvider
  * Remove global HTTPS_CLIENT static variable
  * Add client field to KeycloakProvider struct
  * Move realm_public_key() into KeycloakProvider as instance method

- Refactor workload_client() to use unix_socket_client()
  * Remove duplicate socket client creation logic
  * Delegate to unix_socket_client() after URI parsing

- Improve test quality and clarity
  * Remove redundant HTTPS client tests (no longer testing our code)
  * Remove redundant URI validation tests (covered by unit tests)
  * Remove tests that verify reqwest behavior rather than our code
  * Add clarifying comments to tests about socket existence
  * Fix error message assertion to use exact match

- Replace sleep() with oneshot channels in integration tests
  * Deterministic synchronization instead of arbitrary timeouts
  * 40x faster test execution (0.41s → 0.01s)
  * Eliminates potential race conditions

Test suite improvements:
- Reduced from 14 to 4 integration tests
- All remaining tests are meaningful and test actual functionality
- Clear separation between unit tests and integration tests
- Zero clippy warnings, all tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Contributor

@empwilli empwilli left a comment

Choose a reason for hiding this comment

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

LGTM

@JanZachmann JanZachmann merged commit 6cd6880 into omnect:main Nov 7, 2025
2 checks passed
@JanZachmann JanZachmann deleted the refactor-http-clients branch December 18, 2025 08:44
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.

3 participants