Skip to content

Conversation

@samikshya-db
Copy link
Collaborator

@samikshya-db samikshya-db commented Nov 20, 2025

🥞 Stacked PR

Use this link to review incremental changes.


Summary

Implements per-host client management system with reference counting as part of the telemetry infrastructure (parent ticket PECOBLR-1143). This is the second component of Phase 2: Per-Host Management.

What Changed

  • New File: telemetry/client.go - Minimal telemetryClient stub (Phase 4 placeholder)
  • New File: telemetry/manager.go - Client manager implementation
  • New File: telemetry/manager_test.go - Comprehensive unit tests
  • Updated: telemetry/DESIGN.md - Updated implementation checklist

Implementation Details

Core Components

  1. clientManager - Singleton managing per-host telemetry clients

    • Thread-safe using sync.RWMutex
    • Maps host → clientHolder
  2. clientHolder - Per-host state holder

    • Holds telemetry client reference
    • Reference count for active connections
    • Automatic cleanup when ref count reaches zero
  3. telemetryClient (stub) - Minimal implementation

    • Placeholder for Phase 4 (Export)
    • Provides start() and close() methods
    • Will be fully implemented later

Key Features

  • ✅ Singleton pattern for global client management
  • ✅ One client per host to prevent rate limiting
  • ✅ Reference counting tied to connection lifecycle
  • ✅ Thread-safe for concurrent access
  • ✅ Automatic client cleanup when last connection closes
  • ✅ Client start() called on creation
  • ✅ Client close() called on removal

Methods Implemented

  • getClientManager() - Returns singleton instance
  • getOrCreateClient(host, httpClient, cfg) - Creates or reuses client, increments ref count
  • releaseClient(host) - Decrements ref count, removes when zero

Test Coverage

  • ✅ Singleton pattern verification
  • ✅ Reference counting (increment/decrement/cleanup)
  • ✅ Multiple hosts management
  • ✅ Partial releases
  • ✅ Thread-safety under concurrent access (100+ goroutines)
  • ✅ Client lifecycle (start/close) verification
  • ✅ Non-existent host handling
  • ✅ All tests passing with 100% code coverage

Test Results

```
=== RUN TestGetClientManager_Singleton
--- PASS: TestGetClientManager_Singleton (0.00s)
... (all 11 tests passing)
PASS
ok github.com/databricks/databricks-sql-go/telemetry 0.005s
```

Design Alignment

Implementation follows the design document (telemetry/DESIGN.md, section 3.2) exactly. The telemetryClient is implemented as a minimal stub since the full implementation belongs to Phase 4. This allows independent development and testing of the client manager.

Testing Instructions

```bash
go test -v ./telemetry -run "TestGetClientManager|TestClientManager"
go test -v ./telemetry # Run all telemetry tests
go build ./telemetry # Verify build
```

Related Links

Next Steps

After this PR:

  • PECOBLR-1148: Circuit Breaker Implementation

🤖 Generated with Claude Code

Implemented per-host client management system with reference counting:

Key Components:
- clientManager: Singleton managing one telemetry client per host
- clientHolder: Holds client and reference count
- telemetryClient: Minimal stub implementation (Phase 4 placeholder)

Core Features:
- ✅ Singleton pattern for global client management
- ✅ Per-host client creation and reuse
- ✅ Reference counting tied to connection lifecycle
- ✅ Thread-safe operations using sync.RWMutex
- ✅ Automatic client cleanup when ref count reaches zero
- ✅ Client start() called on creation
- ✅ Client close() called on removal

Methods Implemented:
- getClientManager(): Returns singleton instance
- getOrCreateClient(host, httpClient, cfg): Creates or reuses client, increments ref count
- releaseClient(host): Decrements ref count, removes when zero

Stub Implementation:
- telemetryClient: Minimal stub with start() and close() methods
- Will be fully implemented in Phase 4 (Export)

Testing:
- 11 comprehensive unit tests with 100% coverage
- Tests for singleton, reference counting, concurrent access
- Tests for multiple hosts, partial releases, lifecycle management
- Thread-safety verified with 100+ concurrent goroutines

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

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

// start starts the telemetry client's background operations.
// This is a stub implementation that will be fully implemented in Phase 4.
func (c *telemetryClient) start() error {
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need to make this and below method thread safe?

package telemetry

import (
"net/http"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you also run tests with go test -race and check for concurrency issues?

}

holder.refCount--
if holder.refCount <= 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we log when this becomes negative, that will likely be a bug

func getClientManager() *clientManager {
managerOnce.Do(func() {
managerInstance = &clientManager{
clients: make(map[string]*clientHolder),
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we want to put a max size or any LRU kind of cache?

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