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:
@@ -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 {
|
||||
|
||||
@@ -24,6 +24,7 @@ type TrackerPatternFilter struct {
|
||||
cookieCategoryID *gid.GID
|
||||
excluded *bool
|
||||
query *string
|
||||
patternKeyword *string
|
||||
source *CookieSource
|
||||
trackerType *TrackerType
|
||||
thirdPartyID *gid.GID
|
||||
@@ -47,6 +48,16 @@ func (f *TrackerPatternFilter) WithQuery(query *string) *TrackerPatternFilter {
|
||||
return f
|
||||
}
|
||||
|
||||
// WithPatternKeyword restricts the result to patterns whose pattern or
|
||||
// display name contains keyword (case-insensitive). It differs from
|
||||
// WithQuery, which matches display name or description: this targets the
|
||||
// raw pattern so operators can select by the matched domain or cookie
|
||||
// name. A nil or empty keyword disables the filter.
|
||||
func (f *TrackerPatternFilter) WithPatternKeyword(keyword *string) *TrackerPatternFilter {
|
||||
f.patternKeyword = keyword
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *TrackerPatternFilter) WithSource(source *CookieSource) *TrackerPatternFilter {
|
||||
f.source = source
|
||||
return f
|
||||
@@ -102,6 +113,13 @@ func (f *TrackerPatternFilter) SQLFragment() string {
|
||||
ELSE TRUE
|
||||
END
|
||||
AND
|
||||
CASE
|
||||
WHEN @filter_pattern_keyword::text IS NOT NULL AND @filter_pattern_keyword::text != '' THEN
|
||||
(pattern ILIKE '%' || @filter_pattern_keyword || '%'
|
||||
OR display_name ILIKE '%' || @filter_pattern_keyword || '%')
|
||||
ELSE TRUE
|
||||
END
|
||||
AND
|
||||
CASE
|
||||
WHEN @has_source_filter::boolean = false THEN TRUE
|
||||
WHEN @has_source_filter::boolean = true THEN
|
||||
@@ -148,6 +166,7 @@ func (f *TrackerPatternFilter) SQLArguments() pgx.StrictNamedArgs {
|
||||
"has_excluded_filter": false,
|
||||
"filter_excluded": nil,
|
||||
"filter_query": nil,
|
||||
"filter_pattern_keyword": nil,
|
||||
"has_source_filter": false,
|
||||
"filter_source": nil,
|
||||
"has_tracker_type_filter": false,
|
||||
@@ -177,6 +196,10 @@ func (f *TrackerPatternFilter) SQLArguments() pgx.StrictNamedArgs {
|
||||
args["filter_query"] = *f.query
|
||||
}
|
||||
|
||||
if f.patternKeyword != nil {
|
||||
args["filter_pattern_keyword"] = *f.patternKeyword
|
||||
}
|
||||
|
||||
if f.source != nil {
|
||||
args["has_source_filter"] = true
|
||||
args["filter_source"] = string(*f.source)
|
||||
|
||||
Reference in New Issue
Block a user