Documentation
¶
Overview ¶
Package localization owns translation bundles: one JSON document per microservice, environment and locale, published to the LOCALIZATION KV bucket at key "{envID}.{microserviceID}.{locale}".
The locale is validated rather than taken as given, because it is a key component — a locale carrying a dot would produce a key no consumer can parse back into its three parts. Bundle size is checked against the KV value limit before the database write, so an oversized bundle is refused outright instead of being committed as a row that can never reach a consumer.
Index ¶
- Variables
- type Filter
- type Handler
- func (h *Handler) CreateLocalization(w http.ResponseWriter, r *http.Request)
- func (h *Handler) DeleteLocalization(w http.ResponseWriter, r *http.Request)
- func (h *Handler) GetLocalization(w http.ResponseWriter, r *http.Request)
- func (h *Handler) GetLocalizationByID(w http.ResponseWriter, r *http.Request)
- func (h *Handler) ListLocalizations(w http.ResponseWriter, r *http.Request)
- func (h *Handler) UpdateLocalization(w http.ResponseWriter, r *http.Request)
- type Localization
- type Page
- type PostgresRepository
- func (r *PostgresRepository) CreateLocalization(ctx context.Context, input Localization) (*Localization, error)
- func (r *PostgresRepository) DeleteLocalization(ctx context.Context, id int64) (*Localization, error)
- func (r *PostgresRepository) GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
- func (r *PostgresRepository) GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
- func (r *PostgresRepository) ListAllForReconcile(ctx context.Context, since time.Time) ([]Localization, error)
- func (r *PostgresRepository) ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
- func (r *PostgresRepository) UpdateLocalization(ctx context.Context, input Localization) (*Localization, error)
- type Repository
- type SQLiteRepository
- func (r *SQLiteRepository) CreateLocalization(ctx context.Context, input Localization) (*Localization, error)
- func (r *SQLiteRepository) DeleteLocalization(ctx context.Context, id int64) (*Localization, error)
- func (r *SQLiteRepository) GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
- func (r *SQLiteRepository) GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
- func (r *SQLiteRepository) ListAllForReconcile(ctx context.Context, since time.Time) ([]Localization, error)
- func (r *SQLiteRepository) ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
- func (r *SQLiteRepository) UpdateLocalization(ctx context.Context, input Localization) (*Localization, error)
- type Service
- func (s *Service) CreateLocalization(ctx context.Context, req Localization) (*Localization, error)
- func (s *Service) DeleteLocalization(ctx context.Context, id int64) error
- func (s *Service) GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
- func (s *Service) GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
- func (s *Service) ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
- func (s *Service) UpdateLocalization(ctx context.Context, req Localization) (*Localization, error)
Constants ¶
This section is empty.
Variables ¶
var ErrBundleTooLarge = errors.New("bundle json exceeds the maximum value size")
ErrBundleTooLarge rejects a bundle bigger than a KV value may be. Accepting it would return a 201 for a row that can never be published, so the write would look successful while consumers never saw it.
var ErrConflict = errors.New("localization was modified by someone else")
ErrConflict is returned when an update carried an expected UPDATED_AT that no longer matches the stored row: somebody else edited it first. Distinct so a handler can map it to HTTP 409.
var ErrEnvironmentNotFound = errors.New("environment not found")
var ErrInvalidBundleJSON = errors.New("invalid bundle json")
var ErrInvalidEnvironmentID = errors.New("invalid environment id")
var ErrInvalidLocale = errors.New("invalid locale")
var ErrInvalidLocalizationID = errors.New("invalid localization id")
var ErrInvalidMicroserviceID = errors.New("invalid microservice id")
var ErrLocalizationExists = errors.New("localization for this microservice, environment and locale already exists")
ErrLocalizationExists collides with the natural unique key (MICROSERVICE_ID, ENVIRONMENT_ID, LOCALE). Distinct so a handler can map it to HTTP 409.
var ErrLocalizationNotFound = errors.New("localization not found")
var ErrMicroserviceNotFound = errors.New("microservice not found")
Referential integrity is checked before the insert so a missing parent row surfaces as a 404 instead of an opaque foreign-key failure.
Functions ¶
This section is empty.
Types ¶
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
func NewHandler ¶
func (*Handler) CreateLocalization ¶
func (h *Handler) CreateLocalization(w http.ResponseWriter, r *http.Request)
POST /localization
func (*Handler) DeleteLocalization ¶
func (h *Handler) DeleteLocalization(w http.ResponseWriter, r *http.Request)
DELETE /localization/{id}
func (*Handler) GetLocalization ¶
func (h *Handler) GetLocalization(w http.ResponseWriter, r *http.Request)
GET /localization/lookup/{msId}/{envId}/{locale}
func (*Handler) GetLocalizationByID ¶
func (h *Handler) GetLocalizationByID(w http.ResponseWriter, r *http.Request)
GET /localization/{id}
func (*Handler) ListLocalizations ¶
func (h *Handler) ListLocalizations(w http.ResponseWriter, r *http.Request)
GET /localization?microserviceId=&environmentId=&locale=&limit=&offset=
func (*Handler) UpdateLocalization ¶
func (h *Handler) UpdateLocalization(w http.ResponseWriter, r *http.Request)
PUT /localization/values
type Localization ¶
type Localization struct {
ID int64 `json:"id"`
MicroserviceID int64 `json:"microserviceId"`
EnvironmentID int64 `json:"environmentId"`
Locale string `json:"locale"` // e.g. "pt-BR", "en-US"
BundleJSON json.RawMessage `json:"bundleJson"`
UpdatedAt time.Time `json:"updatedAt"`
// ExpectedUpdatedAt opts an update into optimistic concurrency: the write
// only applies while the stored row still carries this timestamp, so two
// admins editing the same bundle no longer silently overwrite each other.
// Absent (nil) keeps the original last-write-wins behaviour.
ExpectedUpdatedAt *time.Time `json:"expectedUpdatedAt,omitempty"`
}
Localization is one translation bundle for a (microservice, environment, locale) tuple. The whole locale is stored as a single JSON bundle so apps load a locale atomically and KV holds one entry per locale.
type Page ¶
Page bounds a list query. The service normalises it, so a repository can bind both values as given.
type PostgresRepository ¶
type PostgresRepository struct {
// contains filtered or unexported fields
}
func NewPostgresRepository ¶
func NewPostgresRepository(db *sql.DB) *PostgresRepository
func (*PostgresRepository) CreateLocalization ¶
func (r *PostgresRepository) CreateLocalization(ctx context.Context, input Localization) (*Localization, error)
func (*PostgresRepository) DeleteLocalization ¶
func (r *PostgresRepository) DeleteLocalization(ctx context.Context, id int64) (*Localization, error)
func (*PostgresRepository) GetLocalization ¶
func (r *PostgresRepository) GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
func (*PostgresRepository) GetLocalizationByID ¶
func (r *PostgresRepository) GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
func (*PostgresRepository) ListAllForReconcile ¶
func (r *PostgresRepository) ListAllForReconcile(ctx context.Context, since time.Time) ([]Localization, error)
ListAllForReconcile returns localization bundles to republish to KV. A zero `since` sweeps every row; otherwise only rows changed at or after `since`.
func (*PostgresRepository) ListLocalizations ¶
func (r *PostgresRepository) ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
func (*PostgresRepository) UpdateLocalization ¶
func (r *PostgresRepository) UpdateLocalization(ctx context.Context, input Localization) (*Localization, error)
type Repository ¶
type Repository interface {
GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
UpdateLocalization(ctx context.Context, input Localization) (*Localization, error)
ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
CreateLocalization(ctx context.Context, input Localization) (*Localization, error)
// DeleteLocalization returns the row it removed, so the caller can derive
// the KV key it has to purge.
DeleteLocalization(ctx context.Context, id int64) (*Localization, error)
}
type SQLiteRepository ¶
type SQLiteRepository struct {
// contains filtered or unexported fields
}
SQLiteRepository backs the local test stack (see internal/database/sqlite.go). Same tables and columns as PostgreSQL; only the bind syntax differs (? vs $1).
func NewSQLiteRepository ¶
func NewSQLiteRepository(db *sql.DB) *SQLiteRepository
func (*SQLiteRepository) CreateLocalization ¶
func (r *SQLiteRepository) CreateLocalization(ctx context.Context, input Localization) (*Localization, error)
func (*SQLiteRepository) DeleteLocalization ¶
func (r *SQLiteRepository) DeleteLocalization(ctx context.Context, id int64) (*Localization, error)
func (*SQLiteRepository) GetLocalization ¶
func (r *SQLiteRepository) GetLocalization(ctx context.Context, microserviceID, environmentID int64, locale string) (*Localization, error)
func (*SQLiteRepository) GetLocalizationByID ¶
func (r *SQLiteRepository) GetLocalizationByID(ctx context.Context, id int64) (*Localization, error)
func (*SQLiteRepository) ListAllForReconcile ¶
func (r *SQLiteRepository) ListAllForReconcile(ctx context.Context, since time.Time) ([]Localization, error)
func (*SQLiteRepository) ListLocalizations ¶
func (r *SQLiteRepository) ListLocalizations(ctx context.Context, filter Filter) ([]Localization, error)
func (*SQLiteRepository) UpdateLocalization ¶
func (r *SQLiteRepository) UpdateLocalization(ctx context.Context, input Localization) (*Localization, error)
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func NewService(repo Repository, pub messaging.ConfigPublisher) *Service
func (*Service) CreateLocalization ¶
func (s *Service) CreateLocalization(ctx context.Context, req Localization) (*Localization, error)
func (*Service) DeleteLocalization ¶
DeleteLocalization removes the row and the KV key it fed. Waiting for the next full reconcile to prune the key would leave consumers serving a deleted locale for up to a whole interval.
func (*Service) GetLocalization ¶
func (*Service) GetLocalizationByID ¶
func (*Service) ListLocalizations ¶
func (*Service) UpdateLocalization ¶
func (s *Service) UpdateLocalization(ctx context.Context, req Localization) (*Localization, error)