Documentation
¶
Overview ¶
Package computed materializes read-only computed attributes. A computed attribute's value is derived (a formula over the entity's other values) and stored like any value by an event subscriber, so it is queryable in FQL with no special-casing. Writing one through the values API is rejected; only this materializer (an internal write) sets it.
The subscriber recomputes on any value change to the entity and converges: re-setting an unchanged computed value emits no event, so the recompute loop terminates.
A schema change to a computed attribute also rebuilds the affected type's entities, off the request goroutine, so a corrected formula converges without waiting for each entity to be written again.
Rollup aggregates over relationships are NOT implemented, and a rollup definition is refused at create/update rather than accepted — see domain/attribute/computed.go. An accepted rollup would have produced an attribute that the schema advertises and that never holds a value.
Index ¶
- func EventTypes() []events.Type
- type Materializer
- func (m *Materializer) Handle(ctx context.Context, env events.Envelope) error
- func (m *Materializer) HandleBatch(ctx context.Context, envs []events.Envelope) error
- func (m *Materializer) Name() string
- func (m *Materializer) OnFormulaError(fn func(err error))
- func (m *Materializer) OnSchemaChange(fn func(tenant valueobjects.TenantID, typeID string))
- func (m *Materializer) Recompute(ctx context.Context, typeID, entityID string) error
- func (m *Materializer) RecomputeTenant(ctx context.Context, tenant valueobjects.TenantID) (int, error)
- func (m *Materializer) RecomputeType(ctx context.Context, tenant valueobjects.TenantID, typeID string) (int, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EventTypes ¶
EventTypes lists the events the materializer subscribes to: value changes drive a recompute, and definition changes invalidate the per-type "has computed attributes" cache (a formula attribute added to or removed from a type — or any of its ancestors — changes whether its entities need recomputing).
Types ¶
type Materializer ¶
type Materializer struct {
// contains filtered or unexported fields
}
Materializer recomputes an entity's computed attributes when its values change, writing the results as (internal) values.
func NewMaterializer ¶
func NewMaterializer(factory application.Factory) *Materializer
NewMaterializer builds the computed-attribute subscriber.
func (*Materializer) Handle ¶
Handle implements events.Handler. A definition event invalidates the cache; a value event recomputes the one entity it names.
func (*Materializer) HandleBatch ¶ added in v1.1.0
HandleBatch implements events.BatchHandler. It coalesces one commit's value events per (tenant, type, entity) so each touched entity is recomputed once, not once per value event: a row that sets ten attributes emits ten events but needs a single recompute. A definition event anywhere in the batch flushes the cache first, so a recompute later in the same commit sees the fresh schema.
func (*Materializer) OnFormulaError ¶ added in v1.3.0
func (m *Materializer) OnFormulaError(fn func(err error))
OnFormulaError registers the callback invoked when a stored formula cannot be parsed. The facade wires it to the background-error observer.
func (*Materializer) OnSchemaChange ¶ added in v1.3.0
func (m *Materializer) OnSchemaChange(fn func(tenant valueobjects.TenantID, typeID string))
OnSchemaChange registers the callback invoked when a schema change may have invalidated materialized values. It is not safe to call once the materializer is dispatching; wire it during composition.
func (*Materializer) Recompute ¶
func (m *Materializer) Recompute(ctx context.Context, typeID, entityID string) error
Recompute evaluates every computed formula attribute of the entity's type and materializes the results. Missing inputs (or division by zero) remove a stale computed value rather than writing a wrong one.
func (*Materializer) RecomputeTenant ¶ added in v1.1.0
func (m *Materializer) RecomputeTenant(ctx context.Context, tenant valueobjects.TenantID) (int, error)
RecomputeTenant re-materializes every entity's computed attributes for a tenant — the recovery counterpart to the search index's Reindex. Internal projections are maintained in the originating request's post-commit (issue #211), so read-your-writes holds regardless of the outbox setting; the trade-off is that a process crash between commit and that post-commit can leave a computed value stale. Running this rebuilds them all. It pages types and their entities, skipping types with no computed attributes, and reuses the per-entity Recompute (each in its own unit of work). Pagination stays correct even though Recompute bumps an entity's last_updated_at: each page's cursor is taken from the values read before that page was recomputed, so a recomputed entity moves ahead of the cursor and is never revisited.
func (*Materializer) RecomputeType ¶ added in v1.3.0
func (m *Materializer) RecomputeType(ctx context.Context, tenant valueobjects.TenantID, typeID string) (int, error)
RecomputeType rebuilds every entity of one type, and of its subtypes, since an inherited computed attribute belongs to those too. It returns the number of entities recomputed.