Documentation
¶
Index ¶
- Variables
- type DeferredCheckError
- type Engine
- func (e *Engine) AcquireWorker(ctx context.Context) error
- func (e *Engine) Budget() EngineBudget
- func (e *Engine) Metrics() Metrics
- func (e *Engine) PerArticleBytes() int64
- func (e *Engine) ReleaseBuffer(n int64)
- func (e *Engine) ReleaseWorker()
- func (e *Engine) ReserveBuffer(ctx context.Context, n int64) error
- type EngineBudget
- type FailedArticleInfo
- type ManifestSink
- type Metrics
- type Post
- type PostStatus
- type Poster
- type Reposter
- type Stats
- type Throttle
Constants ¶
This section is empty.
Variables ¶
var ( // ErrPosterClosed is returned when attempting to post after the poster has been closed ErrPosterClosed = errors.New("poster is closed") )
Functions ¶
This section is empty.
Types ¶
type DeferredCheckError ¶ added in v0.0.29
type DeferredCheckError struct {
FailedArticles []FailedArticleInfo
TotalArticles int
}
DeferredCheckError is a non-fatal error indicating some articles need deferred verification. The upload itself succeeded, but article verification (STAT check) failed after all immediate retries.
func (*DeferredCheckError) Error ¶ added in v0.0.29
func (e *DeferredCheckError) Error() string
type Engine ¶ added in v0.0.30
type Engine struct {
// contains filtered or unexported fields
}
Engine is the process-wide upload resource owner. It bounds the number of articles posted concurrently (worker slots) and the total memory reserved for in-flight article buffers (buffer budget), independent of how many queue jobs are active. One Engine is shared by every job through the transfer runtime.
All methods are safe for concurrent use and safe to call on a nil *Engine, in which case they are no-ops (preserving standalone behaviour when no engine is injected).
func NewEngine ¶ added in v0.0.30
NewEngine builds an Engine sized for the given article size, explicit buffer limit (0 = auto), and total upload connection capacity.
func (*Engine) AcquireWorker ¶ added in v0.0.30
AcquireWorker blocks until an upload worker slot is free (or ctx is cancelled). Returns ctx.Err() if cancelled while waiting. A nil engine is a no-op.
func (*Engine) Budget ¶ added in v0.0.30
func (e *Engine) Budget() EngineBudget
Budget returns the resolved limits.
func (*Engine) Metrics ¶ added in v0.0.30
Metrics returns a snapshot of current engine activity. Safe on a nil engine.
func (*Engine) PerArticleBytes ¶ added in v0.0.30
PerArticleBytes is the reservation size for a single in-flight article, or 0 when no engine is configured.
func (*Engine) ReleaseBuffer ¶ added in v0.0.30
ReleaseBuffer returns n bytes of buffer budget. Must be paired with a prior successful ReserveBuffer of the same size. A nil engine or non-positive n is a no-op.
func (*Engine) ReleaseWorker ¶ added in v0.0.30
func (e *Engine) ReleaseWorker()
ReleaseWorker frees a worker slot acquired by AcquireWorker. A nil engine is a no-op.
func (*Engine) ReserveBuffer ¶ added in v0.0.30
ReserveBuffer blocks until n bytes of buffer budget are available (or ctx is cancelled), then records the reservation. Returns ctx.Err() if cancelled while waiting. A nil engine or non-positive n is a no-op.
type EngineBudget ¶ added in v0.0.30
type EngineBudget struct {
// PerArticleBytes is the memory reserved for a single in-flight article
// (raw body + estimated encoded size + fixed overhead).
PerArticleBytes int64
// BudgetBytes is the total buffer memory the engine may reserve at once.
BudgetBytes int64
// WorkerCount is the maximum number of articles posted concurrently.
WorkerCount int64
}
EngineBudget is the resolved set of process-wide upload limits.
func ComputeEngineBudget ¶ added in v0.0.30
func ComputeEngineBudget(articleSize uint64, bufferLimit int64, connCapacity int) EngineBudget
ComputeEngineBudget resolves the process-wide upload-buffer budget and worker count from the configured article size, an explicit buffer limit (0 = auto), and the total connection capacity (sum of max_connections * effective inflight across upload providers).
per_article = article_size + estimated_yenc_size + 256 KiB auto_budget = clamp(per_article * min(conn_capacity, 32), 64MiB, 512MiB) worker_count = min(conn_capacity, floor(budget / per_article))
The result guarantees BudgetBytes >= PerArticleBytes and WorkerCount >= 1 so callers can always make forward progress.
type FailedArticleInfo ¶ added in v0.0.29
FailedArticleInfo contains information about an article that failed verification and should be deferred for later checking.
type ManifestSink ¶ added in v0.0.30
type ManifestSink interface {
RecordFile(ctx context.Context, filePath string, articles []*article.Article) error
// ExistingArticles returns a previously recorded manifest's article records
// for filePath (ok=false if none), used for crash recovery to reuse the
// exact Message-IDs rather than regenerating them.
ExistingArticles(ctx context.Context, filePath string) ([]manifest.ArticleRecord, bool, error)
}
ManifestSink records a durable manifest for a file's articles before they are posted. It is implemented outside the poster (by the transfer runtime) and injected per job; a nil sink disables manifest recording (standalone mode).
type Metrics ¶ added in v0.0.30
type Metrics struct {
ActiveWorkers int64
QueuedWorkers int64
WorkerCount int64
ReservedBytes int64
BudgetBytes int64
PerArticleByte int64
}
Metrics is a point-in-time snapshot of engine activity for observability.
type Post ¶
type Post struct {
FilePath string
Articles []*article.Article
Status PostStatus
Error error
Retries int
// contains filtered or unexported fields
}
Post represents a file to be posted
type PostStatus ¶
type PostStatus int
PostStatus represents the status of a post
const ( PostStatusPending PostStatus = iota PostStatusPosted PostStatusVerified PostStatusFailed PostStatusCancelled PostStatusPosting )
type Poster ¶
type Poster interface {
// Post posts files from a directory to Usenet
Post(ctx context.Context, files []string, rootDir string, nzbGen nzb.NZBGenerator) error
// PostWithRelativePaths posts files with custom display names (relative paths) for subjects
// relativePaths maps absolute file path to the display name to use in the subject
PostWithRelativePaths(ctx context.Context, files []string, rootDir string, nzbGen nzb.NZBGenerator, relativePaths map[string]string) error
// Stats returns posting statistics
Stats() Stats
// Close closes the poster
Close()
}
Poster defines the interface for posting articles to Usenet
func New ¶
func New(ctx context.Context, cfg config.Config, poolManager pool.PoolManager, jobProgress progress.JobProgress) (Poster, error)
New creates a new poster using dependency injection for the connection pool manager
func NewWithEngine ¶ added in v0.0.30
func NewWithEngine(ctx context.Context, cfg config.Config, poolManager pool.PoolManager, jobProgress progress.JobProgress, engine *Engine, manifestSink ManifestSink) (Poster, error)
NewWithEngine creates a poster that routes upload work through the supplied process-wide Engine, so effective concurrency and in-flight buffer memory are bounded across all jobs. A nil engine preserves standalone behaviour. The optional manifestSink records a durable manifest per file before posting; a nil sink disables manifest recording.
type Reposter ¶ added in v0.0.30
type Reposter struct {
// contains filtered or unexported fields
}
Reposter re-posts individual articles during durable verification, reading each body from its original source file and posting through the shared upload pool and engine. It is process-wide (owned by the transfer runtime), distinct from the per-job poster, and implements verification.Reposter.
func NewReposter ¶ added in v0.0.30
func NewReposter(uploadPool pool.NNTPClient, engine *Engine, throttleRate int64) *Reposter
NewReposter creates a Reposter using the shared upload pool and engine. If throttleRate > 0 the same byte/sec throttle as normal uploads is applied.
func (*Reposter) Repost ¶ added in v0.0.30
Repost re-posts a single article from its manifest record. The body is read from rec.SourcePath at rec.Offset, and the post reuses rec's Message-ID and headers so the NZB remains correct. It acquires an engine worker slot and buffer reservation so re-posts share the process-wide resource limits.
type Stats ¶
type Stats struct {
ArticlesPosted int64
ArticlesChecked int64
BytesPosted int64
ArticleErrors int64
StartTime time.Time
// contains filtered or unexported fields
}
Stats tracks posting statistics
type Throttle ¶
type Throttle struct {
// contains filtered or unexported fields
}
Throttle handles rate limiting using a token-bucket algorithm. Token-bucket state is protected by a mutex: the previous lock-free implementation allowed concurrent consumers to overdraw the bucket past zero, silently bypassing the configured rate under contention.
func NewThrottle ¶ added in v0.0.6
NewThrottle creates a new throttle with the given rate and interval