Skip to content

feat: fail CI when pubsub.Publish calls are found in db transactions #17903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 19, 2025

Conversation

dannykopping
Copy link
Contributor

Publishing inside a db transaction can lead to database connection starvation/contention since it requires its own connection.

This ruleguard rule (one-shotted by Claude Sonnet 3.7 and finalized by @Emyrk) will detect two of the following 3 instances:

type Nested struct {
	ps pubsub.Pubsub
}

func TestFail(t *testing.T) {
	t.Parallel()

	db, ps := dbtestutil.NewDB(t)
	nested := &Nested{
		ps: ps,
	}

	// will catch this
	_ = db.InTx(func(_ database.Store) error {
		_, _ = fmt.Printf("")
		_ = ps.Publish("", []byte{})
		return nil
	}, nil)

	// will catch this
	_ = db.InTx(func(_ database.Store) error {
		_ = nested.ps.Publish("", []byte{})
		return nil
	}, nil)

	// will NOT catch this
	_ = db.InTx(func(_ database.Store) error {
		blah(ps)
		return nil
	}, nil)
}

func blah(ps pubsub.Pubsub) {
	ps.Publish("", []byte{})
}

The ruleguard doesn't recursively introspect function calls so only the first two cases will be guarded against, but it's better than nothing.

image

dannykopping and others added 2 commits May 16, 2025 17:02
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
@spikecurtis spikecurtis requested review from johnstcn and removed request for sreya and spikecurtis May 19, 2025 11:25
@spikecurtis
Copy link
Contributor

I definitely think it's a good idea, but my ruleguard-fu is pretty weak. @johnstcn do you mind taking a look?

Copy link
Member

@johnstcn johnstcn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may also need to match the inline assignment case e.g. if err := ps.Publish(...)

Signed-off-by: Danny Kopping <dannykopping@gmail.com>
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
@dannykopping dannykopping enabled auto-merge (squash) May 19, 2025 13:04
@Emyrk
Copy link
Member

Emyrk commented May 19, 2025

The ruleguard doesn't recursively introspect function calls so only the first two cases will be guarded against

Correct, the best you can attempt to do is catch passing ps as an argument to a function called in the body. Something like this?? Probably is not worth it, as you need to catch :=, =, and maybe method calls $_.$_($*_, $ps, $*_). Etc, etc, etc

		$x.InTx(func($y) error {
			$*_
			$_($*_ $ps, $*_)
			$*_
		}, $*_)

There will always be holes 😢.

dannykopping and others added 3 commits May 19, 2025 16:26
Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
@dannykopping dannykopping merged commit 87dc247 into main May 19, 2025
34 checks passed
@dannykopping dannykopping deleted the dk/pubpubnope branch May 19, 2025 14:52
@github-actions github-actions bot locked and limited conversation to collaborators May 19, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants