Skip to content

RoutingGrain dispatch slots repeatedly exhaust on head-of-line blocking behind slow cache-hub destination #5004

Closed as duplicate

Description

@systemorph-com

What is failing

The RoutingGrain in MeshWeaver.Hosting.Orleans repeatedly saturates its 64-dispatch slot budget on the memex silo, raising [ROUTE] Routing back-pressure eight times over ~5 hours (07:40–12:52 UTC). Critically, the episode stamps increment on the same activation (d89f0147#1 → #8, no recycle): every episode drained below half-threshold and then re-crossed. This is not a leaked slot on this activation — it is recurring saturation episodes, and 6 of the 8 samples carry the head-of-line signature: stream destinations queued 1, deepest per-destination queue 62, always behind the same destination, cache/UQaJgLdynkKmdsldLQJQgg.

Probable cause

Medium confidence: a slow or effectively stuck cache-hub grain destination (cache/UQaJgLdynkKmdsldLQJQgg in the memex namespace) is not consuming its ordered route leg, so ~62 dispatches queue behind it until the in-flight budget exhausts. The dispatch slot is held for the whole leg — including the unbounded wait for a ThreadPool thread before the leg's own timeouts start — so a slow consumer or CPU starvation on the silo produces the same signature. The two clean samples (#1, #7: deepest queue 0) are plain load crossings; they do not contradict this, but they mean part of the signal is ordinary traffic. The specific defect needs the cache destination's own logs to pin down: is that hub consuming at all, and are its legs terminating?

Impact

Eight critical bursts over five hours on a single pod, with recovery between episodes — degraded, not an outage. Real impact: route dispatches to all destinations stall behind the blocked cache leg during each episode, so live updates across the memex portal lag intermittently. Note this is fleet-wide today: ~30 sibling back-pressure incidents were opened on 2026-09-20 across both the memex and memex-cloud namespaces and multiple pods, many with the same cache/... head-of-line signature — this ticket is one instance of a systemic pattern, not an isolated pod problem.

Where to look

  • The route-dispatch/leg accounting in MeshWeaver.Hosting.Orleans.RoutingGrain (the [ROUTE] log site): how a slot is released when a leg's destination stops consuming, and whether the unbounded ThreadPool wait should be bounded.
  • The destination hub behind memex/cache/UQaJgLdynkKmdsldLQJQgg — check its activation, consumption rate, and whether it was recycled between 07:40 and 12:52 UTC.
  • Sibling incident Admin/_LogIncident/03e5e31ad393af55 (same site, memex-cloud, 15 occurrences, two pods) for the cross-namespace picture.

Evidence

Fingerprint 3e9ee663bc972498
Category MeshWeaver.Hosting.Orleans.RoutingGrain
Severity Critical
Namespace memex
Pods memex-portal-deployment-5f69f6b6bd-z7tb6
Occurrences 8
First seen 2026-09-20 07:40:59Z
Last seen 2026-09-20 12:52:45Z
Routing not determined — no configured route matches the category MeshWeaver.Hosting.Orleans.RoutingGrain. This repository is the configured fallback, not a finding about who owns the fault; the category names the LOGGER, which may not be the subject.
Recent log lines
2026-09-20 07:40:59Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#1 started 2026-09-20T07:40:59.2892032Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 0, deepest per-destination queue 0, routing pool subscribing 0. Latest dispatch target DefaultViews/_Policy — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 08:07:04Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#2 started 2026-09-20T08:07:04.5266262Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 08:23:06Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#3 started 2026-09-20T08:23:06.8219131Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 10:05:12Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#4 started 2026-09-20T10:05:12.9206650Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 10:45:55Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#5 started 2026-09-20T10:45:55.5850848Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 12:28:08Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#6 started 2026-09-20T12:28:08.8770953Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 12:37:59Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#7 started 2026-09-20T12:37:59.2454000Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 0, deepest per-destination queue 0, routing pool subscribing 0. Latest dispatch target Crm/Client — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.
2026-09-20 12:52:45Z memex-portal-deployment-5f69f6b6bd-z7tb6 crit: MeshWeaver.Hosting.Orleans.RoutingGrain[0]
      [ROUTE] Routing back-pressure [d89f0147#8 started 2026-09-20T12:52:45.6363590Z]: 64 route dispatches in flight (reporting threshold 64); stream destinations queued 1, deepest per-destination queue 62, routing pool subscribing 0. Latest dispatch target cache/UQaJgLdynkKmdsldLQJQgg — the address that happened to cross the threshold, NOT a diagnosis. A slot is held from dispatch until the leg terminates, INCLUDING the unbounded wait for a ThreadPool thread before the leg's own timeouts start, so a CPU-starved silo raises this with nothing stuck. A deepest queue of 1 or more means legs are blocked behind a leg (head-of-line on one destination); 0 means nothing is waiting on anything, so read it as load. 🚨 Deepest is sampled AT THE CROSSING, so like the in-flight count it is partly an artefact of the threshold: with N destinations sharing the backlog it is ~InFlight/N whatever is wrong. READ THE EPISODE STAMP, not the depth: a later line with a HIGHER episode on this activation means this episode drained; a line with a DIFFERENT activation id means the grain was recycled; and if neither a clear nor a higher episode ever follows, the in-flight count never fell below half the threshold — which means a leg never terminated and its slot leaked, not that the silo was busy.

Re-addressed by the current identity function: this incident inherited e4a97855ab595beb (Systemorph/MeshWeaver.Plugins#1796). Those nodes are superseded and will not fold, file or comment again.

Opened automatically from Admin/_LogIncident/3e9ee663bc972498. Recurrences are folded into this issue rather than opening new ones.

Activity

  1. rbuergi commented on Sep 21, 2026

    @rbuergi
    Contributor

    Closes as duplicate of #5009 — Migrated: d89f0147#1 → #8 across 5 hours with 6 of 8 samples head-of-line behind cache/UQaJgLdynkKmdsldLQJQgg — the second-longest longitudinal run in the set (§1, §3).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions