Skip to content

feat(backend): preserve log history across manual run retries - #14982

Open
jeffspahr wants to merge 1 commit into
kubeflow:masterfrom
jeffspahr:codex/retry-log-history
Open

jeffspahr wants to merge 1 commit into
kubeflow:masterfrom
jeffspahr:codex/retry-log-history

Conversation

@jeffspahr

@jeffspahr jeffspahr commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Description of your changes:

Manual Retry run clears task pods, status metadata, and artifact links. That prevents stale outputs from becoming current results, but also loses the references needed to find earlier logs. Reusing an executor output prefix can additionally overwrite the old log object.

This change preserves prior log references before resetting the task and gives executor log objects an invocation-specific path. It is independent of UI modernization #14584 and closes #14981.

  • Snapshot log artifacts, driver-log URI, pods, timestamps, and outcome in a separate task_log_history table. Snapshot, artifact unlinking, and reset commit atomically under the run's retry-generation fence. Duplicate delivery preserves the original snapshot; successful siblings retain their current results.
  • Expose output-only PipelineTask.log_history through existing authorized task/run reads. Historical data never becomes current model/dataset output. Regenerate the API clients; no UI behavior changes.
  • Store executor logs under attempts/<pod UID>/executor-logs-N, keeping automatic-attempt naming while preventing manual retries from overwriting earlier objects.
  • Delete history transactionally with its run. Keep existing pod and object-store retention policies.

Migration and rollout: A create-only, standalone table with no foreign keys or backfill. The new-table operation uses same-connection advisory ownership, a one-second metadata-lock limit, and a ten-second deadline. Failed ownership/DDL aborts startup and is safe to retry. Existing history tables are excluded from broad reconciliation. Roll out the API server and launcher together: older launchers can still overwrite reused log paths. Rollback leaves the additive table intact but stops recording; the operator guide covers orphan metadata cleanup after old-server deletions. Previously deleted/overwritten logs cannot be reconstructed. Namespace export/import does not yet transfer this separate history table. See retry log history guidance.

Validation:

  • Full Go suites: server, model, storage, resource manager, history, launcher/component, and client manager.
  • MySQL 8.0.46 and PostgreSQL 16: atomic rollback with an injected failure, concurrent duplicate reset, stale-generation rejection, repeated retries, deletion, and migration/repeated startup. Existing native PostgreSQL integration also passes.
  • Migration tests start from populated preceding schemas, assert CREATE-only DDL without foreign keys and unchanged task-table identity, and verify reads/writes finish during startup. Competing creators, cancellation/recovery, and PostgreSQL blocked-DDL timeout are covered. These tests use the existing backend CI database services; they do not certify unrelated release migrations or every historical schema.
  • Upgrade fixture: 20 existing tasks with long metadata plus 100 request-fixture rows. During the actual startup migration, MySQL completed 87 read/write pairs (maximum 4.77 ms) and PostgreSQL 71 (maximum 13.89 ms). The forced PostgreSQL DDL lock timed out and recovered in approximately 1.03 seconds. These are disposable-test measurements, not production latency guarantees. MySQL contention coverage uses advisory ownership rather than a separately forced metadata-lock timeout.
  • Fail → retry → succeed retains historical logs while exposing only new current outputs. Authorization rejects cross-run and unauthorized reads; client-supplied history is ignored. Immutable-path tests cover automatic and manual retries, custom paths, and disabled publication.
  • Canonical and compatibility Go clients compile; generated Python models pass syntax validation.

Checklist:

  • Commits signed off with DCO.
  • PR title follows the repository convention.

Signed-off-by: Jeff Spahr <spahrj@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 14:58
@google-oss-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from jeffspahr. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions

Copy link
Copy Markdown

Contributor Report for @jeffspahr

Metric Value
Kubeflow org member Yes
Issues opened in kubeflow/pipelines 0
Merged PRs in kubeflow/pipelines 0
GitHub account age 3469 days (created 2017-04-21)
PR comments in kubeflow/pipelines 1505

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Go HTTP task requests serialize unset history, breaking compatibility with servers that do not recognize the new field.

1 open issue
5 files not reviewed
  • backend/api/v2/go_client/run.pb.go: Generated file
  • backend/api/v2/go_http_client/run_model/pipeline_task_log_history.go: Generated file
  • backend/api/v2/go_http_client/run_model/v2_pipeline_task.go: Generated file
  • backend/api/v2beta1/go_client/aliases.go: Generated file
  • backend/api/v2beta1/go_http_client/run_model/aliases.go: Generated file
