AddWorkerSafely leaves registered kinds after an alias collision
メンテナーはふだん 1 日以内に返信
評価
調査の方向性
Start by reading worker.go, especially Workers.add, which the issue identifies as writing entries before validating remaining aliases. Use the provided reproducer as the regression test: after a collision, replacement workers for the primary kind and earlier alias should register successfully. An open linked pull request indicates work is already underway.
索引モデルが issue の本文から書いたものです。
説明
When AddWorkerSafely encounters a collision in a later KindAliases entry, it returns an error but leaves the new primary kind and preceding aliases registered. A caller that handles the error cannot subsequently register replacement workers for those kinds.
I reproduced this against current master 6cdaf386c3f672e267ff19a5eb3b105a081171bc, using the public API only, before any client initialization or Start. Workers.add writes entries before validating the remaining aliases.
Reproducer
In a separate Go module, require github.com/riverqueue/river v0.48.1-0.20261004195309-6cdaf386c3f6 and save this as registration_test.go:
package registryprobe
import (
"context"
"strings"
"testing"
"github.com/riverqueue/river"
)
type occupiedArgs struct{}
func (occupiedArgs) Kind() string { return "probe_occupied" }
type candidateArgs struct{}
func (candidateArgs) Kind() string { return "probe_primary" }
func (candidateArgs) KindAliases() []string {
return []string{"probe_early_alias", "probe_occupied"}
}
type primaryArgs struct{}
func (primaryArgs) Kind() string { return "probe_primary" }
type earlyAliasArgs struct{}
func (earlyAliasArgs) Kind() string { return "probe_early_alias" }
func addPrimary(workers *river.Workers) error {
return river.AddWorkerSafely(workers, river.WorkFunc(func(context.Context, *river.Job[primaryArgs]) error { return nil }))
}
func addEarlyAlias(workers *river.Workers) error {
return river.AddWorkerSafely(workers, river.WorkFunc(func(context.Context, *river.Job[earlyAliasArgs]) error { return nil }))
}
func TestFailedAliasRegistrationLeavesNoNewKinds(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
registerReplacement func(*river.Workers) error
}{
{"EarlierAlias", addEarlyAlias},
{"PrimaryKind", addPrimary},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
workers := river.NewWorkers()
if err := river.AddWorkerSafely(workers, river.WorkFunc(func(context.Context, *river.Job[occupiedArgs]) error { return nil })); err != nil {
t.Fatal(err)
}
err := river.AddWorkerSafely(workers, river.WorkFunc(func(context.Context, *river.Job[candidateArgs]) error { return nil }))
if err == nil || !strings.Contains(err.Error(), "probe_occupied") {
t.Fatalf("expected occupied-alias collision, got %v", err)
}
if err := tc.registerReplacement(workers); err != nil {
t.Fatalf("failed registration retained %s, preventing recovery: %v", tc.name, err)
}
})
}
}
func TestFreshRegistryControl(t *testing.T) {
t.Parallel()
workers := river.NewWorkers()
if err := addPrimary(workers); err != nil {
t.Fatal(err)
}
if err := addEarlyAlias(workers); err != nil {
t.Fatal(err)
}
}
Executed with Go 1.27.1:
go test -mod=readonly -race -p 1 ./... -run 'TestFailedAliasRegistrationLeavesNoNewKinds|TestFreshRegistryControl' -count=1 -timeout=60s -v
Both recovery checks fail:
failed registration retained EarlierAlias, preventing recovery: worker for kind "probe_early_alias" is already registered
failed registration retained PrimaryKind, preventing recovery: worker for kind "probe_primary" is already registered
The fresh-registry control passes. The run used an isolated local module with networking disabled during execution, no database and no running River client. I have not run River's full make test or make lint, and have not implemented a fix.
Should a failed registration leave the workers bundle unchanged? If that is the intended contract, I'd like to address this narrowly in worker.go with regression tests for alias collisions. This would not change ordinary kind renaming or permit registration after Client.Start; I noted the clarification in #335.
AI assistance (OpenAI/Codex) was used to investigate and draft the reproducer/report; the results above are from executing the pinned library, not generated test output.
- 主要言語
- Go
- スター
- 5.7k
- フォーク
- 187
- 平均マージ
- 1日 11時間
- マージ済み PR(30日)
- 63
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
riverqueue/river のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
riverqueue/river#1454 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 52/100
riverqueue/river#1411 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Remote JobCancel() can be silently lost while the notifier is reconnecting (no durable-poll fallback)対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 5/5 1週間以上 初心者へのやさしさ 45/100
riverqueue/river#1358 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
riverqueue/river#1258 · コメント 7 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
riverqueue/river#1225 · コメント 14 件 ·
メンテナーはふだん 1 日以内に返信
riverqueue/river の issue をすべて見る
似ている issue
-
Discriminator mapping keys are listed in a random order対応中かも @reuvenharrison が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
Idle compaction monitors LIST the replica every tick when the newest destination file spans more than one TXID対応中かも @pishuv が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
benbjohnson/litestream#1563 ·
メンテナーはふだん 2 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
agent-research agent-review-finding chore
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
jordansmall/spindrift#4922 ·
メンテナーはふだん 1 日以内に返信
-
gcsartifact: deleting a missing version returns an error対応中かも @ktsoator が今日担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 2 日以内に返信