Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

AddWorkerSafely leaves registered kinds after an alias collision

Offen
#1,433 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@flcrom arbeitet bereits daran.

Seit 05.10.2026.

  • #1440 von @flcrom — offen

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
25/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
go
Bereich
backend

Rechercherichtung

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.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

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.

Vorherrschende Sprache
Go
Sterne
5.7k
Forks
187
Ø Merge
1 T. 11 Std.
Gemergte PRs (30 T.)
63

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus riverqueue/river

Alle Issues in riverqueue/river

Ähnliche Issues

Weitere Issues zu Go

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.