Skip to content

[History server] Add per-session meta.json for session lifecycle tracking#4955

Open
Lucas61000 wants to merge 5 commits into
ray-project:masterfrom
Lucas61000:issue-4885
Open

[History server] Add per-session meta.json for session lifecycle tracking#4955
Lucas61000 wants to merge 5 commits into
ray-project:masterfrom
Lucas61000:issue-4885

Conversation

@Lucas61000

@Lucas61000 Lucas61000 commented Jun 26, 2026

Copy link
Copy Markdown

Why are these changes needed?

Add per-session meta.json files to the cluster-metadata directory so the History Server can track session lifecycle status (in_progress, completed, terminated).

Currently, the History Server lists sessions from cluster-metadata markers but has no way to tell whether a session is active, finished gracefully, or crashed. This matters for operators debugging failed Ray clusters — they need to quickly identify which sessions exited abnormally.

Related issue number

Closes #4885

Checks

  • I've made sure the tests are passing.
  • Testing Strategy
    • Unit tests
    • Manual tests
      • E2E (kind + MinIO): deployed RayCluster → ran RayJob → deleted, verified
        /clusters shows completed with endTime.
    • This PR is not tested :(

Summary

Collector (head only, write):

  • Writes in_progress meta.json when a new session directory is detected
  • On graceful shutdown (SIGTERM/SIGINT), writes completed + best-effort Ray dashboard cluster_status (3s timeout)
  • SIGKILL leaves meta.json as in_progress — crash detection handles it

History Server (read-only inference):

  • During /clusters listing, cross-references stored sessions against live RayCluster CRs
  • An in_progress session whose K8s CR no longer exists → terminated
  • Inference is read-time only (no write-back to storage), self-correcting on next List
  • Skips inference when K8s API is unreachable (ListRayClusters returns error)

Storage (4 backends: S3, GCS, Azure Blob, Aliyun OSS):

  • WriteMeta / ReadMeta on StorageWriter / StorageReader
  • List() filters .meta.json to avoid duplicate session entries, enriches ClusterInfo with Status + EndTime

…king

- Add SessionStatus type, MetaJson struct, and ClusterInfo extensions (types.go)
- Add MetaJsonPath helper in cluster-metadata scheme (clustermetadata.go)
- Extend StorageWriter/StorageReader with WriteMeta/ReadMeta (interface.go)
- Implement WriteMeta/ReadMeta across all 4 storage backends (S3, GCS, Azure, OSS)
- Filter .meta.json files from List() to avoid duplicate session entries
- Collector: write in_progress on new session, completed + RayStatus on shutdown (head only)
- History Server: read-only crash detection — in_progress sessions whose cluster is gone → terminated
- Update localtest mocks for WriteMeta/ReadMeta
- Fix existing mock implementations for new interface methods
- Add tests: MetaJsonPath, List enrichment, crash detection, ReadMeta not found

Signed-off-by: Lucas <54979663+lucas61000@users.noreply.github.com>
Comment thread historyserver/pkg/collector/logcollector/runtime/logcollector/collector.go Outdated
close(ShutdownChan) before updateMetaJsonOnShutdown so WatchSessionLatestLoops
cannot fire a late fsnotify event that overwrites completed back to in_progress.

Signed-off-by: Lucas <54979663+lucas61000@users.noreply.github.com>
…tor start

On startup the new collector finalizes any same-cluster sessions still
marked in_progress (left behind by a killed previous collector).
Runs at most once per collector lifetime to avoid redundant storage
List() calls.

Signed-off-by: Lucas <54979663+lucas61000@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 3 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 3c069d4. Configure here.

ClusterNamespace: c.Namespace,
StartTime: c.CreateTimeStamp,
EndTime: time.Now().Unix(),
Status: utils.SessionStatusCompleted,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale sessions marked completed

Medium Severity

When a new session starts, finalizePreviousSessions writes completed for older in_progress meta files left after SIGKILL or collector loss. Those sessions did not shut down gracefully, so persisted status contradicts the PR’s terminated/crash story and bypasses History Server read-time terminated inference for in_progress rows.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3c069d4. Configure here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

My understanding is completed means the session ended (cluster moved to a new session), while terminated is reserved for when the RayCluster CR itself disappears. Since the cluster is still alive here, completed seems more appropriate.

clusters := r.Reader.List()
for _, c := range clusters {
if c.Namespace != r.RayClusterNamespace || c.Name != r.RayClusterName {
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Owner not matched when finalizing

Medium Severity

finalizePreviousSessions treats sessions as the same cluster when only Namespace and Name match. Metadata paths also distinguish OwnerKind and OwnerName, so a standalone RayCluster and a RayJob-owned cluster can share namespace and Ray cluster name while storing different sessions.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3c069d4. Configure here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

As far as I understand, K8s enforces RayCluster name uniqueness per namespace, so two owners cannot hold the same name simultaneously.

Comment thread historyserver/pkg/historyserver/clientmanager.go
…sters

Prevents crash detection from reasoning over an incomplete live set
when some K8s clients are unreachable.

Signed-off-by: Lucas <54979663+lucas61000@users.noreply.github.com>
Signed-off-by: Lucas <54979663+lucas61000@users.noreply.github.com>
@Lucas61000

Copy link
Copy Markdown
Author

@chiayi The PR is ready for review, really appreciate your time!

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.

[Feature] [History Server] Per-session meta.json for session lifecycle tracking

1 participant