Help us shape the future of Go! Take the 2026 Go Developer Survey

discoverystore

package
v0.136.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: MIT Imports: 53 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalid = errors.New("discovery: invalid request")
)
View Source
var (
	// ErrNoSignals is a read or write that needs the signal plane, which the
	// engine runs without.
	ErrNoSignals = errors.New("discovery: no signal plane")
)
View Source
var (
	ErrNotFound = errors.New("discovery: not found")
)
View Source
var (
	// ErrSignalsDown is ErrNoSignals while the configured signal plane is
	// down: retry later.
	ErrSignalsDown = fmt.Errorf("%w: ClickHouse is down", ErrNoSignals)
)

Functions

This section is empty.

Types

type DailyReleasesOptions

type DailyReleasesOptions struct {
	discovery.Reader
	Filter
	// Days includes EndDate, or today; 10 by default, from 1 through 31.
	Days int
	// EndDate is an inclusive YYYY-MM-DD in TimeZone; today by default.
	// Future dates are rejected. Visibility is evaluated at the current time.
	EndDate string
	// TimeZone is an IANA zone, UTC by default.
	TimeZone     string
	CardEntities []string
}

DailyReleasesOptions selects a complete calendar-day window of releases.

type Engagement

type Engagement struct {
	Store  *signalstore.Store
	Tenant string
	// RRFK is the seed fusion constant (default 60).
	RRFK int
}

Engagement is the co-engagement Candidates source: Similar reads works co-engaged with the anchor; ForSubject seeds from the subject's highest-signal non-negative works and RRF-fuses each seed's co-engaged list.

func NewEngagement

func NewEngagement(conn signal.Conn, database, tenant string) (Engagement, error)

NewEngagement builds the default source over a hub's ClickHouse database.

func (Engagement) ForSubject

func (e Engagement) ForSubject(ctx context.Context, subject signal.Subject, q discovery.Query) ([]discovery.Candidate, error)

ForSubject never returns its seeds.

func (Engagement) Similar

type Filter

type Filter struct {
	Kind string

	// IDs bounds a public hydration read; normal visibility/domain rules apply.
	IDs []string
	// Entities are all required (effective on the card's version); a position
	// sort orders by the first, which must be of an ordered entity kind. A
	// reader's content filter never hides an entity's content from a list
	// requiring that entity.
	Entities        []string
	ExcludeEntities []string
	// Traits are all required on the card's version.
	Traits []string
	// Attributes are "name:value" equalities on Kind's declared filterable
	// attributes, all required.
	Attributes []string
	// ReleasedOn is a day (YYYY-MM-DD) or month (YYYY-MM) of publication in
	// TimeZone.
	ReleasedOn string
	// PublishedWithin keeps currently live publications in this popularity
	// period (7d, 30d, 90d, 365d or all). It does not change the ranking window.
	PublishedWithin string

	// TimeZone is an IANA zone; UTC by default.
	TimeZone string
	// ViewStatus is unseen, in_progress or completed: the signed-in
	// reader's own.
	ViewStatus string
	// ChannelIDs keeps content one of these channels owns (the original feed);
	// owning is not membership and opens nothing.
	ChannelIDs []string

	// Creators keeps content one of these users is credited on.
	Creators []string
	// Access keeps content at one of these levels: public is what anyone
	// opens now (audience releases included), the others what stays locked at that
	// level.
	Access []string
	// Tiers keeps content locked behind one of these tiers.
	Tiers []string
	// contains filtered or unexported fields
}

Filter selects contents: what lists, search and release dates share.

type ListOptions

type ListOptions struct {
	discovery.Reader
	Filter
	// Sort is newest, oldest, title, popular[:period], top_rated[:period],
	// most_favorited, position or random; the kind's configured
	// sort, else newest, by default. Popular suffixes are configured bucket IDs.
	Sort string
	// ActivityFrom and ActivityUntil choose a custom popularity window of whole
	// UTC dates [from, until). Both require SortPopular and an explicit Kind.
	// They select activity dates, independently of publication-date filters.
	ActivityFrom  string
	ActivityUntil string
	// CardEntities are the entity kinds cards name; every kind with a page by
	// default.
	CardEntities []string
	Cursor       string
	// Page numbers pages from 1 instead of Cursor.
	Page int
	// Limit defaults to 24 and is capped at 100.
	Limit int
	// Summary adds selection-wide counts on the first page, or on every
	// numbered page.
	Summary bool
}

