firestore

package
v0.5.6 Latest Latest
Warning

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

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

Documentation

Overview

Package firestore opens the application's Firestore client from configuration and keeps it as process state every operation reaches through Handle.

Importing it registers the [middleware.firestore] binding, so a project that does not use Firestore gains no configuration key and links no driver:

import _ "github.com/shibukawa/popcornweb/database/firestore"

The database must have been created in Datastore mode, which is chosen at creation and cannot be changed. Startup checks it, because a native-mode database answers this API with the same status a missing composite index produces and the two would otherwise be indistinguishable.

It wraps no operation. A handler calls tinybind's firestorebind directly, handing it the process handle. A generated .pw.firestore query resolves the same handle itself, so its call sites stay context-only:

h, err := firestore.Handle(ctx)
reading, err := h.Load[Reading](ctx, datastore.NameKey("Reading", id))

The client is a deployment fact fixed for a process, so nothing is installed into request contexts: no context.Value stands between a call site and the client.

A kind belongs to the type rather than to the deployment, so nothing here maps a name. The namespace is the one isolation dimension, and it is a client option set once.

Index

Constants

View Source
const (
	// CredentialsServiceAccount signs a JWT with a service account key. It is
	// the default, and it needs no token endpoint round trip.
	CredentialsServiceAccount = "service_account"
	// CredentialsMetadata reads a token from the instance metadata server,
	// which is what Cloud Run, GKE and GCE have. It links no RSA code.
	CredentialsMetadata = "metadata"
	// CredentialsOAuth2 exchanges the key for an access token at the token
	// endpoint, for a deployment that requires a real one.
	CredentialsOAuth2 = "oauth2"
	// CredentialsStatic uses a token the process supplies through
	// SetTokenSource. It reads no key file.
	CredentialsStatic = "static"
)

Credential sources. The driver resolves GOOGLE_APPLICATION_CREDENTIALS and nothing else, so which source a deployment has is configured rather than discovered: probing the metadata server to find out would cost a round trip on every process that is not on Google Cloud, and would silently change the credential when a probe timed out.

Variables

This section is empty.

Functions

func Client

func Client(ctx context.Context) (*datastore.Client, error)

Client returns the process client, for an operation firestorebind does not wrap.

Reach for this only when calling the driver directly, and pass keys through the handle's KeyFor when you do — the client applies no namespace of its own. Everything firestorebind wraps takes the whole Handle instead.

func EnsureClient

func EnsureClient(ctx context.Context) (context.Context, bool)

EnsureClient returns a context on which firestorebind's context-form entries resolve the process client, reporting false when none can be reached.

A pw call site does not need it: Handle reads the process state directly, so neither a request context nor a setup context carries a client node. It remains for code handing a context to something that still calls the context-form firestorebind entries. A context that already carries a client is returned unchanged.

func Handle

func Handle(ctx context.Context) (firestorebind.Handle, error)

Handle returns the Datastore client bound to the tenancy of this deployment, which is what the "On"-suffixed firestorebind entries take and what every generated .pw.firestore query resolves through.

The client is a deployment fact fixed for a process, so the common path reads process state and walks no context chain. When the process holds no client — a unit test building its own context, or a tool running without this extension — a handle installed with firestorebind.WithClient or WithHandle is honoured instead.

func Ready

func Ready(ctx context.Context) error

Ready reports whether the store answers, for a readiness probe.

It is the same reserved-key lookup startup makes, because there is no table listing and no ping on this API: a probe has to be an ordinary read. That costs one small read per call, which is worth knowing when setting the interval.

func RegisterKind

func RegisterKind(record firestorebind.Kinder)

RegisterKind records a framework-owned kind from the package that writes it.

The value is the store's own record type. Its Kind method names the kind, and its ExpiryProperty method, when it has one, names the property a TTL policy expires on — so the published list is derived from the same declaration the codec reads rather than maintained beside it. A property renamed in one place and not the other is the drift this exists to prevent.

Registering twice for one kind keeps the first entry, since re-initialization in tests re-runs the same registrations.

func SetTokenSource

func SetTokenSource(source google.TokenSource)

SetTokenSource installs the bearer tokens a static credential uses.

It exists for a deployment whose token comes from a companion service rather than from a key file or the metadata server, and for a test that wants a client without one. Call it before the application starts.

Types

type Config

type Config struct {
	// Enabled opens the client and installs the middleware.
	Enabled bool `toml:"enabled" help:"Enabled opens the client and installs the middleware"`
	// ProjectID names the Google Cloud project. Empty falls back to
	// GOOGLE_CLOUD_PROJECT and then DATASTORE_PROJECT_ID, and a project
	// resolvable from none of them is a startup error.
	ProjectID string `` /* 137-byte string literal not displayed */
	// Database names a non-default database in that project. Empty selects the
	// project's default database.
	Database string `toml:"database" help:"Database names a non-default database in that project. Empty selects the project's default database"`
	// Namespace scopes every key this process writes and reads. It is the one
	// isolation dimension here: a kind belongs to the type, so there is no
	// prefix or name mapping to configure.
	Namespace string `toml:"namespace" help:"Namespace scopes every key this process writes and reads"`
	// Endpoint overrides the Datastore host, which is how the emulator is
	// reached. Empty falls back to DATASTORE_EMULATOR_HOST and then the
	// service. A value with no scheme is taken as http.
	Endpoint string `toml:"endpoint" help:"Endpoint overrides the Datastore host, which is how the emulator is reached"`
	// Credentials names the token source: service_account, metadata, oauth2 or
	// static.
	Credentials string `toml:"credentials" default:"service_account" help:"token source: service_account, metadata, oauth2 or static"`
	// CredentialsFile is the service account key. Empty falls back to
	// GOOGLE_APPLICATION_CREDENTIALS. Only the two signing sources read it.
	CredentialsFile string `toml:"credentials_file" help:"CredentialsFile is the service account key. Empty falls back to GOOGLE_APPLICATION_CREDENTIALS"`
	// Timeout bounds one request.
	Timeout time.Duration `toml:"timeout" default:"10s" help:"Timeout bounds one request"`
	// MaxIdleConns sizes the connection pool. The rule of thumb is the
	// expected concurrency.
	MaxIdleConns int `` /* 126-byte string literal not displayed */
}

Config is the [middleware.firestore] runtime binding. It is registered when this package is imported, so a project that does not use Firestore gains no key.

The database it names must have been created in Datastore mode. That is chosen when the database is created and cannot be changed afterwards, so startup checks it rather than letting a native-mode database answer the first request with a precondition failure.

It carries no schema keys. Nothing creates a kind and nothing reports one, so a verify_schema or auto_migrate key here would configure nothing.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig is the binding's zero-value replacement, and the same values the default struct tags carry.

Both exist because they answer different questions: configbind reads the tags to fill an unset key, and a caller building a Config in Go reads this.

type KindInfo

type KindInfo struct {
	// Kind is the entity kind, which is the declared name unchanged.
	Kind string
	// ExpiryProperty is the timestamp property a TTL policy expires on. It is
	// empty for a kind whose records do not expire.
	ExpiryProperty string
}

KindInfo is one framework-owned kind and, when its records expire, the property a TTL policy has to be pointed at.

A deployment needs both. Nothing creates a kind, so there is no schema to print; what deployment tooling still has to be told is which kinds exist and which property expires, and only the linked code knows that.

func Kinds

func Kinds() []KindInfo

Kinds reports the framework-owned kinds this binary links, sorted by kind so the output of a tool that prints them is stable.

It is read by documentation and by deployment tooling, and by nothing on the request path: no code looks a kind up here, because a kind is intrinsic to the type that owns it.

Jump to

Keyboard shortcuts

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