nntppool

package module
v2.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 2, 2026 License: MIT Imports: 24 Imported by: 0

README

nntppool

A nntp pool connection with retry and provider rotation.

Features

  • Connection pooling
  • Body download retry and yenc decode
  • Post article with retry and yenc encode
  • Stat article with retry
  • TLS support
  • Multiple providers with rotation. In case of failure for article not found the provider will be rotated.
  • Backup providers. If all providers fail, the backup provider will be used for download. Useful for block accounts usage.
  • Dynamic reconfiguration - Update provider settings, add/remove providers, or change connection limits without interrupting service
  • Intelligent metrics system - Comprehensive metrics with rolling windows, automatic cleanup, and memory management to prevent infinite growth

Installation

To install the nntppool package, you can use go get:

go get github.com/javi11/nntppool/v2

Since this package uses Rapidyenc, you will need to build it with CGO enabled

Usage Example

package main

import (
    "context"
    "log"
    "os"
    "time"

    "github.com/javi11/nntppool/v2"
)

func main() {
    // Configure the connection pool
    config := nntppool.Config{
        MinConnections: 5,
        MaxRetries:    3,
        Providers: []nntppool.UsenetProviderConfig{
            {
                Host:                          "news.example.com",
                Port:                          119,
                Username:                      "user",
                Password:                      "pass",
                MaxConnections:                10,
                MaxConnectionIdleTimeInSeconds: 300,
                TLS:                           false,
            },
            {
                Host:                          "news-backup.example.com",
                Port:                          119,
                Username:                      "user",
                Password:                      "pass",
                MaxConnections:                5,
                MaxConnectionIdleTimeInSeconds: 300,
                TLS:                           true,
                IsBackupProvider:              true,
            },
        },
    }

    // Create a new connection pool
    pool, err := nntppool.NewConnectionPool(config)
    if err != nil {
        log.Fatal(err)
    }
    defer pool.Quit()

    // Example: Download an article
    ctx := context.Background()
    msgID := "<example-message-id@example.com>"
    file, err := os.Create("article.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    written, err := pool.Body(ctx, msgID, file, nil)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Downloaded %d bytes", written)

    // Example: Post an article
    article, err := os.Open("article.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer article.Close()

    err = pool.Post(ctx, article)
    if err != nil {
        log.Fatal(err)
    }

    // Example: Check if an article exists
    msgNum, err := pool.Stat(ctx, msgID, []string{"alt.binaries.test"})
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Article number: %d", msgNum)
}
Best Practices
  • Monitor Progress: Always check reconfiguration status, especially in production
  • Gradual Changes: Make incremental changes rather than large configuration overhauls
  • Error Handling: Handle reconfiguration errors gracefully and consider rollback strategies
  • Testing: Test configuration changes in development before applying to production

Metrics System

The connection pool includes a comprehensive metrics system that provides detailed insights into connection pool performance while intelligently managing memory usage to prevent infinite growth over time.

Key Features
  • Rolling Time Windows: Metrics are organized into configurable time windows (default: 1 hour)
  • Automatic Cleanup: Old metrics are automatically cleaned up based on retention policies
  • Memory Management: Built-in memory monitoring with configurable thresholds and automatic cleanup
  • Connection Tracking: Automatic detection and cleanup of stale connections
  • Data Compression: Historical data is compressed into summaries for long-term storage
  • Real-time Monitoring: Live metrics for active connections and pool performance
Getting Metrics
// Get comprehensive metrics snapshot
snapshot := pool.GetMetrics()

fmt.Printf("Active connections: %d\n", snapshot.ActiveConnections)
fmt.Printf("Total bytes downloaded: %d\n", snapshot.TotalBytesDownloaded)
fmt.Printf("Download speed: %.2f bytes/sec\n", snapshot.DownloadSpeed)
fmt.Printf("Error rate: %.2f%%\n", snapshot.ErrorRate)
fmt.Printf("Memory usage: %d bytes\n", snapshot.CurrentMemoryUsage)

// Check daily and weekly summaries
if snapshot.DailySummary != nil {
    fmt.Printf("Daily summary: %d connections created\n", snapshot.DailySummary.TotalConnectionsCreated)
}

if snapshot.WeeklySummary != nil {
    fmt.Printf("Weekly average: %.2f connections/hour\n", snapshot.WeeklySummary.AverageConnectionsPerHour)
}
Configuring Metrics Retention
// Configure metrics retention policy
config := nntppool.MetricRetentionConfig{
    DetailedRetentionDuration: 48 * time.Hour,        // Keep detailed metrics for 2 days
    RotationInterval:          30 * time.Minute,      // Create new windows every 30 minutes
    MaxHistoricalWindows:      96,                    // Keep 96 windows (2 days of 30-min windows)
    MemoryThresholdBytes:      50 * 1024 * 1024,      // Trigger cleanup at 50MB
    AutoCleanupEnabled:        true,                  // Enable automatic cleanup
}

// Apply the configuration
metrics := pool.GetMetricsInstance() // You'll need to expose this method
metrics.SetRetentionConfig(config)
Manual Maintenance
// Perform manual cleanup and rotation check
metrics.PerformRotationCheck()

// Force connection cleanup
staleCount := metrics.ForceConnectionCleanup()
fmt.Printf("Cleaned up %d stale connections\n", staleCount)

// Get system status
status := metrics.GetRollingMetricsStatus()
fmt.Printf("Current window: %v to %v\n", status.CurrentWindowStartTime, status.CurrentWindowEndTime)
fmt.Printf("Historical windows: %d/%d\n", status.HistoricalWindowCount, status.MaxHistoricalWindows)

memory := metrics.GetMemoryUsage()
fmt.Printf("Memory: %d/%d bytes (%.1f%%)\n",
    memory.AllocatedBytes,
    memory.ThresholdBytes,
    float64(memory.AllocatedBytes)/float64(memory.ThresholdBytes)*100)
Metrics Available

The system tracks comprehensive metrics including:

Connection Metrics:

  • Total connections created/destroyed
  • Active connection count
  • Connection acquire/release operations
  • Connection age and lifecycle

Performance Metrics:

  • Download/upload speeds (recent and historical)
  • Command success rates
  • Error rates and retry counts
  • Acquire wait times

Traffic Metrics:

  • Bytes downloaded/uploaded
  • Articles retrieved/posted
  • Command counts and errors

System Metrics:

  • Memory usage and thresholds
  • Rolling window status
  • Connection cleanup statistics
  • Provider-specific metrics
Automatic Cleanup Behavior

The metrics system automatically:

  1. Rotates windows when time periods expire (e.g., every hour)
  2. Monitors memory usage every 5 minutes by default
  3. Cleans up stale connections every 30 seconds
  4. Compresses old data when retention periods are exceeded
  5. Triggers aggressive cleanup when memory thresholds are reached

This ensures that long-running applications maintain stable memory usage while preserving useful historical data for analysis and monitoring.

Development Setup

To set up the project for development, follow these steps:

  1. Clone the repository:
git clone https://github.com/javi11/nntppool/v2.git
cd nntppool
  1. Install dependencies:
go mod download
  1. Run tests:
make test
  1. Lint the code:
make lint
  1. Generate mocks and other code:
make generate

Contributing

Contributions are welcome! Please open an issue or submit a pull request. See the CONTRIBUTING.md file for details.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Documentation

Overview

Package nntppool is a generated GoMock package.

Package nntppool provides a connection pooling mechanism for NNTP connections.

Package nntppool is a generated GoMock package.

Index

Constants

View Source
const (
	SegmentAlreadyExistsErrCode = 441
	ToManyConnectionsErrCode    = 502
	ArticleNotFoundErrCode      = 430
	CanNotJoinGroup             = 411
	AuthenticationRequiredCode  = 401
	AuthenticationFailedCode    = 403
	InvalidUsernamePasswordCode = 480
)

Variables

View Source
var (
	ErrCapabilitiesUnpopulated    = errors.New("capabilities unpopulated")
	ErrNoSuchCapability           = errors.New("no such capability")
	ErrNilNntpConn                = errors.New("nil nntp connection")
	ErrNoProviderAvailable        = errors.New("no provider available, because possible max connections reached")
	ErrArticleNotFoundInProviders = errors.New("the article is not found in any of your providers")
	ErrFailedToPostInAllProviders = errors.New("failed to post in all providers")
	ErrConnectionPoolShutdown     = errors.New("connection pool is shutdown")
)

Functions

func ExampleMetricsUsage

func ExampleMetricsUsage()

ExampleMetricsUsage demonstrates how to use the simplified pool metrics system

func MonitoringExample

func MonitoringExample()

MonitoringExample shows how to implement continuous metrics monitoring

func PerformanceTrackingExample

func PerformanceTrackingExample()

PerformanceTrackingExample demonstrates tracking download/upload speeds by taking snapshots and calculating deltas

func ResetExample

func ResetExample()

ResetExample demonstrates optional Reset() functionality

func TestProviderConnectivity

func TestProviderConnectivity(ctx context.Context, config UsenetProviderConfig, logger Logger, client nntpcli.Client) error

TestProviderConnectivity tests connectivity to a provider without requiring a pool This is a standalone utility function that can be used independently If client is nil, a default NNTP client will be created

Types

type BodyBatchRequest added in v2.3.0

type BodyBatchRequest struct {
	// MessageID is the article message ID to retrieve.
	MessageID string
	// Writer is the destination for the decoded body content.
	Writer io.Writer
	// Discard is the number of bytes to discard from the beginning of the body.
	// Use 0 for full download.
	Discard int64
}

BodyBatchRequest represents a request in a batch download operation.

type BodyBatchResult added in v2.3.0

type BodyBatchResult struct {
	// MessageID is the article message ID that was requested.
	MessageID string
	// BytesWritten is the number of bytes written to the writer.
	BytesWritten int64
	// Error is any error that occurred during the request.
	// nil indicates success.
	Error error
	// ProviderHost is the host of the provider that served this request.
	ProviderHost string
}

BodyBatchResult represents the result of a batch download request.

type Config

type Config struct {
	Logger              Logger
	NntpCli             nntpcli.Client
	Providers           []UsenetProviderConfig
	HealthCheckInterval time.Duration
	MinConnections      int
	MaxRetries          uint
	DelayType           DelayType
	// Deprecated: now is always false
	SkipProvidersVerificationOnCreation bool
	RetryDelay                          time.Duration
	ShutdownTimeout                     time.Duration
	DrainTimeout                        time.Duration
	ForceCloseTimeout                   time.Duration
	DefaultConnectionLease              time.Duration
	ProviderReconnectInterval           time.Duration
	ProviderMaxReconnectInterval        time.Duration
	ProviderHealthCheckStagger          time.Duration
	ProviderHealthCheckTimeout          time.Duration
	NntpOperationTimeout                time.Duration
	// contains filtered or unexported fields
}

func (*Config) GetProviders

func (c *Config) GetProviders() []config.ProviderConfig

Adapter methods for internal package interfaces

type ConnectionProviderInfo

type ConnectionProviderInfo struct {
	Host           string        `json:"host"`
	Username       string        `json:"username"`
	MaxConnections int           `json:"maxConnections"`
	PipelineDepth  int           `json:"pipelineDepth"`
	State          ProviderState `json:"state"`
}

func (ConnectionProviderInfo) ID

type DelayType

type DelayType int
const (
	DelayTypeFixed DelayType = iota
	DelayTypeRandom
	DelayTypeExponential
)

type Logger

type Logger interface {
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)
	DebugContext(ctx context.Context, msg string, args ...any)
	InfoContext(ctx context.Context, msg string, args ...any)
	WarnContext(ctx context.Context, msg string, args ...any)
	ErrorContext(ctx context.Context, msg string, args ...any)
}

