suppressionsync

package
v1.15.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 29, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package suppressionsync owns the write side of the account suppression list that provider feedback drives.

Slice B8 of the sending abuse prevention plan moves suppression upsert ownership here ahead of the provider-facing reconciliation (Task 11): every feedback-driven upsert advances the row's sync_generation and clears any pending removal, so a stale delete that raced the upsert loses. The race contract is fixed now, before a remote list exists, so Task 11 can add the SES-facing half without changing it.

The package is a leaf over pgx: it never reads a message, an agent, or a user row, which is what lets the deletion-resistant feedback path call it after the message that caused the bounce is long gone.

Index

Constants

View Source
const (
	SourceBounce    = "bounce"
	SourceComplaint = "complaint"
	SourceManual    = "manual"
)

Source values match the suppressions.source CHECK constraint.

Variables

This section is empty.

Functions

func CompleteRemovalTx

func CompleteRemovalTx(ctx context.Context, tx pgx.Tx, userID, address string, generation int64) (removed bool, err error)

CompleteRemovalTx deletes the row only if it is still pending removal at the generation the remover observed. A feedback upsert in between advanced the generation and cleared the flag, so the stale delete removes nothing: the address stays suppressed, which is the only safe answer when the provider has just said it bounces.

func MarkRemovalPendingTx

func MarkRemovalPendingTx(ctx context.Context, tx pgx.Tx, userID, address string) (generation int64, found bool, err error)

MarkRemovalPendingTx flags the row for removal and returns the generation the remover must present to CompleteRemovalTx. found=false when there is no such suppression.

Types

type Upsert

type Upsert struct {
	ID         string
	Inserted   bool  // a new row; false when an existing row was refreshed
	Generation int64 // sync_generation after this write
}

Upsert is the outcome of one feedback-driven upsert.

func UpsertTx

func UpsertTx(ctx context.Context, tx pgx.Tx, id, userID, address, reason, source, sourceMessageID string) (Upsert, error)

UpsertTx inserts the (user, address) suppression or, when it already exists, advances its sync_generation and clears removal_pending. The existing row's reason and source are kept: the first evidence wins, and a refresh must not rewrite a manual entry into a bounce.

The address must already be normalized (lower-cased, trimmed); this package does not own address canonicalization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL