Documentation
¶
Overview ¶
Package labels' match.go defines the SubscriptionMatch shape persisted as a nullable JSONB column on slack_channel_subscriptions. A nil column value (and equivalently a nil receiver here) means "every event in the org" — this collapses the legacy scope=org|install + InstallID *string design into a single column.
SubscriptionMatch composes per-resource TargetMatch slots; TargetMatch composes a list of IDs with an optional Selector. Composition rules:
- SubscriptionMatch.Matches: OR across non-nil kinds.
- TargetMatch.matches: OR within (id ∈ IDs OR Selector hit).
- Selector.Matches: AND across MatchLabels.
TargetKind is intentionally NOT shared with interests.ResourceKind: pkg/labels lives below internal/ in the import graph and the resource taxonomy is a property of the dispatch layer, not of label matching.
Index ¶
- func WithLabels(column string, lbls Labels) func(*gorm.DB) *gorm.DB
- func WithoutLabels(column string, lbls Labels) func(*gorm.DB) *gorm.DB
- type EventTargets
- type Labeled
- type Labels
- type Selector
- type SubscriptionMatch
- func (m *SubscriptionMatch) Canonical() string
- func (SubscriptionMatch) GormDataType() string
- func (m *SubscriptionMatch) Matches(t EventTargets) bool
- func (m *SubscriptionMatch) Scan(v interface{}) error
- func (m *SubscriptionMatch) Validate() error
- func (m SubscriptionMatch) Value() (driver.Value, error)
- type TargetKind
- type TargetMatch
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WithLabels ¶
WithLabels returns a GORM scope that filters rows where the JSONB column contains all the specified key-value pairs (PostgreSQL @> containment). A value of "*" is treated as a wildcard — it matches any value for that key (uses jsonb_exists() to check key existence). Returns a no-op scope if lbls is nil or empty.
func WithoutLabels ¶ added in v0.19.991
WithoutLabels is the negative counterpart of WithLabels. It filters rows where the JSONB column does NOT match any of the specified key-value pairs. A value of "*" rejects rows where the key is present at all (jsonb_exists). Other values reject only rows where the exact pair is set. Each NotMatchLabels entry is independent; a row is excluded if ANY entry matches it (mirrors Selector.Matches in-Go semantics). Returns a no-op scope if lbls is nil or empty.
Types ¶
type EventTargets ¶ added in v0.19.927
type EventTargets struct {
InstallID string
ComponentID string
ActionID string
InstallLabels Labels
ComponentLabels Labels
ActionLabels Labels
}
EventTargets is the projection of a dispatched event the matcher needs: the resolved entity IDs and their label sets at the time of dispatch. Any field may be empty — an absent ID short-circuits TargetMatch.matches so a component-only event never falsely satisfies an installs filter.
type Labeled ¶
type Labeled struct {
Labels Labels `json:"labels,omitzero" gorm:"default null" temporaljson:"labels,omitzero,omitempty"`
}
Labeled is an embeddable struct for any GORM model that supports labels. Embed it to get a consistent JSONB labels column with standard tags.
type Labels ¶
Labels defines a custom type for map[string]string that works with JSONB in GORM.
func ParseLabelsQuery ¶
ParseLabelsQuery parses a comma-separated "key:value" string into Labels. Returns nil for empty input. Entries without a separator are treated as wildcard key-only filters (value set to "*"). Supports both ":" and "=" as key-value separators. Splits on the first separator only, so values may contain colons or equals. A value of "*" means "match any value for this key" (wildcard).
func (Labels) GormDataType ¶
GormDataType returns the GORM data type for this field.
func (*Labels) Merge ¶
Merge adds all key-value pairs from other into the receiver, overwriting existing keys.
func (*Labels) RemoveKeys ¶
RemoveKeys removes the specified keys from the labels.
type Selector ¶ added in v0.19.927
type Selector struct {
MatchLabels Labels `json:"match_labels,omitempty"`
NotMatchLabels Labels `json:"not_match_labels,omitempty"`
}
Selector matches a label set with AND across keys. A value of "*" means "key must exist" (mirrors the wildcard semantics of WithLabels' jsonb_exists branch in scopes.go); any other value requires exact equality (mirrors @>).
NotMatchLabels expresses negation with the same value semantics: an entry rejects sets where the key is present and matches (exact value or wildcard existence). It exists so users can say "everything except env=stage" without having to enumerate every other env value or label every install.
Callers represent "match everything" as a *nil* Selector, never as Selector{MatchLabels: nil} — see Validate.
func (*Selector) Canonical ¶ added in v0.19.927
Canonical returns a deterministic JSON encoding (keys sorted) so the value can participate in the SlackChannelSubscription unique index without being at the mercy of Go map iteration order.
func (*Selector) Matches ¶ added in v0.19.927
Matches returns true iff every entry in MatchLabels is satisfied by set AND no entry in NotMatchLabels is satisfied by set. Empty MatchLabels and empty NotMatchLabels both mean "no constraint of that polarity"; callers should not construct such a Selector (Validate rejects it) but the matcher is permissive so dispatch never silently drops events on stale data.
func (*Selector) Validate ¶ added in v0.19.927
Validate enforces the invariant that a *non-nil* Selector carries at least one constraint (positive or negative). The "match everything" case is expressed by a nil pointer at the call site (TargetMatch.Selector == nil), not by empty maps — this keeps the dispatch / preview / canonical-key code paths from having to special-case an ambiguous shape.
type SubscriptionMatch ¶ added in v0.19.927
type SubscriptionMatch struct {
Installs *TargetMatch `json:"installs,omitempty"`
Components *TargetMatch `json:"components,omitempty"`
Actions *TargetMatch `json:"actions,omitempty"`
}
SubscriptionMatch is the per-subscription routing filter persisted as JSONB on slack_channel_subscriptions.match. Schema supports populating multiple kinds in one row (CLI uses this); the v1 modal will only ever write one kind at a time.
func (*SubscriptionMatch) Canonical ¶ added in v0.19.927
func (m *SubscriptionMatch) Canonical() string
Canonical returns a deterministic JSON encoding suitable for use in the slack_channel_subscriptions unique index column. Sorting nested slices / selector keys here means two semantically-equal matches produce identical bytes regardless of construction order or map iteration. "" for the match-all (nil / zero) case so it round-trips with the SQL NULL.
func (SubscriptionMatch) GormDataType ¶ added in v0.19.927
func (SubscriptionMatch) GormDataType() string
GormDataType marks the column as JSONB.
func (*SubscriptionMatch) Matches ¶ added in v0.19.927
func (m *SubscriptionMatch) Matches(t EventTargets) bool
Matches returns true if any non-nil kind matches its corresponding event target. A nil receiver is the org-wide subscription — match everything.
func (*SubscriptionMatch) Scan ¶ added in v0.19.927
func (m *SubscriptionMatch) Scan(v interface{}) error
Scan implements sql.Scanner for the JSONB match column. Mirrors the pattern used by interests.Interests so a NULL or empty column round-trips to a zero-valued struct (which Value() then turns back into NULL).
func (*SubscriptionMatch) Validate ¶ added in v0.19.927
func (m *SubscriptionMatch) Validate() error
Validate requires at least one populated kind and recurses into each. A fully-empty SubscriptionMatch should be expressed as a nil column, not as a row carrying an unconstrained struct.
func (SubscriptionMatch) Value ¶ added in v0.19.927
func (m SubscriptionMatch) Value() (driver.Value, error)
Value implements driver.Valuer. The zero match persists as SQL NULL — see isZero — so the column's "nil = match everything" semantics survive callers that hand us &SubscriptionMatch{} instead of nil.
type TargetKind ¶ added in v0.19.927
type TargetKind string
TargetKind is the set of entity kinds a SubscriptionMatch can target. Kept deliberately narrow — only kinds that the picker UI exposes today.
const ( TargetKindInstalls TargetKind = "installs" TargetKindComponents TargetKind = "components" TargetKindActions TargetKind = "actions" )
type TargetMatch ¶ added in v0.19.927
type TargetMatch struct {
IDs []string `json:"ids,omitempty"`
Selector *Selector `json:"selector,omitempty"`
}
TargetMatch filters one entity kind. An empty TargetMatch{} (no IDs, no Selector) is intentionally valid and means "any entity of this kind" — the modal needs an explicit "Any installs" option distinct from "Specific installs" / "By labels" without forcing a sentinel value.
func (*TargetMatch) Validate ¶ added in v0.19.927
func (t *TargetMatch) Validate() error
Validate ensures the filter is well-formed. Empty TargetMatch{} is allowed (see type doc); a non-nil Selector must itself be non-empty.