Logger interface compatible with slog.Logger

type MockPooledConnection

type MockPooledConnection struct {
	// contains filtered or unexported fields
}

MockPooledConnection is a mock of PooledConnection interface.

func NewMockPooledConnection

func NewMockPooledConnection(ctrl *gomock.Controller) *MockPooledConnection

NewMockPooledConnection creates a new mock instance.

func (*MockPooledConnection) Close

func (m *MockPooledConnection) Close() error

Close mocks base method.

func (*MockPooledConnection) Connection

func (m *MockPooledConnection) Connection() nntpcli.Connection

Connection mocks base method.

func (*MockPooledConnection) CreatedAt

func (m *MockPooledConnection) CreatedAt() time.Time

CreatedAt mocks base method.

func (*MockPooledConnection) EXPECT

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockPooledConnection) Free

func (m *MockPooledConnection) Free() error

Free mocks base method.

func (*MockPooledConnection) Provider

Provider mocks base method.

type MockPooledConnectionMockRecorder

type MockPooledConnectionMockRecorder struct {
	// contains filtered or unexported fields
}

MockPooledConnectionMockRecorder is the mock recorder for MockPooledConnection.

func (*MockPooledConnectionMockRecorder) Close

Close indicates an expected call of Close.

func (*MockPooledConnectionMockRecorder) Connection