What changed in this PR

Preserves troubleshooting logs across manual run retries for #14981, without treating historical artifacts as current outputs or changing UI behavior.

Changes:

  • Adds transactional history snapshots, generation-fenced resets, and bounded table creation.
  • Exposes output-only history through task APIs and regenerated clients.
  • Gives executor logs pod-specific paths and adds lifecycle, authorization, migration, and retention guidance.
File Description
sdk/​python/​kfp/​server_api/​models/​v2_pipeline_task.py Adds task history property.
sdk/​python/​kfp/​server_api/​models/​pipeline_task_log_history.py Adds Python history model.
sdk/​python/​kfp/​server_api/​models/​__init__.py Exports history model.
sdk/​python/​kfp/​server_api/​__init__.py Exposes history model publicly.
frontend/​src/​apisv2/​run/​models/​V2PipelineTask.ts Deserializes read-only history.
frontend/​src/​apisv2/​run/​models/​PipelineTaskLogHistory.ts Adds TypeScript history model.
frontend/​src/​apisv2/​run/​models/​index.ts Exports history types.
frontend/​src/​apisv2/​run/​apis/​RunServiceApi.ts Excludes history from request types.
docs/​operator-guides/​retry-log-history.md Documents rollout and retention limits.
docs/​_static/​kfp_api_single_file.swagger.json Publishes updated API schema.
backend/​src/​v2/​component/​launcher_v2.go Uses pod-specific log paths.
backend/​src/​v2/​component/​launcher_v2_test.go Tests immutable log paths.
backend/​src/​apiserver/​storage/​task_store.go Snapshots, hydrates, and deletes history.
backend/​src/​apiserver/​storage/​task_store_test.go Tests history lifecycle and atomicity.
backend/​src/​apiserver/​storage/​native_postgres_integration_test.go Adapts PostgreSQL retry coverage.
backend/​src/​apiserver/​server/​run_server_retry_history_test.go Tests history authorization.
backend/​src/​apiserver/​server/​api_converter.go Exposes persisted history.
backend/​src/​apiserver/​server/​api_converter_test.go Tests output-only conversion.
backend/​src/​apiserver/​resource/​resource_manager.go Delegates atomic retry reset.
backend/​src/​apiserver/​model/​task.go Adds transient history field.
backend/​src/​apiserver/​model/​task_log_history.go Defines standalone history table.
backend/​src/​apiserver/​model/​common.go Registers history model.
backend/​src/​apiserver/​client_manager/​task_log_history_migration.go Adds bounded create-only migration.
backend/​src/​apiserver/​client_manager/​task_log_history_migration_test.go Tests migration contention and recovery.
backend/​src/​apiserver/​client_manager/​client_manager.go Integrates dedicated history migration.
backend/​api/​v2beta1/​go_http_client/​run_model/​aliases.go Adds HTTP compatibility alias.
backend/​api/​v2beta1/​go_client/​aliases.go Adds protobuf compatibility alias.
backend/​api/​v2/​swagger/​run.swagger.json Defines history API schema.
backend/​api/​v2/​swagger/​kfp_api_single_file.swagger.json Updates combined API schema.
backend/​api/​v2/​run.proto Defines output-only task history.
backend/​api/​v2/​python_http_client/​README.md Lists history model documentation.
backend/​api/​v2/​python_http_client/​docs/​V2PipelineTask.md Documents task history property.
backend/​api/​v2/​python_http_client/​docs/​PipelineTaskLogHistory.md Documents snapshot fields.
backend/​api/​v2/​go_http_client/​run_model/​v2_pipeline_task.go Adds Go HTTP history field.
backend/​api/​v2/​go_http_client/​run_model/​pipeline_task_log_history.go Adds Go HTTP history model.
backend/​api/​v2/​go_client/​run.pb.go Regenerates protobuf history bindings.

Review effort: Balanced

// Output only. Prior executions archived by manual retries, oldest first.
// History begins when preservation is enabled; older retries are not backfilled.
// Read Only: true
LogHistory []*PipelineTaskLogHistory `json:"log_history"`

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(backend): preserve log history across manual run retries

2 participants