typed

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package typed provides typed wrappers around the generic Murmur QueryService — the building block for application services that want to expose typed protos to their callers rather than the generic Value{bytes} shape.

Why this exists

Murmur's `pkg/query/grpc.QueryService` returns `Value{present, data}` where `data` is the wire-encoded monoid value (int64-LE for Sum/Count/Min/Max, marshaled HLL/TopK/Bloom for sketches). Clients decode the bytes per the pipeline's monoid kind. This is right for Murmur — it keeps the service monoid-agnostic — but it pushes decoding boilerplate to every caller.

The typed-wrapper pattern: an application service exposes its OWN Connect-RPC API with typed responses (e.g. count-core's `BotInteractionCountService.GetBotInteractionCount(...) → int64`). The implementation calls the underlying Murmur QueryService, decodes the bytes via this package, and returns the typed shape. Callers see typed protos; Murmur stays generic.

This package ships the decoders + thin typed-client wrappers for the shipped monoid kinds: Sum/Count/Min/Max (int64), HLL, TopK, Bloom. Full per-pipeline codegen — generating a typed `*ServerStub` per pipeline — is Phase 2 roadmap; this package is the building block it would generate against.

Usage

Wrap a generic Murmur QueryService client once:

rawClient := murmurv1connect.NewQueryServiceClient(httpClient, baseURL)
likes := typed.NewSumClient(rawClient)

// Now: typed Get / GetMany / GetWindow.
count, present, err := likes.Get(ctx, "post-123")
counts, err := likes.GetMany(ctx, []string{"post-123", "post-456"})
last24h, err := likes.GetWindow(ctx, "post-123", 24*time.Hour)

Build your own Connect-RPC service against the typed client:

type CountCoreServer struct {
    likes  *typed.SumClient
    unique *typed.HLLClient
}
func (s *CountCoreServer) GetBotInteractionCount(ctx, req) (resp, error) {
    n, ok, err := s.likes.Get(ctx, req.GetEntity())
    if err != nil { return nil, connect.NewError(...) }
    return &countpb.GetBotInteractionCountResponse{
        Count: n,
        Present: ok,
    }, nil
}

The application's Connect-RPC service is whatever proto shape it wants; the typed client hides the bytes-decoding from it.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupported = errors.New("typed client: operation not supported by underlying pipeline")

ErrUnsupported is returned by adapters that don't implement an optional method (e.g., calling GetWindow on a SumClient that only wraps a non-windowed pipeline). Wrapped via fmt.Errorf at the call site.

Functions

func DecodeInt64

func DecodeInt64(data []byte) int64

DecodeInt64 decodes an 8-byte little-endian int64. Mirrors the `mgrpc.Int64LE` encoder used server-side. Returns 0 for short inputs.

Types

type BloomClient

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

BloomClient is the typed wrapper for Bloom-filter pipelines.

func NewBloomClient

func NewBloomClient(inner Inner) *BloomClient

NewBloomClient wraps the generic QueryService client with Bloom approximate-size responses.

func (*BloomClient) Get

func (c *BloomClient) Get(ctx context.Context, entity string, opts ...Option) (BloomValue, bool, error)

Get returns the Bloom filter's shape for the entity's all-time sketch.

func (*BloomClient) GetMany added in v0.2.0

func (c *BloomClient) GetMany(ctx context.Context, entities []string, opts ...Option) ([]BloomValue, []bool, error)

GetMany batches Get for many entities (all-time, non-windowed). Order matches input order; missing entities yield a zero-valued BloomValue with the corresponding bool false in the present slice.

func (*BloomClient) GetRange added in v0.2.0

func (c *BloomClient) GetRange(ctx context.Context, entity string, start, end time.Time, opts ...Option) (BloomValue, error)

GetRange returns the merged Bloom-filter shape over the absolute time range [start, end] for the given entity. Pipeline must be windowed. CapacityBits and HashFunctions reflect the per-bucket filter shape (stable filter-construction constants); ApproxSize is the union over the buckets in range.

func (*BloomClient) GetWindow

func (c *BloomClient) GetWindow(ctx context.Context, entity string, duration time.Duration, opts ...Option) (BloomValue, error)

GetWindow returns the merged Bloom-filter shape over the most-recent `duration`. The merged sketch's capacity / hash count match the per-bucket sketches' shape; ApproxSize reflects the union over the window's buckets.

func (*BloomClient) GetWindowMany

func (c *BloomClient) GetWindowMany(ctx context.Context, entities []string, duration time.Duration, opts ...Option) ([]BloomValue, error)

GetWindowMany is the batched analog of GetWindow — fetches the merged Bloom-filter shape for N entities in one round-trip. Returns parallel arrays: out[i] is the BloomValue for entities[i]; missing entities yield a zero-valued BloomValue.

type BloomValue

type BloomValue struct {
	CapacityBits  uint64
	HashFunctions uint32
	ApproxSize    uint64
}

BloomValue carries the Bloom filter's shape — capacity (bits), the number of hash functions, and the approximate set size derived from the populated bit count.

type HLLClient

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

HLLClient is the typed wrapper for HLL pipelines whose state is the axiomhq/hyperloglog byte format. Returns cardinality estimates rather than raw sketch bytes.

func NewHLLClient

func NewHLLClient(inner Inner) *HLLClient

NewHLLClient wraps the generic QueryService client with HLL cardinality-estimate responses.

func (*HLLClient) Get

func (c *HLLClient) Get(ctx context.Context, entity string, opts ...Option) (HLLValue, bool, error)

Get returns the cardinality estimate for the entity's all-time sketch.

func (*HLLClient) GetMany added in v0.2.0

func (c *HLLClient) GetMany(ctx context.Context, entities []string, opts ...Option) ([]HLLValue, []bool, error)

GetMany batches Get for many entities (all-time, non-windowed). Order matches input order; missing entities return a zero-valued HLLValue plus the corresponding bool false in the present slice. Use this when you need to distinguish "absent" from "present-and-empty" — GetWindowMany cannot, since the underlying generic RPC returns the merged value without a per-entity present flag.

func (*HLLClient) GetRange added in v0.2.0

func (c *HLLClient) GetRange(ctx context.Context, entity string, start, end time.Time, opts ...Option) (HLLValue, error)

GetRange returns the cardinality estimate over the absolute time range [start, end] for the given entity. Pipeline must be windowed. The server merges the buckets falling in range via HLL union before the estimate is taken, so the result is the merged cardinality, not the sum of per-bucket cardinalities.

func (*HLLClient) GetWindow

func (c *HLLClient) GetWindow(ctx context.Context, entity string, duration time.Duration, opts ...Option) (HLLValue, error)

GetWindow returns the cardinality estimate over the most-recent `duration`.

func (*HLLClient) GetWindowMany

func (c *HLLClient) GetWindowMany(ctx context.Context, entities []string, duration time.Duration, opts ...Option) ([]HLLValue, error)

GetWindowMany is the batched analog of GetWindow — fetches windowed cardinalities for N entities in one round-trip. Returns parallel arrays: out[i] is the cardinality estimate for entities[i]; missing entities yield a zero-valued HLLValue.

type HLLValue

type HLLValue struct {
	Cardinality uint64
	ByteLen     int
}

HLLValue carries the estimated cardinality plus the byte length of the underlying sketch (useful for cluster-wide capacity tracking).

type Inner

Inner is the underlying Connect-RPC client shape this package wraps. Production: the generated `murmurv1connect.QueryServiceClient`. Tests: a fake satisfying the same shape.

type Option

type Option func(*queryOptions)

Option configures a typed Get / GetMany / GetWindow / GetRange call.

func WithFreshRead

func WithFreshRead() Option

WithFreshRead sets the underlying request's fresh_read flag, bypassing server-side singleflight + cache layers. Used for read-your-writes flows.

type SumClient

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

SumClient is the typed wrapper for Sum / Count / Min / Max pipelines whose state is `int64` and whose wire shape is 8-byte little-endian. The same client works against any of those four monoid kinds — they all encode int64 the same way.

func NewSumClient

func NewSumClient(inner Inner) *SumClient

NewSumClient wraps the generic QueryService client with typed int64 responses. Use for any pipeline whose monoid is Sum / Count / Min / Max.

func (*SumClient) Get

func (c *SumClient) Get(ctx context.Context, entity string, opts ...Option) (int64, bool, error)

Get returns the all-time aggregation value for entity. The bool reports whether the entity exists in the store; missing entities return (0, false, nil). Use this for non-windowed pipelines.

func (*SumClient) GetMany

func (c *SumClient) GetMany(ctx context.Context, entities []string, opts ...Option) ([]int64, []bool, error)

GetMany batches Get for many entities. Order matches input order; missing entities return 0 in the value slice with the corresponding bool false in the present slice.

func (*SumClient) GetRange

func (c *SumClient) GetRange(ctx context.Context, entity string, start, end time.Time, opts ...Option) (int64, error)

GetRange returns the merged value over the absolute time range [start, end] for the given entity. Pipeline must be windowed.

func (*SumClient) GetWindow

func (c *SumClient) GetWindow(ctx context.Context, entity string, duration time.Duration, opts ...Option) (int64, error)

GetWindow returns the merged value over the most-recent `duration` for the given entity. Pipeline must be windowed.

func (*SumClient) GetWindowMany

func (c *SumClient) GetWindowMany(ctx context.Context, entities []string, duration time.Duration, opts ...Option) ([]int64, error)

GetWindowMany is the batched analog of GetWindow — fetches windowed values for N entities in one round-trip.

type TopKClient

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

TopKClient is the typed wrapper for Misra-Gries Top-K pipelines. Returns ranked items rather than raw sketch bytes.

func NewTopKClient

func NewTopKClient(inner Inner) *TopKClient

NewTopKClient wraps the generic QueryService client with TopK item-list responses.

func (*TopKClient) Get

func (c *TopKClient) Get(ctx context.Context, entity string, opts ...Option) ([]TopKItem, bool, error)

Get returns the ranked top-K items for the entity's all-time sketch. Items are ordered by descending count.

func (*TopKClient) GetMany added in v0.2.0

func (c *TopKClient) GetMany(ctx context.Context, entities []string, opts ...Option) ([][]TopKItem, []bool, error)

GetMany batches Get for many entities (all-time, non-windowed). Order matches input order; missing entities return a nil slice plus the corresponding bool false in the present slice.

func (*TopKClient) GetRange added in v0.2.0

func (c *TopKClient) GetRange(ctx context.Context, entity string, start, end time.Time, opts ...Option) ([]TopKItem, error)

GetRange returns the ranked top-K items over the absolute time range [start, end] for the given entity. Pipeline must be windowed. The server merges per-bucket Misra-Gries summaries before returning, so the ranking reflects merged-summary order — not a simple union of per-bucket rankings.

func (*TopKClient) GetWindow

func (c *TopKClient) GetWindow(ctx context.Context, entity string, duration time.Duration, opts ...Option) ([]TopKItem, error)

GetWindow returns the ranked top-K items over the most-recent `duration`.

func (*TopKClient) GetWindowMany

func (c *TopKClient) GetWindowMany(ctx context.Context, entities []string, duration time.Duration, opts ...Option) ([][]TopKItem, error)

GetWindowMany is the batched analog of GetWindow — fetches windowed ranked-item lists for N entities in one round-trip. Returns parallel arrays: out[i] is the ranked items for entities[i]; missing entities yield a nil slice.

type TopKItem

type TopKItem struct {
	Key string
	// Count is a Misra-Gries LOWER BOUND, not a count. It understates the true
	// count by up to n/(K+1), where n is the total weight the sketch ingested —
	// and n is not visible from this item list. A sketch that retained 0.1% of
	// its stream returns a handful of counts in the single digits and looks
	// exactly like an exact answer over a handful of events.
	//
	// The sketch does not record n, so the bound cannot be derived from what
	// this client returns — carry n out of band (an event counter on the same
	// pipeline is the usual answer) if the difference matters to you.
	Count uint64
}

TopKItem is one (key, count) pair from a Misra-Gries summary.

Jump to

Keyboard shortcuts

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