Scope reset-trackers by keyword and report progress

The reset-trackers operator command reset every uncategorised,
non-excluded pattern of a banner and printed only a single summary
line once the transaction committed, giving no feedback during long
rebuilds.

Add a --keyword flag that scopes both the glob decomposition and the
mapping reset to patterns whose pattern or display name contains the
substring. The match lives in a new TrackerPatternFilter.WithPatternKeyword
field so it runs in SQL and is shared by the glob load and the
ResetAndRequestMappingByCookieCategoryID update, keeping the two in
lockstep. The banner-wide pattern-analysis re-arm is left unscoped.

Thread an optional progress callback through ResetBannerTrackers so the
command streams per-phase updates (category load, per-glob decomposition,
mapping reset, analysis re-arm) as the work runs.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-09 19:40:16 +02:00
parent 5415b2d438
commit faca86a022
5 changed files with 95 additions and 10 deletions

View File

@@ -1390,14 +1390,19 @@ WHERE
// iterating on the mapping agent. Excluded patterns are left untouched -
// exclusion is a deliberate suppression. The cookie_category_id key
// scopes the reset to the uncategorised category the caller resolves;
// the Scoper keeps it tenant-isolated. Returns the number of patterns
// reset.
// the Scoper keeps it tenant-isolated. When keyword is non-nil and
// non-empty, the reset is further restricted to patterns whose pattern or
// display name contains it (case-insensitive). Returns the number of
// patterns reset.
func (tps *TrackerPatterns) ResetAndRequestMappingByCookieCategoryID(
ctx context.Context,
tx pg.Tx,
scope Scoper,
cookieCategoryID gid.GID,
keyword *string,
) (int64, error) {
filter := NewTrackerPatternFilter(nil, nil, nil).WithPatternKeyword(keyword)
q := `
UPDATE tracker_patterns
SET
@@ -1410,12 +1415,14 @@ WHERE
%s
AND cookie_category_id = @cookie_category_id
AND excluded = false
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_category_id": cookieCategoryID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, filter.SQLArguments())
result, err := tx.Exec(ctx, q, args)
if err != nil {