Skip to content

feat(config,server,cli,watch): support global general.callback_url (#1481) - #1482

Open
prafful1234 wants to merge 7 commits into
Altinity:masterfrom
prafful1234:feature/general-callback-url
Open

feat(config,server,cli,watch): support global general.callback_url (#1481)#1482
prafful1234 wants to merge 7 commits into
Altinity:masterfrom
prafful1234:feature/general-callback-url

Conversation

@prafful1234

Copy link
Copy Markdown

Summary

Fixes #1481

This PR introduces general.callback_url and general.callback_timeout configuration options to enable backup completion webhooks across all execution paths: API, CLI, and Watch Mode.

Currently, completion callbacks are only available via the API query parameter (POST /backup/create?callback=...). This PR unifies callback handling into a shared pkg/status dispatcher while preserving strict backward compatibility for existing API consumers.

Changes

  • Config (pkg/config): Added general.callback_url and general.callback_timeout (default 5s), with support for CALLBACK_URL and CALLBACK_TIMEOUT environment variables.
  • Shared Dispatcher (pkg/status): Created SendCallback() supporting CallbackPayload (status, error, operation_id, and optional command / duration).
  • API Fallback (pkg/server): Updated API handler to fall back to general.callback_url if the ?callback= query parameter is missing or empty. Query params still take precedence when provided.
  • CLI Commands (cmd/clickhouse-backup): Added synchronous callback dispatch in CLI lifecycle hooks, reusing existing commandId / operation_id tracking. Errors during dispatch are logged and swallowed so CLI exit codes are never affected by callback failures.
  • Watch Mode (pkg/backup/watch.go): Added per-iteration callback dispatch and status.Current.Start() / Stop() tracking inside the watch loop, ensuring each individual watch cycle sends a clean callback with its own unique operation_id.
  • Docs: Updated configuration references in ReadMe.md and Manual.md, and added an entry to ChangeLog.md.

Key Constraints Respected

  1. API Backward Compatibility: CallbackPayload.Error intentionally retains no omitempty tag so API callback JSON payloads remain byte-identical ("error": "" is always present). command and duration use omitempty.
  2. Resilience: HTTP errors or timeouts during webhook dispatch are caught and logged; they never cause a backup operation or CLI command to fail.
  3. Watch Lifecycle: Callbacks fire per watch cycle (with individual start/stop status tracking), rather than once for the parent process lifetime.

Testing

Followed workflow across all modified packages:

  • pkg/config: Tested parsing from YAML, ENV overrides, and default timeout handling.
  • pkg/status: Tested payload serialization, HTTP timeout enforcement, and non-200 response handling.
  • pkg/server: Tested fallback logic when ?callback= is absent/empty vs explicitly set.
  • cmd/clickhouse-backup: Tested CLI callback dispatch on command success/failure and confirmed non-zero callback failures do not mutate command exit codes.
  • pkg/backup: Tested per-iteration callback firing and error recovery across multiple watch ticks.

All tests pass cleanly:

go test -v ./pkg/... ./cmd/...

prafful1234 and others added 7 commits July 26, 2026 16:20
Provide a shared callback dispatcher with config fallback so one-shot CLI
commands and each watch iteration can notify external systems without
changing the existing API callback JSON contract.
ValidateConfig now errors on durations <= 0 (e.g: 0s)
CallbackTimeoutDuration is always positive after a successful load
API server already notifies via pkg/server
dispatchCLICallback now returns early when --command-id is set
Also extract applyCLICallbacks add allowlist coverage, and drop unused GetOperationId
`startWatchIteration` no longer registers a `status.Current` row per cycle (AsyncStatus.commands is append-only) preventing unbounded memory growth in long-running watch processes
The iteration `operation_id` is now a bare UUID and finish is made idempotent via sync
Once the top-level watch commandId is passed to `CreateToRemote/Rebase` again
`parseCallback` now builds each POST from `context.WithoutCancel` plus `general.callback_timeout`
Canceled caller context cannot kill the notification and callbacks no longer hang without a deadline
Signed-off-by: slach <bloodjazman@gmail.com>
@prafful1234

Copy link
Copy Markdown
Author

@Slach the failing Test (21.8–26.3) jobs look fixed on master (object-disk streaming fallback).

please approve the CI? Thanks!

@Slach Slach added this to the 2.8.1 milestone Jul 29, 2026
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.

[FR] Support global general.callback_url for CLI commands and watch mode

2 participants