Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Local activity scheduleToClose budget restarts when a timer-backed retry runs on replay

オープン
#3,106 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@sangkyoonnam がすでに取り組んでいます。

2026年10月1日 から。

  • #3107 @sangkyoonnam による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
68/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
java

調査の方向性

Start in temporal-sdk/src/main/java/io/temporal/internal/statemachines/LocalActivityCallback.java, tracing how firstSkd is parsed and passed into retries. Reproduce with sticky queue scheduling disabled and the listed local activity options; done means replayed retries preserve the original schedule-to-close budget, terminate with RETRY_STATE_TIMEOUT, and a regression test covers the behavior.

索引モデルが issue の本文から書いたものです。

説明

Expected Behavior

A local activity that retries through a workflow timer keeps counting ScheduleToCloseTimeout from its first attempt across replay. sdk-core restores the original schedule time from the marker and hands it back with the retry (local_activity_state_machine.rs:147, :646); its proto says it "Must be passed with attempt to the retry LA" (activity_result.proto:97-99). sdk-go sets the schedule time from workflow time (workflow.go:1281) and computes the deadline from it (internal_event_handlers.go:892-894), so both preserve the original scheduling baseline across replay.

Actual Behavior

Java parses firstSkd from the marker into LocalActivityFailedException, then discards it (LocalActivityCallback.java:29-37). The retry uses System.currentTimeMillis() captured when workflow code ran, which on replay is the replay clock. The retry pre-check then sees a budget computed from that clock, so a replay can reset the budget. In the reproduction below the activity runs all 5 attempts and ends with RETRY_STATE_MAXIMUM_ATTEMPTS_REACHED instead of RETRY_STATE_TIMEOUT. Further evictions can keep extending it while retries remain eligible. This dates to v1.18.0 (#1542); it's not a regression.

Steps to Reproduce the Problem

  1. Worker with WorkerOptions.newBuilder().setStickyQueueScheduleToStartTimeout(Duration.ZERO), so every workflow task replays full history (an eviction or restart during backoff does the same).
  2. Run:
@ActivityInterface public interface Fails { String run(); }
public static class FailsImpl implements Fails {
  public String run() { throw new RuntimeException("fail"); }
}
@WorkflowInterface public interface Wf { @WorkflowMethod String run(); }
public static class WfImpl implements Wf {
  public String run() {
    return Workflow.newLocalActivityStub(Fails.class, LocalActivityOptions.newBuilder()
        .setScheduleToCloseTimeout(Duration.ofSeconds(10))
        .setLocalRetryThreshold(Duration.ofSeconds(1))
        .setRetryOptions(RetryOptions.newBuilder()
            .setInitialInterval(Duration.ofSeconds(4))
            .setBackoffCoefficient(1)
            .setMaximumAttempts(5).build())
        .build()).run();
  }
}
  1. Expected: RETRY_STATE_TIMEOUT after about 2 attempts, since attempt 3 would start at ~8s with ~2s left, under the 4s backoff. Actual: RETRY_STATE_MAXIMUM_ATTEMPTS_REACHED after all 5 attempts.

Specifications

  • Version: main at 4a4e6b2d (v1.40.0-4)
  • Platform: macOS, JDK 21, in-process test server

One limitation: the marker value is the first worker's wall clock, so cross-worker clock skew can shorten or lengthen the budget. I have a fix with a regression test ready.

主要言語
Java
スター
433
フォーク
257
平均マージ
2日 20時間
マージ済み PR(30日)
20

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

temporalio/sdk-java のほかの issue

temporalio/sdk-java の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。