func (mr *MockPooledConnectionMockRecorder) Connection() *gomock.Call

Connection indicates an expected call of Connection.

func (*MockPooledConnectionMockRecorder) CreatedAt

func (mr *MockPooledConnectionMockRecorder) CreatedAt() *gomock.Call

CreatedAt indicates an expected call of CreatedAt.

func (*MockPooledConnectionMockRecorder) Free

Free indicates an expected call of Free.

func (*MockPooledConnectionMockRecorder) Provider

Provider indicates an expected call of Provider.

type MockUsenetConnectionPool

type MockUsenetConnectionPool struct {
	// contains filtered or unexported fields
}

MockUsenetConnectionPool is a mock of UsenetConnectionPool interface.

func NewMockUsenetConnectionPool

func NewMockUsenetConnectionPool(ctrl *gomock.Controller) *MockUsenetConnectionPool

NewMockUsenetConnectionPool creates a new mock instance.

func (*MockUsenetConnectionPool) Body

func (m *MockUsenetConnectionPool) Body(ctx context.Context, msgID string, w io.Writer, nntpGroups []string) (int64, error)

Body mocks base method.

func (*MockUsenetConnectionPool) BodyBatch added in v2.3.0

func (m *MockUsenetConnectionPool) BodyBatch(ctx context.Context, group string, requests []BodyBatchRequest) []BodyBatchResult

