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

pluginstore

package
v0.0.0-...-d646d51 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package pluginstore gives each plugin its own PostgreSQL schema (#2481).

なぜ schema を分けるのか

mk-go の migration は連番 (`000074_...`) で、プラグインをこの列に載せられない。 2 つのプラグインが同時に次の番号を要求して衝突する。schema を分ければ、各 プラグインが本体の連番と干渉せず独立した migration を持てる。

手法は #2450 でテスト用に導入したものと同じ (`search_path` を DSN に張る)。 pgx は未知の keyword を runtime parameter として送るので、接続ごとに適用され、 pool が新しい接続を張っても schema が変わらない。

分離の強さについて

`search_path` は**事故を防ぐ仕組みであって、権限による強制ではない**。 プラグインが `public.note` のように明示的に修飾すれば mk-go のテーブルに 到達できる。プラグインは同一プロセスの Go コードで、そもそも設定ファイルから 認証情報を読めるため、ここを権限で塞いでも意味は薄い。

重要なのは「素直に書いたら本体のテーブルに触れない」ことで、これは満たす。 **ノートの可視性判定はアプリケーション側の 4 箇所にあり DB には無い**ので、 `SELECT * FROM note` が通ってしまうと非公開ノートが混ざる。

Index

Constants

View Source
const SchemaPrefix = "plugin_"

SchemaPrefix namespaces plugin schemas so they never collide with mk-go's own objects (which live in `public`).

Variables

This section is empty.

Functions

func Apply

func Apply(ctx context.Context, db Executor, migrations []Migration) error

Apply runs the migrations that have not been applied yet against db.

Store.Migrate はロックを取ってからこれを呼ぶ。**plugin/plugintest も同じ 関数を使う** — フェイクが本番と違う挙動をすると、テストが通ったのに本番で 落ちる (実際 plugintest が素朴に実行していて、2 回目で 「already exists」になった)。

func ListSchemas

func ListSchemas(ctx context.Context, baseDSN string) ([]string, error)

ListSchemas returns the plugin schemas that exist in the database.

func OrphanSchemas

func OrphanSchemas(present []string, known []string) []string

OrphanSchemas returns the schemas that belong to no currently built-in plugin.

**プラグインを消してもデータは自動では消さない。** カウンタと違って削除した 行は復元できないので、一時的に外しただけの運用 (更新・切り分け) でデータが 飛ぶ方が損害が大きい (fsck が孤児行を報告に留めているのと同じ理由、#2473)。

代わりに「残っていること」を見えるようにする。黙って残ると、運営者は自分の DB に何があるか把握できなくなる。

突き合わせは**プラグイン名から schema 名を作る向き**で行う。schema 名から プラグイン名へ戻すと、`plugin_game_info` が `game-info` と `game_info` の どちらだったか判別できない (SchemaName が `-` を `_` に倒すため)。

func SchemaName

func SchemaName(name string) (string, error)

SchemaName maps a plugin name to its schema, validating the identifier.

identifier は SQL の placeholder にできないため文字列として埋め込むしかない。 plugin.Definition 側でも名前を検証しているが、**ここでも検証する**: 埋め込みの 直前で確かめないと、呼び出し経路が増えたときに検証の無い経路ができる。

Types

type Executor

type Executor interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
}

Executor is the subset of *sql.DB / *sql.Conn that applying migrations needs.

type Migration

type Migration struct {
	Version int
	SQL     string
}

Migration is one versioned schema change.

type Store

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

Store is one plugin's storage handle.

func Open

func Open(baseDSN, name string, maxConns int) (*Store, error)

Open creates the plugin's schema if needed and returns a pool pinned to it.

baseDSN は mk-go 本体と同じ接続文字列 (config.Config.DSN())。

func (*Store) Close

func (s *Store) Close() error

Close releases the pool.

func (*Store) DB

func (s *Store) DB() *sql.DB

DB returns the pool. search_path はこの schema に固定されている。

func (*Store) Migrate

func (s *Store) Migrate(ctx context.Context, migrations []Migration) error

Migrate applies migrations that have not run yet, in version order.

**プロセスが複数あっても安全に動く必要がある。** role 分割 (#2459) で server と queue が別プロセスになると、両方が同時に起動して同じ migration を流そうとする。 advisory lock で直列化する。

func (*Store) Schema

func (s *Store) Schema() string

Schema returns the PostgreSQL schema name.

Jump to

Keyboard shortcuts

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