# `ExDataSketch.SampleData`
[🔗](https://github.com/thanos/ex_data_sketch/blob/main/lib/ex_data_sketch/sample_data.ex#L1)

Sample-data generators for the tutorial livebooks under `livebooks/sketches/`.

Not part of the sketch API -- this module exists purely so each livebook's
"Sample data" section is a single function call instead of a duplicated
cache-path/generate/cache-write block. Every function here generates a
fixed *shape* of data (documented per function below) at a default size
matching what its livebook actually uses, and transparently caches that
default result under `System.tmp_dir!()`, so re-running a livebook (or a
whole verification sweep across all of them) after the first pass is
instant.

Every generator also accepts real size overrides (`:count`, `:pool_size`,
`:half_count`, or a couple of Theta/IBLT-specific keys -- see each
function's `@doc`), primarily so this module's own regression tests don't
need to generate millions of items to exercise it. **Caching only applies
to the default (no-override) call** -- passing any option other than
`:backend` skips the cache file entirely, so a small test run can never
read stale-shaped data from, or overwrite, the real livebook cache.

Randomized generators use the `ExDataSketch.Backend.Rust` NIF when it's
available, since the defaults are 1-2 million items; pass `backend:
ExDataSketch.Backend.Pure` to force the Elixir fallback (used
automatically when the NIF isn't loaded). Deterministic range-based
generators (no randomness involved -- `bloom_urls/1`, `cuckoo_sessions/1`,
`quotient_api_keys/1`, `xor_filter_domains/1`, `filter_chain_users/1`,
`theta_sets/1`, `iblt_keys/1`) are plain Elixir only: a single linear pass
building formatted strings has nothing for a NIF to meaningfully
accelerate.

# `bloom_urls`

```elixir
@spec bloom_urls(keyword()) :: {[String.t()], [String.t()]}
```

Bloom tutorial: inserted URLs plus an equal number of novel URLs to test
the false-positive rate against.

Options: `:half_count` (default 500,000).

# `cms_events`

```elixir
@spec cms_events(keyword()) :: [String.t()]
```

CMS tutorial: page-view events, power-law distributed (a few pages dominate).

Options: `:count` (default 2,000,000), `:pool_size` (default 10,000).

# `cqf_events`

```elixir
@spec cqf_events(keyword()) :: [String.t()]
```

CQF tutorial: rate-limit-check events, power-law distributed.

Options: `:count` (default 1,000,000), `:pool_size` (default 50,000).

# `cuckoo_sessions`

```elixir
@spec cuckoo_sessions(keyword()) :: {[String.t()], [String.t()]}
```

Cuckoo tutorial: inserted sessions plus an equal number of novel sessions.

Options: `:half_count` (default 500,000).

# `ddsketch_durations`

```elixir
@spec ddsketch_durations(keyword()) :: [float()]
```

DDSketch tutorial: operation durations (ms) spanning several orders of
magnitude (fast API calls, medium DB queries, rare slow jobs).

Options: `:count` (default 1,000,000).

# `filter_chain_users`

```elixir
@spec filter_chain_users(keyword()) :: {[String.t()], [String.t()]}
```

FilterChain tutorial: inserted users plus an equal number of novel users.

Options: `:half_count` (default 500,000).

# `frequent_items_queries`

```elixir
@spec frequent_items_queries(keyword()) :: [String.t()]
```

FrequentItems tutorial: search queries, power-law distributed.

Options: `:count` (default 1,000,000), `:pool_size` (default 5,000).

# `hll_events`

```elixir
@spec hll_events(keyword()) :: [String.t()]
```

HLL tutorial: events drawn uniformly from a visitor pool.

Options: `:count` (default 2,000,000), `:pool_size` (default 500,000).

# `iblt_keys`

```elixir
@spec iblt_keys(keyword()) :: {[String.t()], [String.t()], [String.t()], [String.t()]}
```

IBLT tutorial: two mostly-agreeing key sets simulating drifted replicas.

Options: `:shared_count` (default 200,000), `:only_a_count` (default 7),
`:only_b_count` (default 5).

# `kll_latencies`

```elixir
@spec kll_latencies(keyword()) :: [float()]
```

KLL tutorial: simulated latencies (ms), mostly fast with a long tail.

Options: `:count` (default 1,000,000).

# `misra_gries_queries`

```elixir
@spec misra_gries_queries(keyword()) :: [String.t()]
```

MisraGries tutorial: same shape as `frequent_items_queries/1` (so the two
tutorials are directly comparable), cached separately.

Options: `:count` (default 1,000,000), `:pool_size` (default 5,000).

# `quotient_api_keys`

```elixir
@spec quotient_api_keys(keyword()) :: {[String.t()], [String.t()]}
```

Quotient tutorial: inserted API keys plus an equal number of novel API keys.

Options: `:half_count` (default 300,000).

# `req_latencies`

```elixir
@spec req_latencies(keyword()) :: [float()]
```

REQ tutorial: latencies (ms), tight and boring in the bulk with a rare,
important tail.

Options: `:count` (default 1,000,000).

# `theta_sets`

```elixir
@spec theta_sets(keyword()) :: {[String.t()], [String.t()]}
```

Theta tutorial: two overlapping user-ID sets with a known true union/intersection.

Options: `:count_a` (default 600,000), `:count_b` (default 600,000),
`:overlap` (default 200,000, must be `<= min(count_a, count_b)`). Set A is
`1..count_a`; set B starts `overlap` items before set A ends, giving an
intersection of exactly `overlap` items.

# `ull_events`

```elixir
@spec ull_events(keyword()) :: [String.t()]
```

ULL tutorial: events drawn uniformly from a session pool.

Options: `:count` (default 2,000,000), `:pool_size` (default 300,000).

# `xor_filter_domains`

```elixir
@spec xor_filter_domains(keyword()) :: {[String.t()], [String.t()]}
```

XorFilter tutorial: blocklisted domains plus an equal number of novel
(safe) domains.

Options: `:half_count` (default 500,000).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