BodyBatch mocks base method.

func (*MockUsenetConnectionPool) BodyReader

func (m *MockUsenetConnectionPool) BodyReader(ctx context.Context, msgID string, nntpGroups []string) (nntpcli.ArticleBodyReader, error)

BodyReader mocks base method.

func (*MockUsenetConnectionPool) EXPECT

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockUsenetConnectionPool) GetConnection

func (m *MockUsenetConnectionPool) GetConnection(ctx context.Context, skipProviders []string, useBackupProviders bool) (PooledConnection, error)

GetConnection mocks base method.

func (*MockUsenetConnectionPool) GetMetrics

func (m *MockUsenetConnectionPool) GetMetrics() *PoolMetrics

GetMetrics mocks base method.

func (*MockUsenetConnectionPool) GetMetricsSnapshot

func (m *MockUsenetConnectionPool) GetMetricsSnapshot() PoolMetricsSnapshot

GetMetricsSnapshot mocks base method.

func (*MockUsenetConnectionPool) GetProviderStatus

func (m *MockUsenetConnectionPool) GetProviderStatus(providerID string) (*ProviderInfo, bool)

GetProviderStatus mocks base method.

func (*MockUsenetConnectionPool) GetProvidersInfo

func (m *MockUsenetConnectionPool) GetProvidersInfo() []ProviderInfo