ListOptions select one page of a list.

type Options

type Options struct {
	Pool   *pgxpool.Pool
	Schema string
	Tenant string
	Kinds  kinds.Config
	// Visibility is the catalog's visibility rule; every read applies it.
	Visibility Visibility
	// Resolver decides direct reads: the anchor of a similar list and the
	// content a signal names.
	Resolver resolve.Resolver
	// Gate decides each card's access.
	Gate *entitlement.Gate
	// ActivitySigner preserves trusted event-time access facts. Nil retains
	// legacy telemetry without normalized-population qualification.
	ActivitySigner discovery.ActivitySigner
	// ActivityCohorts are ordered, application-defined readership categories.
	ActivityCohorts []signal.ActivityCohort
	// Entities names the entities on cards and in typeahead.
	Entities *entitystore.Store
	// Channels resolves the primary authoring home independently of metadata.
	Channels *channelstore.Store
	// Media resolves cards' covers and ladders; nil leaves them out.
	Media discovery.Media
	// Hub is the keyword search client and the signal plane. Without a
	// signal plane, or while it is down, history, signals, exposures,
	// view_status, similar, recommendations and popularity are unavailable.
	Hub *hub.Hub
	// Candidates sources similar and recommendations; nil is co-engagement
	// over the signal plane.
	Candidates discovery.Candidates
	// Tenure supplies elapsed access to configured tiers; nil omits it from
	// account statistics. Billing adapters may implement access.TenureReader.
	Tenure access.TenureReader
	Logger *slog.Logger
	Now    func() time.Time
}

Options configure a Service.

type RecommendationOptions

type RecommendationOptions struct {
	discovery.Reader
	Filter
	CardEntities []string
	// Limit defaults to 12 and is capped at 50.
	Limit int
	// Summary counts omissions within the bounded recommendation candidates.
	Summary bool
}

RecommendationOptions select a similar or "for you" list.

type Recommender

type Recommender struct {
	Candidates discovery.Candidates
	Store      *signalstore.Store
	Tenant     string
	// DefaultLimit applies when options leave Limit zero (default 20).
	DefaultLimit int
	// RRFK scales popularity-fill tail scores (default 60).
	RRFK int
}

Recommender turns a Candidates source into tenant-scoped discovery lists.

func (Recommender) Recommend

func (r Recommender) Recommend(ctx context.Context, subject signal.Subject, opts discovery.RecommendOptions) ([]discovery.Hit, error)

Recommend returns "for you" works for a subject: excluding already-seen (unless IncludeSeen) and always disliked works, filled on cold start or thin candidates from popularity of the last 30 days, then of all time, then Backfill.

func (Recommender) Similar

Similar returns works like the anchor, never the anchor itself.

type ReleaseDatesOptions

type ReleaseDatesOptions struct {
	discovery.Reader
	Filter
	// By is month (the default) or day.
	By string
	// Cursor is the previous page's next_cursor: dates before it follow.
	Cursor string
	// Limit defaults to 60 and is capped at 1000.
	Limit int
}

ReleaseDatesOptions select the release date index.

type SearchOptions

type SearchOptions struct {
	discovery.Reader
	Filter
	Query string
	// Sort is relevance (the default) or a list sort of the best matches.
	Sort         string
	CardEntities []string
	Cursor       string
	// Page numbers pages from 1 instead of Cursor.
	Page int
	// Limit defaults to 24 and is capped at 100.
	Limit int
	// Unpersonalized ranks a signed-in reader's results as anyone's.
	Unpersonalized bool
	// Summary adds contextual counts on the first page, or on every numbered
	// page.
	Summary bool
}

SearchOptions select one page of keyword search.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service serves discovery for one tenant.

func New

func New(o Options) (*Service, error)

New validates o.

func (*Service) Activity

func (s *Service) Activity(ctx context.Context, kind string, days int) (discovery.Activity, error)

Activity reads a kind's measured readership per day of the last days (10 by default, at most 90).

func (*Service) ActivityContexts

ActivityContexts captures eligibility at display/open time, before the browser queues its beacons. Its population observation includes subscribers browsing free content, not only subscribers opening a paid gallery.

func (*Service) Availability

func (s *Service) Availability(ctx context.Context, kind string, window signal.Window, scope signal.ActivityScope, contents []string) (signal.Availability, error)

Availability returns only immutable catalog history. It never treats a current rule as evidence of how content was accessible before adoption. Non-nil contents bound it to those contents of the kind.

func (*Service) ChannelFeed

func (s *Service) ChannelFeed(ctx context.Context, id string, r discovery.Reader, cursor string, limit int) (discovery.ContentPage, error)

ChannelFeed returns originals and repost references through the usual catalog reader policy. Reposts preserve the original IDs, versions and interactions.

func (*Service) ClearSearches

func (s *Service) ClearSearches(ctx context.Context, actor access.Actor, session, query string) error

ClearSearches deletes the reader's recent searches: one query, or all of them.

func (*Service) ContentFilters

func (s *Service) ContentFilters(ctx context.Context, actor access.Actor, language string) (discovery.ContentFilters, error)

ContentFilters resolves names from the entity service; policy itself is never exposed. Canonical shared choices win over preserved legacy preferences.

func (*Service) EraseSearches

func (s *Service) EraseSearches(ctx context.Context, subjects []signal.Subject) error

EraseSearches deletes subjects' recent searches.

func (*Service) Favorites

Favorites pages what the signed-in reader favorited, most recent first: the content items their listing shows (one card per item, whichever version they favorited) or the active entities.

func (*Service) ForgetHistory

func (s *Service) ForgetHistory(ctx context.Context, actor access.Actor, kind, contentID string) error

ForgetHistory erases the signed-in reader's signals for one content item, one kind, or every kind.

func (*Service) Handler

func (s *Service) Handler(a auth.Authenticator) (http.Handler, error)

Handler serves the discovery routes: lists, search, typeahead, similar and "for you" lists, the release date index, the reader's content filters and history, and the signals and exposures clients send. a says who each request is; each request runs in access.WithMemo, so a page costs one billing read.

func (*Service) History

History pages the contents the signed-in reader engaged with, most recent first they already know. Current domain, publication, preferences and access rules still apply.

func (*Service) ImportLegacyReading

func (s *Service) ImportLegacyReading(ctx context.Context, in []discovery.ImportLegacyReading) error

ImportLegacyReading preserves migration bookmarks without fabricating actual reading events. It is called only by the authorized bulk importer.

func (*Service) ImportSignals

func (s *Service) ImportSignals(ctx context.Context, in []discovery.ImportSignal) error

ImportSignals records explicit imported clicks under the importer authority. Legacy resume/progress has a separate non-measured import path. ErrNoSignals without a signal plane (ErrSignalsDown while it is down).

func (*Service) InitializeContentFilters

func (s *Service) InitializeContentFilters(ctx context.Context, actor access.Actor, u discovery.ContentFiltersInitialization) error

func (*Service) KnownCards

KnownCards hydrates explicit IDs in caller order. No publication, domain, preference, access or deletion rule is relaxed.

func (*Service) Library

Library lists the editions actor holds an exact version key of: the keys under the tenant's content prefix, from the request's one billing read. Deleted content is listed too, as purchase history, within the current domain's hard visibility boundary; it is not readable.

func (*Service) List

List pages cards: one per content item the reader's listing shows that matches the filter, in the sort's order.

func (*Service) ManagementSuggestions

ManagementSuggestions are lean, private editor targets. Public domain, optional-reader, publication and billing rules never substitute for editor authorization; current draft/held names remain separate from public search.

func (*Service) MyStats

func (s *Service) MyStats(ctx context.Context, actor access.Actor) (discovery.MyStats, error)

MyStats reads a person's account statistics; finished contents only with a signal plane.

func (*Service) PruneSearches

func (s *Service) PruneSearches(ctx context.Context) (int, error)

PruneSearches deletes recent searches unused for SearchRetention, and any of an erased person (one recorded while the erasure ran). It returns how many it deleted.

func (*Service) RecentSearches

func (s *Service) RecentSearches(ctx context.Context, actor access.Actor, session string, limit int) (discovery.RecentSearches, error)

RecentSearches lists the reader's recent searches, newest first.

func (*Service) Recommendations

func (s *Service) Recommendations(ctx context.Context, o RecommendationOptions) (discovery.ContentPage, error)

Recommendations lists contents for the signed-in reader from their history, filled from what is popular lately, then ever, then newest, that their listing shows; seen and disliked content left out.

func (*Service) RecordEngagement

func (s *Service) RecordEngagement(ctx context.Context, actor access.Actor, in discovery.EngagementBatch) error

RecordEngagement records measured intervals under their original trusted access receipt. Short positive partials are retained; person qualification happens after aggregation, so two legitimate 600ms partials are not lost.

func (*Service) RecordExposures

func (s *Service) RecordExposures(ctx context.Context, actor access.Actor, in discovery.Exposures) error

RecordExposures records result lists for click attribution.

func (*Service) RecordSearch

func (s *Service) RecordSearch(ctx context.Context, actor access.Actor, session, query string, results int) error

RecordSearch keeps a query the reader searched; a signed-out reader without a session, or an erased person, keeps none.

func (*Service) RecordSignals

func (s *Service) RecordSignals(ctx context.Context, actor access.Actor, in discovery.Signals) error

RecordSignals records explicit card clicks. Loaded/visible reading attention is submitted separately through RecordEngagement.

func (*Service) RefreshPopularRankings

func (s *Service) RefreshPopularRankings(ctx context.Context) error

RefreshPopularRankings prepares the host's declared choices, including on an empty installation with no public traffic. A reader never creates work.

func (*Service) ReleaseDates

ReleaseDates counts the contents the reader's listing shows by the day or month they were published, newest first.

func (*Service) Releases

Releases reads one complete window so clients can reveal more cards without additional API calls. It shares listing visibility, preferences and access.

func (*Service) Search

func (s *Service) Search(ctx context.Context, o SearchOptions) (result discovery.SearchPage, resultErr error)

Search pages the contents matching a keyword query, grouped per content item, under the reader's visibility and the filter.

func (*Service) SetContentFilters

func (s *Service) SetContentFilters(ctx context.Context, actor access.Actor, u discovery.ContentFiltersUpdate) error

func (*Service) SignalPlane

func (s *Service) SignalPlane() bool

SignalPlane reports whether signals are recorded now.

func (*Service) Similar

Similar lists contents like the anchor content that the reader's listing shows; of the anchor's kind unless the filter names one.

func (*Service) SitemapContents

func (s *Service) SitemapContents(ctx context.Context, o discovery.SitemapOptions) (discovery.SitemapPage, error)

SitemapContents pages the site's public pages of a content kind.

func (*Service) SitemapEntities

func (s *Service) SitemapEntities(ctx context.Context, o discovery.SitemapOptions) (discovery.SitemapPage, error)

SitemapEntities pages the site's public pages of an entity kind: active entities holding content the site lists.

func (*Service) Standing

func (s *Service) Standing(ctx context.Context, actor access.Actor, refs []contentref.ContentRef) ([]catalog.ViewerState, error)

Standing is a signed-in person's standing with content items and versions, per ref in order: their favorites and, with a signal plane, their progress. A failed signal read leaves progress out.

func (*Service) Typeahead

Typeahead suggests contents the reader's listing shows and active entities, matching literal substrings of their own titles, names or aliases, with prefix bias. Full search separately handles contextual keywords and typos.

type Visibility

type Visibility interface {
	Viewer(ctx context.Context, o catalog.ViewerOptions) (*catalogstore.Viewer, error)
}

Visibility is the catalog's one visibility rule (engine spec §4): *catalog.Store. A request's Viewer renders it as SQL over content_facets.

Jump to

Keyboard shortcuts

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