Skip to content

[Task] Harden periodic tasks so a single exception no longer cancels the schedule #6608

Closed

Description

@Aias00

Background

A 2026-08-02 source audit confirmed that 8 open issues share the same root cause: a periodic task scheduled via ScheduledThreadPoolExecutor (either scheduleAtFixedRate or scheduleWithFixedDelay) is permanently cancelled after a single uncaught exception, because the JDK contract states "if any execution of the task encounters an exception, subsequent executions are suppressed." Confirmed that org.apache.shenyu.common.exception.ShenyuException extends RuntimeException, so rethrows escape the task and kill the schedule.

This one defect class silently stops cluster election, instance health sync, registry watches, token refresh, heartbeat, and the upstream health-check loop — a broad class of "the gateway/admin silently stops reconciling" symptoms.

Affected issues (all verified VALID)

Variants observed

Suggested fix pattern (single mechanism closes all 8)

Introduce a common resilient wrapper for periodic tasks in shenyu-common (or a small helper in each module) that:

  1. Wraps the task body in try { ... } catch (Throwable t) { LOG.error(...); } so an exception never escapes and cancels the schedule.
  2. For tasks that must surface fatal errors, swallow-and-log for transient errors and escalate (metric/alert) rather than killing the schedule.
  3. Ensures any shared mutable state (e.g. the futures list in [BUG] Upstream health check can get stuck after one async check failure #6502) is cleared in a finally, independent of whether join() succeeded.

Apply it uniformly to ShenyuClusterService, InstanceCheckService, TtlScheduler, ConsulInstanceRegisterRepository, EurekaInstanceRegisterRepository, ShenyuClientURIExecutorSubscriber, AccessTokenManager, and UpstreamCheckService.

Goal

Track the shared fix so the 8 issues can be closed by one well-scoped PR (or a small series) rather than eight independent patches that risk re-implementing the same guard inconsistently.

Audit ref: docs/issue-candidates-2026-08-02.md

Activity

  1. github-actions commented on Aug 2, 2026

    @github-actions
    Contributor

    👋 Hello @Aias00

    A new issue has been opened by @Aias00:

    Please review when you have time. Thank you! 🙏

  2. Aias00 commented on Aug 3, 2026

    @Aias00
    ContributorAuthor

    Update — round-2 deep-scan (2026-08-02): no NEW "scheduler-stops-after-one-exception" members surfaced; the family of 8 above appears complete for that specific defect class.

    The scan did surface three RELATED thread-lifecycle leaks that share the broader "periodic-task / worker-thread lifecycle hardening" theme and could be folded into this pass if its scope is widened. They are DISTINCT defects (idempotent-start / worker-shutdown), not duplicates of the exception-cancellation family — linking for visibility only:

  3. sunnysabor commented on Oct 1, 2026

    @sunnysabor
    Contributor

    Scope update: PR #7406 addresses the cluster-election member tracked by #6495. It catches RuntimeException only at that scheduler boundary, preserving its cleanup/release behavior and allowing the next fixed-rate attempt; fatal Errors remain visible. This is an incremental fix for #6495 only — the other periodic-task issues listed here still need independent validation and fixes. I did not introduce a shared Throwable-catching wrapper because the affected tasks have different cleanup and recovery semantics.

  4. added 9 commits that reference this issue on Oct 18, 2026
  5. added a commit that references this issue on Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions