catalogscan

package
v1.147.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package catalogscan catalogs what the platform's own connections can see (#1918): every Trino table and view with its columns, every stored API operation and every GraphQL operation, written to the platform catalog so no external ingestion is needed. A scan never deletes: a dataset a connection no longer shows is marked removed and its curation stays readable.

Index

Constants

View Source
const (
	KindTrino   = "trino"
	KindAPI     = "api"
	KindGraphQL = "graphql"
)

The connection kinds the scan reads.

View Source
const DefaultScanInterval = 6 * time.Hour

DefaultScanInterval is how often every connection is scanned when no interval has been set.

View Source
const LockKey int64 = 4713210201

LockKey is the advisory lock a scan holds, so replicas never scan at once.

View Source
const MinScanInterval = 5 * time.Minute

MinScanInterval is the shortest interval an operator may set, so a mistyped value cannot keep every connection's engine busy.

View Source
const SettingsSection = "catalog"

SettingsSection is the platform_settings row the catalog's settings live in. They are configured in the admin portal, not the configuration file.

Variables

This section is empty.

Functions

This section is empty.

Types

type ColumnRow

type ColumnRow struct {
	Schema    string
	Table     string
	TableType string
	Column    string
	DataType  string
	Nullable  bool
}

ColumnRow is one row of a catalog's information_schema.columns, joined to its table's type.

type Connection

type Connection struct {
	Instance string
	Bound    string
}

Connection is one connection a source scans: the instance name a catalog reference carries and the name a call binds it by.

type Document

type Document struct {
	// Key is what an Operation's Document names it by.
	Key string
	// Filename is the name the document is kept under, extension included.
	Filename string
	MIMEType string
	Content  []byte
}

Document is a source's schema document as the platform holds it: an OpenAPI spec, a GraphQL SDL.

type Exclusion

type Exclusion struct {
	ConnectionKind string   `json:"connection_kind"`
	Connection     string   `json:"connection"`
	Entries        []string `json:"entries"`
}

Exclusion is the part of one connection an operator keeps out of the catalog: dotted path prefixes, such as a Trino catalog or catalog.schema.

type Exclusions

type Exclusions [][]string

Exclusions are the dataset paths an operator excluded on one connection, each a dotted prefix: "hive" excludes a Trino catalog, "hive.tmp" one schema in it, "mutation" every GraphQL mutation.

func ParseExclusions

func ParseExclusions(entries []string) Exclusions

ParseExclusions reads dotted entries into prefixes, ignoring blank ones.

func (Exclusions) Excludes

func (x Exclusions) Excludes(path ...string) bool

Excludes reports whether a dataset path starts with any excluded prefix.

type Loop

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

Loop runs a scan whenever the configured interval has passed since the last one any replica started, and whenever asked to.

func NewLoop

func NewLoop(scanner *Scanner, settings SettingsReader, db *sql.DB) *Loop

NewLoop builds the loop.

func (*Loop) AfterScan

func (l *Loop) AfterScan(fn func(context.Context))

AfterScan names what runs after each scan this replica finishes without error. Set it before Start.

func (*Loop) ScanNow

func (l *Loop) ScanNow(ctx context.Context, by string) error

ScanNow asks for a scan regardless of the interval and returns at once. The request is recorded, so the replica that next takes the scan lock runs it even when another replica is scanning now; this replica also checks at once. A request made while one is already waiting is the same request.

func (*Loop) Start

func (l *Loop) Start(ctx context.Context)

Start begins the loop. It checks at once, so a deployment's first scan runs when it starts rather than an interval later.

func (*Loop) Stop

func (l *Loop) Stop()

Stop ends the loop and waits for a scan in progress to return.

type Operation

type Operation struct {
	// Path is the operation's name under its connection: the operation id for
	// an API, the kind and dotted field path for GraphQL (query.repository).
	Path    []string
	Columns []catalog.ColumnInput
	// Document is the Key of the schema document the operation was read from,
	// or empty.
	Document string
}

Operation is one operation an API or GraphQL connection exposes, with the inputs it takes as columns.

type OperationReader

type OperationReader interface {
	Connections() []Connection
	Operations(ctx context.Context, bound string) ([]Operation, error)
	// Documents are the connection's schema documents, keyed as each
	// Operation's Document names them. A connection with none returns none.
	Documents(ctx context.Context, bound string) ([]Document, error)
}

OperationReader lists the operations of one kind of connection and the schema documents they were read from.

type OperationSource

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

OperationSource catalogs the operations of API or GraphQL connections.

func NewAPISource

func NewAPISource(r OperationReader) *OperationSource

NewAPISource catalogs every stored OpenAPI operation of each API connection.

func NewGraphQLSource

func NewGraphQLSource(r OperationReader) *OperationSource

NewGraphQLSource catalogs every operation of each GraphQL connection's stored schema.

func (*OperationSource) Connections

func (s *OperationSource) Connections() []Connection

Connections are the live connections of the kind.

func (*OperationSource) Datasets

func (s *OperationSource) Datasets(ctx context.Context, c Connection, skip Exclusions, yield func(catalog.DatasetInput) error) error

Datasets yields one dataset per operation.

func (*OperationSource) KeepDocuments

func (s *OperationSource) KeepDocuments(store catalog.DocumentStore) *OperationSource

KeepDocuments has the source keep each connection's schema documents in the catalog, linked from the datasets read from them (#1918). A nil store keeps none.

func (*OperationSource) Kind

func (s *OperationSource) Kind() string

Kind is the connection kind.

func (*OperationSource) Types

func (s *OperationSource) Types() []catalog.DatasetType

Types is the one operation type the source produces.

type Outcome

type Outcome struct {
	ConnectionKind string    `json:"connection_kind"`
	Connection     string    `json:"connection"`
	StartedAt      time.Time `json:"started_at"`
	FinishedAt     time.Time `json:"finished_at"`
	Datasets       int       `json:"datasets"`
	Removed        int       `json:"removed"`
	// Error is why the scan of this connection stopped. A failed scan marks
	// nothing removed: what it did not read is not evidence of absence.
	Error string `json:"error,omitempty"`
	// Unread are the parts of the connection the scan could not read, such
	// as a Trino catalog whose connector is down. The rest is cataloged, and
	// nothing under an unread part is marked removed.
	Unread []Unread `json:"unread"`
}

Outcome is what one connection's scan did.

type Recorder

type Recorder interface {
	RecordOutcome(ctx context.Context, o Outcome) error
}

Recorder keeps each connection's last outcome.

type Scanner

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

Scanner runs scans.

func New

func New(store Writer, settings SettingsReader, outcomes Recorder, sources ...Source) *Scanner

New builds a scanner over the given sources.

func (*Scanner) Scan

func (s *Scanner) Scan(ctx context.Context) ([]Outcome, error)

Scan scans every connection of every source and returns what each did, in source and connection order. Connections are read concurrently, and one connection failing does not stop the others.

type Settings

type Settings struct {
	// ScanInterval is how often every connection is scanned, as a Go
	// duration ("6h"). Empty means DefaultScanInterval.
	ScanInterval string      `json:"scan_interval"`
	Exclusions   []Exclusion `json:"exclusions"`
	UpdatedBy    string      `json:"updated_by,omitempty"`
	UpdatedAt    *time.Time  `json:"updated_at,omitempty"`
}

Settings are the catalog's operator settings.

func Defaults

func Defaults() Settings

Defaults are the settings of a deployment that never set any.

func (Settings) ExclusionsFor

func (s Settings) ExclusionsFor(kind, connection string) Exclusions

ExclusionsFor returns what is excluded on one connection.

func (Settings) Interval

func (s Settings) Interval() time.Duration

Interval is the scan interval, falling back to the default for an empty or unreadable value.

func (Settings) Validate

func (s Settings) Validate() error

Validate refuses an interval that does not parse or is too short, and an exclusion that names no connection.

type SettingsReader

type SettingsReader interface {
	Get(ctx context.Context) (Settings, error)
}

SettingsReader reads the catalog settings.

type Source

type Source interface {
	// Kind is the connection kind, the first part of every reference the
	// source produces.
	Kind() string
	// Connections are the live connections of this kind.
	Connections() []Connection
	// Datasets lists what the connection can see, skipping any dataset the
	// exclusions name. It reports each dataset through yield so a large
	// connection is not held in memory at once.
	Datasets(ctx context.Context, c Connection, skip Exclusions, yield func(catalog.DatasetInput) error) error
	// Types are the dataset types the source produces, the ones a scan of it
	// may mark removed.
	Types() []catalog.DatasetType
}

Source lists the datasets one kind of connection can see.

type Store

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

Store keeps the catalog settings and each connection's last scan outcome.

func NewStore

func NewStore(db *sql.DB) *Store

NewStore returns the store over db.

func (*Store) Get

func (s *Store) Get(ctx context.Context) (Settings, error)

Get returns the stored settings, or the defaults when none were saved.

func (*Store) Outcomes

func (s *Store) Outcomes(ctx context.Context) ([]Outcome, error)

Outcomes returns every connection's last scan.

func (*Store) RecordOutcome

func (s *Store) RecordOutcome(ctx context.Context, o Outcome) error

RecordOutcome keeps one connection's last scan.

func (*Store) Set

func (s *Store) Set(ctx context.Context, in Settings, author string) error

Set saves the settings after validating them.

type TrinoReader

type TrinoReader interface {
	Connections() []Connection
	Catalogs(ctx context.Context, bound string) ([]string, error)
	Columns(ctx context.Context, bound, catalogName string, fn func(ColumnRow) error) error
}

TrinoReader is what the Trino source reads through. Columns must report a table's rows together, in column order, and must skip information_schema.

type TrinoSource

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

TrinoSource catalogs every table and view a Trino connection can see.

func NewTrinoSource

func NewTrinoSource(r TrinoReader) *TrinoSource

NewTrinoSource builds the source.

func (*TrinoSource) Connections

func (s *TrinoSource) Connections() []Connection

Connections are the live Trino connections.

func (*TrinoSource) Datasets

func (s *TrinoSource) Datasets(ctx context.Context, c Connection, skip Exclusions, yield func(catalog.DatasetInput) error) error

Datasets reads each catalog in turn. A catalog that cannot be read is reported as unread after the others have been read, so one broken connector does not hide the rest, and nothing in it is marked removed.

func (*TrinoSource) Kind

func (*TrinoSource) Kind() string

Kind is "trino".

func (*TrinoSource) Types

func (*TrinoSource) Types() []catalog.DatasetType

Types are tables and views; a registered or webhook table keeps its own type and is never marked removed by a scan.

type Unread

type Unread struct {
	Path  string `json:"path"`
	Error string `json:"error"`
}

Unread is one part of a connection a scan could not read: the dataset path prefix in reference form, and why.

type UnreadError

type UnreadError struct {
	Parts []Unread
}

UnreadError is what a source returns when it read the connection except for some parts of it.

func (*UnreadError) Error

func (e *UnreadError) Error() string

Error lists each unread part with its reason.

type Writer

type Writer interface {
	PutDataset(ctx context.Context, in catalog.DatasetInput) (*catalog.Dataset, error)
	MarkRemoved(ctx context.Context, r catalog.Removal) (int, error)
}

Writer is what a scan needs from the catalog store.

Jump to

Keyboard shortcuts

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