Skip to content

ReadProjectionProgressAsync hardcodes LastHeartbeat/AgentStatus to null on a stale rationale #5172

Description

@jeremydmiller

Both ReadProjectionProgressAsync overloads hardcode LastHeartbeat and AgentStatus to null, and neither selects the columns — so the targeted per-cell progression read returns NULL for exactly the two fields a monitor would call it for, even with EnableExtendedProgressionTracking on and the columns populated.

src/Marten/Storage/MartenDatabase.EventStorage.cs:

// :419  SQL is only "select name, last_seq_id from ... where name like ..."
// :450
return best is null ? null : new ProjectionProgressRow(projectionName, tenantId, bestSequence, null, null);

// :480  SQL is only "select last_seq_id from ... where name = ..."
// :490
return new ProjectionProgressRow(name.Name, name.TenantId, sequence, null, null);

The rationale is stale

The XML docs assert a world that no longer exists — :402-403:

ProjectionProgressRow.AgentStatus and ProjectionProgressRow.LastHeartbeat are always null: Marten models the columns but no daemon path writes them (#519).

and :465-466 repeats it. ProjectionProgressRow's own doc in JasperFx (src/JasperFx.Events/ProjectionProgressRow.cs:21-25) says the same.

That was true when #519 was written. Since #537 the daemon does write them — ExtendedProgressionWriterWriteExtendedProgressionAsync populates heartbeat and agent_status on every flush, and AllProjectionProgress reads them back correctly via ProjectionProgressStatement + ShardStateSelector. Only this read path was never updated.

Why it matters

#435 added ReadProjectionProgressAsync(projectionName, tenantId, …) specifically as a targeted per-cell read for monitoring — the alternative to pulling every row through AllProjectionProgress. A caller who takes that supported path to ask "is this shard's agent alive" gets NULL, with no indication the answer is a placeholder rather than a fact. The row-scan path they were meant to avoid returns the real value.

Fix

Add the two columns to both queries when EnableExtendedProgressionTracking is on, hydrate them into the record, and drop the stale comments in both repos. The like query at :419 already reads name for ShardName.TryParse, so it's a column-list change.

Note ProjectionProgressRow has no field for pause_reason, running_on_node, or the failure_* columns — worth deciding whether this read should carry those too, or stay minimal and point monitors at AllProjectionProgress.

Found while auditing #5167. See also the companion issues on the never-written *_behind_threshold columns and the never-written high-water heartbeat.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions