window

package
v1.2.2 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 12 Imported by: 0

README

window

Package window stores the last N event values for an entity and computes exact client-side aggregations over that bounded list. It is useful for features such as "average amount over the last 10 events" where event count, not wall-clock time, defines the window.

A *client.Client can be passed directly to Execute, Read, and Delete. The package stores records in set window and uses a single list bin internally. WindowSize must be between 1 and MaxWindowSize (100).

Strengths

  • The helper is intentionally small: Execute and Read need only Operate, and Delete needs only Delete, so tests can use narrow mocks.
  • Storage is easy to reason about. Each entity scope maps to one deterministic key in set window, derived from Name, Ref, the source value for Ref, and GroupBy values.
  • GroupBy order does not affect the key, which helps when callers construct equivalent requests from maps or configuration.
  • Aggregations are exact over the retained values. There are no HLL or TDigest sketches in this helper; percentile calculation sorts the retained values and uses linear interpolation.
  • MaxWindowSize bounds each list to at most 100 retained values, keeping read, decode, and aggregation work predictable for last-N features.

Weaknesses / Tradeoffs

  • This is a count-based last-N window, not a time-range query. Event timestamps are stored with entries, but reads aggregate by list contents and trimming removes the oldest appended entries, not entries older than a timestamp.
  • TTL applies to the whole window record and is refreshed by writes. It does not expire individual entries inside the list.
  • Every read decodes the retained list and computes aggregations client-side. That is exact and simple, but it is intentionally capped at MaxWindowSize rather than designed for large windows.
  • The window result implements count, sum, min, max, average, sample standard deviation, and percentile. Other queries.Field flags, such as distinct, geometric mean, and circular mean, are not returned by this helper.
  • List uniqueness applies to the full serialized entry [EventID, value, timestamp]. Replays need the same value and event timestamp to serialize identically; EventID is stored but not validated as a separate uniqueness key.
  • Missing or non-numeric Value fields read as 0 with MapSource.

Request

Important request fields:

  • Name: variable name used in key derivation.
  • Namespace: FrogoDB namespace.
  • Ref: source key for the reference entity, such as a user ID.
  • GroupBy: optional source keys that further scope the entity.
  • Value: source key for the numeric value appended to the window.
  • WindowSize: number of recent events to keep, from 1 through 100.
  • Fields: aggregation flags from package queries.
  • PercentileP: percentile for FieldPercentile, expressed from 0 to 1.
  • EventID: current event ID stored with each appended entry.
  • TTL: required positive expiration duration.
  • IncludeCurrent: when true, write before reading; when false, read before writing.

Ref, Value, WindowSize, and TTL are validated. The deterministic key is derived from Name, Ref, the source value for Ref, and GroupBy values. GroupBy order does not affect the key.

Example

func updateWindow(ctx context.Context) error {
    c, err := client.New("127.0.0.1:3000")
    if err != nil {
        return err
    }
    defer c.Close()

    src := queries.NewMapSource(map[string]any{
        "event_id":         "evt-123",
        "standard.user_id": "user-42",
        "amount":           42.5,
        "event_time":       time.Now(),
    })

    req := window.Request{
        Name:           "user_last_10_amounts",
        Namespace:      "scoring",
        Ref:            "standard.user_id",
        Value:          "amount",
        WindowSize:     10,
        Fields:         queries.FieldCount | queries.FieldAvg | queries.FieldSTD | queries.FieldPercentile,
        PercentileP:    0.90,
        EventID:        src.String("event_id"),
        TTL:            24 * time.Hour,
        IncludeCurrent: true,
    }

    result, err := window.Execute(ctx, c, req, src)
    if err != nil {
        return err
    }

    _ = result.Count
    _ = result.Avg
    _ = result.Percentile
    return nil
}

Use Read to compute the current window without appending the event:

result, err := window.Read(ctx, c, req, src)

Use Delete to remove the stored window for the same request and source scope:

err := window.Delete(ctx, c, req, src)

Behavior

Execute writes and reads in the order selected by IncludeCurrent.

  • IncludeCurrent: true: append the current event, trim excess entries, then read and aggregate the updated list.
  • IncludeCurrent: false: read and aggregate existing entries, then append the current event.

Writes append entries with EventID, numeric value, and event timestamp. The append uses the client's unique/no-fail list flags for exact serialized entry matches. When the list grows past WindowSize, the oldest entries are removed from the beginning.

Result includes Count, Sum, Min, Max, Avg, STD, Percentile, and Values. Window math is exact over the retained values. Percentiles use linear interpolation and clamp PercentileP to the 0 to 1 range.

Event timestamps come from queries.EventTime(src), so event_time may be a time.Time, int64 Unix seconds, or int Unix seconds. If omitted, the helper uses time.Now().

Documentation

Index

Constants

View Source
const MaxWindowSize = 100

MaxWindowSize is the upper bound for WindowSize.

View Source
const SetWindow = "window"

SetWindow is the set name for window storage.

Variables

This section is empty.

Functions

func Delete

func Delete(ctx context.Context, c deleteClient, req Request, src queries.Source) error

Delete removes the stored window data for the given entity. The key is deterministic from (Name, Ref, source values, GroupBy).

Types

type Request

type Request struct {
	Name           string        // variable name
	Namespace      string        // FrogoDB namespace
	Ref            string        // source key for entity reference
	GroupBy        []string      // grouping fields
	Value          string        // source key for numeric value
	WindowSize     int           // last N events (max 100)
	Fields         queries.Field // which functions to compute
	PercentileP    float64       // for percentile (0-1)
	EventID        string        // current event ID (for dedup)
	TTL            time.Duration // REQUIRED. Expiration for window records.
	IncludeCurrent bool
}

Request describes a sliding window aggregation query.

func (Request) Validate

func (r Request) Validate() error

Validate checks that required fields are set.

type Result

type Result struct {
	Count      int64
	Sum        float64
	Min        float64
	Max        float64
	Avg        float64
	STD        float64
	Percentile float64
	Values     []float64 // the raw window values (for debugging)
}

Result holds the outcome of a sliding window aggregation.

func Execute

func Execute(ctx context.Context, c operateClient, req Request, src queries.Source) (Result, error)

Execute writes the current event value and reads the window aggregation. The order of write vs read is controlled by IncludeCurrent.

func Read

func Read(ctx context.Context, c operateClient, req Request, src queries.Source) (Result, error)

Read performs a read-only window query without writing the current event.

Jump to

Keyboard shortcuts

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