GetProvidersInfo mocks base method.

func (*MockUsenetConnectionPool) Post

Post mocks base method.

func (*MockUsenetConnectionPool) Quit

func (m *MockUsenetConnectionPool) Quit()

Quit mocks base method.

func (*MockUsenetConnectionPool) Stat

func (m *MockUsenetConnectionPool) Stat(ctx context.Context, msgID string, nntpGroups []string) (int, error)

Stat mocks base method.

func (*MockUsenetConnectionPool) TestProviderPipelineSupport added in v2.3.0

func (m *MockUsenetConnectionPool) TestProviderPipelineSupport(ctx context.Context, providerHost, testMsgID string) (bool, int, error)

TestProviderPipelineSupport mocks base method.

type MockUsenetConnectionPoolMockRecorder

type MockUsenetConnectionPoolMockRecorder struct {
	// contains filtered or unexported fields
}

MockUsenetConnectionPoolMockRecorder is the mock recorder for MockUsenetConnectionPool.

func (*MockUsenetConnectionPoolMockRecorder) Body

func (mr *MockUsenetConnectionPoolMockRecorder) Body(ctx, msgID, w, nntpGroups any) *gomock.Call

Body indicates an expected call of Body.

func (*MockUsenetConnectionPoolMockRecorder) BodyBatch added in v2.3.0

func (mr *MockUsenetConnectionPoolMockRecorder) BodyBatch(ctx, group, requests any) *gomock.Call

BodyBatch indicates an expected call of BodyBatch.

func (*MockUsenetConnectionPoolMockRecorder) BodyReader

func (mr *MockUsenetConnectionPoolMockRecorder) BodyReader(ctx, msgID, nntpGroups any) *gomock.Call

BodyReader indicates an expected call of BodyReader.

func (*MockUsenetConnectionPoolMockRecorder) GetConnection

func (mr *MockUsenetConnectionPoolMockRecorder) GetConnection(ctx, skipProviders, useBackupProviders any) *gomock.Call

GetConnection indicates an expected call of GetConnection.

func (*MockUsenetConnectionPoolMockRecorder) GetMetrics

GetMetrics indicates an expected call of GetMetrics.

func (*MockUsenetConnectionPoolMockRecorder) GetMetricsSnapshot

func (mr *MockUsenetConnectionPoolMockRecorder) GetMetricsSnapshot() *gomock.Call

GetMetricsSnapshot indicates an expected call of GetMetricsSnapshot.

func (*MockUsenetConnectionPoolMockRecorder) GetProviderStatus

func (mr *MockUsenetConnectionPoolMockRecorder) GetProviderStatus(providerID any) *gomock.Call

GetProviderStatus indicates an expected call of GetProviderStatus.

func (*MockUsenetConnectionPoolMockRecorder) GetProvidersInfo

func (mr *MockUsenetConnectionPoolMockRecorder) GetProvidersInfo() *gomock.Call

GetProvidersInfo indicates an expected call of GetProvidersInfo.

func (*MockUsenetConnectionPoolMockRecorder) Post

Post indicates an expected call of Post.

func (*MockUsenetConnectionPoolMockRecorder) Quit

Quit indicates an expected call of Quit.

func (*MockUsenetConnectionPoolMockRecorder) Stat

func (mr *MockUsenetConnectionPoolMockRecorder) Stat(ctx, msgID, nntpGroups any) *gomock.Call

Stat indicates an expected call of Stat.

func (*MockUsenetConnectionPoolMockRecorder) TestProviderPipelineSupport added in v2.3.0

func (mr *MockUsenetConnectionPoolMockRecorder) TestProviderPipelineSupport(ctx, providerHost, testMsgID any) *gomock.Call

TestProviderPipelineSupport indicates an expected call of TestProviderPipelineSupport.

type Option

type Option func(*Config)

type PoolMetrics

type PoolMetrics struct {
	// contains filtered or unexported fields
}

PoolMetrics provides simple atomic counters for pool operations All operations use atomic operations for thread-safety with minimal overhead

func NewPoolMetrics

func NewPoolMetrics() *PoolMetrics

NewPoolMetrics creates a new metrics instance with zero counters

func (*PoolMetrics) Cleanup

func (m *PoolMetrics) Cleanup()

Cleanup removes all provider tracking entries from memory This should be called during shutdown to prevent memory leaks

func (*PoolMetrics) GetSnapshot

func (m *PoolMetrics) GetSnapshot(pools []*providerPool) PoolMetricsSnapshot

GetSnapshot returns a point-in-time snapshot of all metrics If pools parameter is provided, includes detailed per-provider metrics The returned snapshot is a copy and won't change as metrics continue to update

func (*PoolMetrics) RecordAcquire

func (m *PoolMetrics) RecordAcquire()

func (*PoolMetrics) RecordAcquireWaitTime

func (m *PoolMetrics) RecordAcquireWaitTime(duration time.Duration)

func (*PoolMetrics) RecordArticleDownloaded

func (m *PoolMetrics) RecordArticleDownloaded(providerHost string)

RecordArticleDownloaded increments the downloaded article counter If providerHost is non-empty, also increments that provider's counter

func (*PoolMetrics) RecordArticlePosted

func (m *PoolMetrics) RecordArticlePosted(providerHost string)

RecordArticlePosted increments the posted article counter If providerHost is non-empty, also increments that provider's counter

func (*PoolMetrics) RecordConnectionCreated

func (m *PoolMetrics) RecordConnectionCreated()

func (*PoolMetrics) RecordConnectionDestroyed

func (m *PoolMetrics) RecordConnectionDestroyed()

func (*PoolMetrics) RecordDownload

func (m *PoolMetrics) RecordDownload(bytes int64, providerHost string)

RecordDownload adds bytes to the download counter If providerHost is non-empty, also adds bytes to that provider's counter

func (*PoolMetrics) RecordError

func (m *PoolMetrics) RecordError(providerHost string)

RecordError increments error counters If providerHost is non-empty, also increments that provider's error count

func (*PoolMetrics) RecordRelease

func (m *PoolMetrics) RecordRelease()

func (*PoolMetrics) RecordRetry

func (m *PoolMetrics) RecordRetry()

func (*PoolMetrics) RecordUpload

func (m *PoolMetrics) RecordUpload(bytes int64, providerHost string)

RecordUpload adds bytes to the upload counter If providerHost is non-empty, also adds bytes to that provider's counter

func (*PoolMetrics) RegisterActiveConnection

func (m *PoolMetrics) RegisterActiveConnection(id string, conn interface{})

func (*PoolMetrics) Reset

func (m *PoolMetrics) Reset()

Reset zeros all counters Optional method for periodic reporting or maintenance Not required for normal operation - counters work indefinitely without memory leaks

func (*PoolMetrics) UnregisterActiveConnection

func (m *PoolMetrics) UnregisterActiveConnection(id string)

type PoolMetricsSnapshot

type PoolMetricsSnapshot struct {
	// Article counts
	ArticlesDownloaded int64 `json:"articles_downloaded"`
	ArticlesPosted     int64 `json:"articles_posted"`

	// Traffic totals
	BytesDownloaded int64 `json:"bytes_downloaded"`
	BytesUploaded   int64 `json:"bytes_uploaded"`

	// Error counts
	TotalErrors    int64            `json:"total_errors"`
	ProviderErrors map[string]int64 `json:"provider_errors"` // host -> error count

	// Per-provider metrics
	ProviderMetrics map[string]ProviderMetricsSnapshot `json:"provider_metrics"` // host -> provider metrics

	// Metadata
	Timestamp time.Time `json:"timestamp"`
}

PoolMetricsSnapshot provides a point-in-time view of all metrics Simplified version: only tracks essential counters

type PooledConnection

type PooledConnection interface {
	Connection() nntpcli.Connection
	Close() error
	Free() error
	Provider() ConnectionProviderInfo
	CreatedAt() time.Time
}

PooledConnection represents a managed NNTP connection from a connection pool. It wraps the underlying NNTP connection with pool management capabilities.

type Provider

type Provider struct {
	Host                           string
	Username                       string
	Password                       string
	Port                           int
	MaxConnections                 int
	MaxConnectionIdleTimeInSeconds int
	IsBackupProvider               bool
}

func (*Provider) ID

func (p *Provider) ID() string

type ProviderConfig

type ProviderConfig interface {
	ID() string
	GetHost() string
	GetUsername() string
	GetPassword() string
	GetPort() int
	GetMaxConnections() int
	GetMaxConnectionIdleTimeInSeconds() int
	GetMaxConnectionTTLInSeconds() int
	GetPipelineDepth() int
	GetTLS() bool
	GetInsecureSSL() bool
	GetIsBackupProvider() bool
	GetVerifyCapabilities() []string
	GetProxyURL() string
}

Helper interface for internal packages

type ProviderInfo

type ProviderInfo struct {
	Host                  string        `json:"host"`
	Username              string        `json:"username"`
	UsedConnections       int           `json:"usedConnections"`
	MaxConnections        int           `json:"maxConnections"`
	State                 ProviderState `json:"state"`
	LastConnectionAttempt time.Time     `json:"lastConnectionAttempt"`
	LastSuccessfulConnect time.Time     `json:"lastSuccessfulConnect"`
	FailureReason         string        `json:"failureReason"`
	RetryCount            int           `json:"retryCount"`
	NextRetryAt           time.Time     `json:"nextRetryAt"`
}

func (ProviderInfo) ID

func (p ProviderInfo) ID() string

type ProviderMetricsSnapshot added in v2.1.0

type ProviderMetricsSnapshot struct {
	Host               string `json:"host"`
	ArticlesDownloaded int64  `json:"articles_downloaded"`
	ArticlesPosted     int64  `json:"articles_posted"`
	BytesDownloaded    int64  `json:"bytes_downloaded"`
	BytesUploaded      int64  `json:"bytes_uploaded"`
	TotalErrors        int64  `json:"total_errors"`
	State              string `json:"state"`
	ActiveConnections  int    `json:"active_connections"`
	MaxConnections     int    `json:"max_connections"`
}

ProviderMetricsSnapshot provides a point-in-time view of a single provider's metrics

type ProviderState

type ProviderState int

ProviderState represents the lifecycle state of a provider during configuration changes

const (
	ProviderStateActive               ProviderState = iota // Normal operation
	ProviderStateOffline                                   // Provider is offline/unreachable
	ProviderStateReconnecting                              // Currently attempting to reconnect
	ProviderStateAuthenticationFailed                      // Authentication failed, won't retry
)

func (ProviderState) String

func (ps ProviderState) String() string

type UsenetConnectionPool

type UsenetConnectionPool interface {
	GetConnection(
		ctx context.Context,

		skipProviders []string,

		useBackupProviders bool,
	) (PooledConnection, error)
	Body(
		ctx context.Context,
		msgID string,
		w io.Writer,
		nntpGroups []string,
	) (int64, error)
	BodyReader(
		ctx context.Context,
		msgID string,
		nntpGroups []string,
	) (nntpcli.ArticleBodyReader, error)
	Post(ctx context.Context, r io.Reader) error
	Stat(ctx context.Context, msgID string, nntpGroups []string) (int, error)
	// BodyBatch downloads multiple articles using pipelining if supported by the provider.
	// The group parameter specifies the newsgroup to join before downloading.
	// Articles are batched according to the provider's PipelineDepth setting.
	// Returns results in the same order as requests.
	// Failed requests are automatically retried with provider rotation.
	BodyBatch(ctx context.Context, group string, requests []BodyBatchRequest) []BodyBatchResult
	// TestProviderPipelineSupport tests if a specific provider supports pipelining.
	// Requires a known valid message ID for testing.
	// Returns true if pipelining is supported, along with a suggested pipeline depth.
	TestProviderPipelineSupport(ctx context.Context, providerHost string, testMsgID string) (supported bool, suggestedDepth int, err error)
	GetProvidersInfo() []ProviderInfo
	GetProviderStatus(providerID string) (*ProviderInfo, bool)
	GetMetrics() *PoolMetrics
	GetMetricsSnapshot() PoolMetricsSnapshot
	Quit()
}

func NewConnectionPool

func NewConnectionPool(c ...Config) (UsenetConnectionPool, error)

type UsenetProviderConfig

type UsenetProviderConfig struct {
	Host               string
	Username           string
	Password           string
	VerifyCapabilities []string
	// ProxyURL is an optional SOCKS5 proxy URL for this provider.
	// Format: socks5://[user:password@]host:port
	// Example: socks5://proxy.example.com:1080
	// Example with auth: socks5://user:pass@proxy.example.com:1080
	ProxyURL                       string
	Port                           int
	MaxConnections                 int
	MaxConnectionIdleTimeInSeconds int
	MaxConnectionTTLInSeconds      int
	// PipelineDepth is the number of BODY commands to send in a pipeline before
	// waiting for responses. Set to 0 or 1 to disable pipelining (default).
	// Recommended values: 2-4 for low latency (<50ms), 4-8 for high latency (100ms+).
	// Higher values can improve throughput on high-latency connections.
	PipelineDepth    int
	TLS              bool
	InsecureSSL      bool
	IsBackupProvider bool
}

func (*UsenetProviderConfig) GetHost

func (u *UsenetProviderConfig) GetHost() string

Adapter methods for internal package interfaces

func (*UsenetProviderConfig) GetInsecureSSL

func (u *UsenetProviderConfig) GetInsecureSSL() bool

func (*UsenetProviderConfig) GetIsBackupProvider

func (u *UsenetProviderConfig) GetIsBackupProvider() bool

func (*UsenetProviderConfig) GetMaxConnectionIdleTimeInSeconds

func (u *UsenetProviderConfig) GetMaxConnectionIdleTimeInSeconds() int

func (*UsenetProviderConfig) GetMaxConnectionTTLInSeconds

func (u *UsenetProviderConfig) GetMaxConnectionTTLInSeconds() int

func (*UsenetProviderConfig) GetMaxConnections

func (u *UsenetProviderConfig) GetMaxConnections() int

func (*UsenetProviderConfig) GetPassword

func (u *UsenetProviderConfig) GetPassword() string

func (*UsenetProviderConfig) GetPipelineDepth added in v2.3.0

func (u *UsenetProviderConfig) GetPipelineDepth() int

func (*UsenetProviderConfig) GetPort

func (u *UsenetProviderConfig) GetPort() int

func (*UsenetProviderConfig) GetProxyURL added in v2.3.0

func (u *UsenetProviderConfig) GetProxyURL() string

func (*UsenetProviderConfig) GetTLS

func (u *UsenetProviderConfig) GetTLS() bool

func (*UsenetProviderConfig) GetUsername

func (u *UsenetProviderConfig) GetUsername() string

func (*UsenetProviderConfig) GetVerifyCapabilities

func (u *UsenetProviderConfig) GetVerifyCapabilities() []string

func (*UsenetProviderConfig) ID

func (u *UsenetProviderConfig) ID() string

Directories

Path Synopsis
internal
pkg
nntpcli
Package nntpcli is a generated GoMock package.
Package nntpcli is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL