Files
weatherreporter/docs/internal/distributor-adapter.md

4.7 KiB

Distributor Adapter Internals

This document describes the distributor upload adapter in internal/adapters/distributor.

Purpose

The adapter submits generated weatherreporter Markdown reports to a configured distributor HTTP upload endpoint. It supports one or more file mappings per upload request. It isolates distributor package types, token-env lookup, upload client construction, source-bundle file mapping, timeout handling, status polling, and upload error wrapping from app orchestration.

Inputs And Outputs

Inputs:

  • distributor endpoint URL
  • token environment variable name
  • upload timeout
  • pipeline ID
  • bundle ID
  • idempotency key
  • source Markdown report paths and bundle-relative path mappings
  • bundle created timestamp
  • context for cancellation

Outputs:

  • accepted distributor run ID
  • accepted distributor upload status
  • distributor run status, status polling error, and raw run report JSON when available
  • weatherreporter-owned idempotency conflict error when applicable

Boundaries

internal/adapters/distributor is the only weatherreporter package that imports gitea.maximumdirect.net/eric/distributor/pkg/upload or gitea.maximumdirect.net/eric/distributor/pkg/bundle.

The app layer passes weatherreporter-owned request values to the adapter. The adapter does not choose report types, render templates, select output copies, decide whether an upload represents one report or a batch, configure destinations, wait for downstream publication, transform Markdown, or persist notification state.

Full upstream distributor package and HTTP contract details stay under docs/integrations/distributor/.

Config Fields Used

The adapter is built from notify.distributor config:

  • endpoint
  • token_env
  • timeout

The app layer renders single-report pipeline ID, bundle ID, idempotency key, and bundle paths from:

  • pipeline_id_template
  • bundle_id_template
  • idempotency_key_template
  • report-specific path templates

For batch uploads, the app layer renders pipeline ID, bundle ID, and idempotency key from notify.distributor.batch.*, resolves report-specific path templates once per included report, and passes the resulting multi-file request to this adapter.

Report-specific path resolution happens entirely in the app layer. Explicit reports.<report>.distributor.path_templates overrides take precedence over report definition defaults.

The token value is read from the environment variable named by token_env after config loading and secrets.directory processing.

Upload Behavior

The adapter calls distributor UploadFiles with one or more file mappings:

  • pipeline ID: the rendered distributor workflow selector
  • source paths: managed Markdown report paths selected by app orchestration
  • bundle paths: rendered bundle-relative report paths for each source
  • created: the report or batch generation timestamp

The adapter creates a distributor upload client with the configured endpoint, bearer token, and timeout-backed HTTP client. It also wraps the upload context with the configured timeout when the timeout is greater than zero.

After upload acceptance, the adapter polls distributor Status for the accepted run ID until the run reaches succeeded or failed, or until the configured timeout expires. It returns the latest status, error text, and raw report JSON in weatherreporter-owned types so app orchestration can persist them in the notification debug artifact. Status lookup failures or timeout before a terminal state are kept as debug status errors on an otherwise accepted upload. A terminal distributor run status of failed is returned as a notification failure with the status report preserved.

Failure Behavior

The adapter validates required endpoint, token env name, token value, pipeline ID, bundle ID, idempotency key, upload files, source paths, bundle paths, and upload client inputs before uploading.

Upload failures include endpoint, pipeline ID, bundle ID, idempotency key, source paths, and bundle paths context. Token values are redacted from adapter errors.

Distributor idempotency conflicts are exposed as a weatherreporter-owned IdempotencyConflictError, so callers do not depend on upstream distributor types.

Tests

Inspect:

  • internal/adapters/distributor/client_test.go
  • internal/app/app_test.go
  • internal/cli/root_test.go

Adapter tests use a fake upload client factory and do not require a live distributor service.

Invariants

  • Distributor package types do not leak outside the adapter.
  • Only managed Markdown report paths selected by app orchestration are uploaded.
  • The adapter never scans the workspace.
  • Token values are not included in errors, CLI output, metadata, docs, or examples.
  • Destination routing and Markdown-to-HTML transformation belong to distributor, not weatherreporter.