Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

AddWorkerSafely leaves registered kinds after an alias collision

Aperta
#1,433 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@flcrom ci sta già lavorando.

Dal 5/10/2026.

  • #1440 di @flcrom — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
go
Ambito
backend

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.

Lingua principale
Go
Stelle
5.7k
Fork
187
Merge medio
1g 11h
PR unite (30g)
63

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di riverqueue/river

Tutte le issue di riverqueue/river

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.