topics

package
v1.3.1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const NSDelimiter = ":"

NSDelimiter separates the namespace from the topic part of a namespaced channel ("acme:chat.room1"). It participates in segment splitting alongside delimiter ("."), so "acme:chat.room1" is the three segments [acme, chat, room1] and "acme:*" is a single-segment wildcard scoped to the "acme" namespace. Exactly one NSDelimiter is required: client-visible channels can therefore never collide with reserved identifiers that use ":" differently (e.g. Redis control keys).

Variables

View Source
var ErrBadChannel = errors.New("channel does not fit the namespaced channel grammar")

ErrBadChannel is returned when a channel is rejected by ValidateChannel: it does not carry exactly one namespace delimiter, its namespace part is not a valid namespace identifier, or its topic part fails the structural topic rules (see ValidateTopic).

View Source
var ErrBadNamespace = errors.New("invalid namespace identifier")

ErrBadNamespace is returned when a namespace identifier is rejected: it is empty, longer than namespaceMaxLen, or contains characters outside [a-z0-9-] (leading/trailing "-" is also rejected).

View Source
var ErrBadSubscriber = errors.New("subscriber is not comparable")

ErrBadSubscriber is returned by Subscribe when sub cannot be used as a map key. Matcher implementations store subscribers in maps, so non-comparable values are rejected up front instead of panicking mid-operation.

View Source
var ErrBadTopic = errors.New("topic does not fit within topic space")

ErrBadTopic is returned when a topic is rejected: it is empty, contains explicit empty segments (e.g. "a.", ".a", "a..b"), contains "**" outside of the final segment (e.g. "a.**.b", "a**b"), or does not fit within the matcher's topic space.

Functions

func Match added in v0.2.0

func Match(pattern, topic string) bool

Match reports whether the subscription pattern matches the concrete topic. It is the exported form of matchCriteria — the single pattern-matching implementation shared by every caller (e.g. sessionCoversChannel); there is no second glob dialect.

func NamespaceOf added in v1.2.0

func NamespaceOf(channel string) (string, error)

NamespaceOf returns the namespace part of a namespaced channel, or ErrBadChannel when the channel does not carry exactly one namespace delimiter with a valid namespace identifier.

func SplitSegments added in v1.2.0

func SplitSegments(s string) []string

SplitSegments splits a topic, pattern or channel into its segments. Both delimiter (".") and NSDelimiter (":") separate segments, so the namespaced channel "acme:chat.room1" is the three segments [acme, chat, room1]. Unlike strings.FieldsFunc, consecutive delimiters yield empty segments, preserving the invalid-topic detection in validTopic and matchCriteria.

func ValidateChannel added in v1.2.0

func ValidateChannel(channel string) error

ValidateChannel validates a namespaced channel or subscription pattern: exactly one nsDelimiter, a valid namespace identifier before it, and a structurally valid topic after it (ValidateTopic rules; wildcards are allowed per those rules). It is the entry point for the session-plane namespace guard; ValidateTopic stays structure-only.

func ValidateNamespace added in v1.2.0

func ValidateNamespace(ns string) error

ValidateNamespace reports whether ns is a valid namespace identifier: 1-32 characters from [a-z0-9-], starting and ending with [a-z0-9].

func ValidateTopic added in v0.2.0

func ValidateTopic(topic string) error

ValidateTopic reports whether topic is a valid channel or subscription pattern: a non-empty list of non-empty segments separated by "." or ":" with "**" allowed only as the final segment. It is the single structural validation entry point shared by the matchers, the hub's exact-subscription path and the broker publish paths; the namespace grammar (ValidateChannel) layers on top of it at the session boundary.

Types

type Matcher

type Matcher interface {
	// Subscribe adds the Subscriber to the topic and returns a Subscription.
	Subscribe(topic string, sub Subscriber) (*Subscription, error)

	// Unsubscribe removes the Subscription. It is idempotent and safe to call
	// with a nil Subscription.
	Unsubscribe(sub *Subscription)

	// Lookup returns the Subscribers for the given topic.
	Lookup(topic string) []Subscriber
}

Matcher contains topic subscriptions and performs matches on them.

Topics are lists of non-empty segments separated by "." or ":" (e.g. "forex.eur", "acme:chat.room1", "*", "a.b.c"). The single segment "*" is a wildcard matching exactly one segment. The final segment "**" is a multi-segment wildcard matching zero or more segments (MQTT-style suffix wildcard): "a.**" matches "a", "a.b" and "a.b.c", and a bare "**" matches every topic. "**" anywhere else (middle position like "a.**.b" or embedded like "a**b") is rejected. The empty topic, topics with explicit empty segments ("a.", ".a", "a..b") and topics with middle-position "**" are rejected by Subscribe with ErrBadTopic and never match in Lookup. Segment count is significant for everything but a trailing "**": "a" does not match "a.b".

Duplicate subscription semantics differ between implementations:

  • The naive, trie and cs-trie matchers are idempotent per (topic, Subscriber): subscribing the same subscriber to the same topic twice is a no-op, and one Unsubscribe removes it.
  • The inverted and optimized inverted bitmap matchers are multi-subscription: every Subscribe call allocates a fresh position, so the same subscriber may subscribe to the same topic multiple times and each subscription must be removed with its own Unsubscribe.

Unsubscribe is idempotent: calling it twice with the same Subscription, or with a nil Subscription, is a no-op.

func NewCSTrieMatcher

func NewCSTrieMatcher() Matcher

func NewInvertedBitmapMatcher

func NewInvertedBitmapMatcher(topicSpace []string) Matcher

func NewNaiveMatcher

func NewNaiveMatcher() Matcher

func NewOptimizedInvertedBitmapMatcher

func NewOptimizedInvertedBitmapMatcher(topicSpaceSize uint) Matcher

func NewTrieMatcher

func NewTrieMatcher() Matcher

type Subscriber

type Subscriber interface{}

Subscriber is a value associated with a subscription.

Subscribers must be comparable: implementations store them in maps and use them as keys. Non-comparable values are rejected by Subscribe with ErrBadSubscriber. A nil Subscriber is allowed.

type Subscription

type Subscription struct {
	ID         uint32
	Topic      string
	Subscriber Subscriber
}

Subscription represents a topic subscription.

ID is only meaningful for the bitmap implementations; the naive, trie and cs-trie implementations leave it at its zero value. A Subscription is only valid for the Matcher that created it.

Jump to

Keyboard shortcuts

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