Compile audience segment definitions into execution plans. Partitions filters into SQL-evaluable and predicate-evaluable phases.
Compile audience segment definitions into execution plans. Partitions filters into SQL-evaluable and predicate-evaluable phases.
AND/OR/NOT composition of audience segment result sets. FC/IS rule: pure functions only — no I/O, no side effects.
Well-formedness (unknown operator, NOT-inside-OR, circular/unknown/invalid
segment refs) is checked up front by explain-composition; the shell
validates a composition tree before evaluating it and raises the typed error
at the HTTP boundary. The evaluation functions below therefore assume a valid
tree and never throw — their error branches fail safe (an empty result set,
and the cycle guard still terminates).
AND/OR/NOT composition of audience segment result sets. FC/IS rule: pure functions only — no I/O, no side effects. Well-formedness (unknown operator, NOT-inside-OR, circular/unknown/invalid segment refs) is checked up front by `explain-composition`; the shell validates a composition tree before evaluating it and raises the typed error at the HTTP boundary. The evaluation functions below therefore assume a valid tree and never throw — their error branches fail safe (an empty result set, and the cycle guard still terminates).
Filter multimethods for audience segment evaluation. FC/IS rule: pure functions only — no I/O, no side effects, no logging.
Validity is checked up front by explain-filter (pure, returns an anomaly
map or nil). The shell validates a segment's filters before compilation and
raises the typed error at the HTTP boundary, so the multimethods below assume
a known filter type and a supported operator and never throw — their unknown
branches fail safe (nil / a false predicate).
Filter multimethods for audience segment evaluation. FC/IS rule: pure functions only — no I/O, no side effects, no logging. Validity is checked up front by `explain-filter` (pure, returns an anomaly map or nil). The shell validates a segment's filters before compilation and raises the typed error at the HTTP boundary, so the multimethods below assume a known filter type and a supported operator and never throw — their unknown branches fail safe (nil / a false predicate).
Pure Hiccup UI components for audience segments. No I/O, no side effects.
Pure Hiccup UI components for audience segments. No I/O, no side effects.
Port definitions for the wagoe-audience library.
Four protocols cover the full lifecycle:
IAudienceResolver — evaluate audiences and check membership IAudienceRepository — persist and retrieve audience definitions IAudienceCache — cache evaluated audience results IUserDataSource — query users for filter evaluation
Port definitions for the wagoe-audience library. Four protocols cover the full lifecycle: IAudienceResolver — evaluate audiences and check membership IAudienceRepository — persist and retrieve audience definitions IAudienceCache — cache evaluated audience results IUserDataSource — query users for filter evaluation
Malli schemas for the wagoe-audience library. All internal data uses kebab-case keywords. snake_case conversion happens only at DB boundaries.
Malli schemas for the wagoe-audience library. All internal data uses kebab-case keywords. snake_case conversion happens only at DB boundaries.
DB-backed cache for evaluated audience results.
L1 — audience_segments.cached_at + audience_memberships table. A result is fresh if cached_at is within TTL minutes. put-cached writes memberships and stamps cached_at + member_count. get-cached reads memberships when stamp is fresh, else nil. invalidate / invalidate-all clear cached_at and memberships.
L2 — wagoe-cache (Redis / in-memory) can be layered in later. The wagoe-cache param is accepted but not yet wired.
DB-backed cache for evaluated audience results.
L1 — audience_segments.cached_at + audience_memberships table.
A result is fresh if cached_at is within TTL minutes.
put-cached writes memberships and stamps cached_at + member_count.
get-cached reads memberships when stamp is fresh, else nil.
invalidate / invalidate-all clear cached_at and memberships.
L2 — wagoe-cache (Redis / in-memory) can be layered in later.
The wagoe-cache param is accepted but not yet wired.HTTP handlers and route definitions for audience management.
Web Pages (mounted under /web/audiences): GET /audiences — list all segments GET /audiences/builder — new segment form GET /audiences/builder/:id — edit existing segment
API Endpoints (mounted under /api/audiences): POST /audiences — create audience PUT /audiences/:id — update audience DELETE /audiences/:id — delete audience POST /audiences/preview — returns count + sample POST /audiences/:id/evaluate — trigger evaluation GET /audiences/:id/members — list members
HTTP handlers and route definitions for audience management. Web Pages (mounted under /web/audiences): GET /audiences — list all segments GET /audiences/builder — new segment form GET /audiences/builder/:id — edit existing segment API Endpoints (mounted under /api/audiences): POST /audiences — create audience PUT /audiences/:id — update audience DELETE /audiences/:id — delete audience POST /audiences/preview — returns count + sample POST /audiences/:id/evaluate — trigger evaluation GET /audiences/:id/members — list members
Integrant lifecycle management for the audience module.
Config keys:
:wagoe/audience {:db-ctx (ig/ref :wagoe/db-context) :cache-service (ig/ref :wagoe/cache) :user-data-source (ig/ref :wagoe/user-data-source)}
Returns {:store <IAudienceRepository> :resolver <IAudienceResolver> :cache <IAudienceCache>}
:wagoe/audience-routes {:audience-service (ig/ref :wagoe/audience)}
Returns {:api [...] :web [...]} for composition by the HTTP handler.
Integrant lifecycle management for the audience module.
Config keys:
:wagoe/audience
{:db-ctx (ig/ref :wagoe/db-context)
:cache-service (ig/ref :wagoe/cache)
:user-data-source (ig/ref :wagoe/user-data-source)}
Returns {:store <IAudienceRepository> :resolver <IAudienceResolver> :cache <IAudienceCache>}
:wagoe/audience-routes
{:audience-service (ig/ref :wagoe/audience)}
Returns {:api [...] :web [...]} for composition
by the HTTP handler.No vars found in this namespace.
Database persistence for audience definitions and memberships.
Implements IAudienceRepository using next.jdbc + HoneySQL.
Column layout for audience_segments: audience_id VARCHAR — keyword name (e.g. "premium-users") filters TEXT/JSONB — serialised as JSON tags TEXT/JSONB — serialised as JSON composition TEXT/JSONB — optional, serialised as JSON cache_config TEXT/JSONB — optional, serialised as JSON
JSON columns use cheshire for serialisation. On PostgreSQL the
columns are JSONB; on H2 (tests) they are stored as TEXT — both
are handled by ->json below.
Database persistence for audience definitions and memberships. Implements IAudienceRepository using next.jdbc + HoneySQL. Column layout for audience_segments: audience_id VARCHAR — keyword name (e.g. "premium-users") filters TEXT/JSONB — serialised as JSON tags TEXT/JSONB — serialised as JSON composition TEXT/JSONB — optional, serialised as JSON cache_config TEXT/JSONB — optional, serialised as JSON JSON columns use cheshire for serialisation. On PostgreSQL the columns are JSONB; on H2 (tests) they are stored as TEXT — both are handled by `->json` below.
Load-time registry of audience segment definitions and the defaudience macro.
The registry is mutable process state, so it lives in the shell — the audience
core namespaces (compiler, composition, filter, ui) stay pure. Definitions are
registered at namespace load via the defaudience macro (validated against the
AudienceDefinition schema) and read at runtime by the audience service.
Load-time registry of audience segment definitions and the `defaudience` macro. The registry is mutable process state, so it lives in the shell — the audience core namespaces (compiler, composition, filter, ui) stay pure. Definitions are registered at namespace load via the `defaudience` macro (validated against the AudienceDefinition schema) and read at runtime by the audience service.
Evaluation service for audience segments.
Implements IAudienceResolver with a hybrid SQL + predicate pipeline:
FC/IS boundary: this shell namespace is allowed to perform I/O.
Evaluation service for audience segments.
Implements IAudienceResolver with a hybrid SQL + predicate pipeline:
1. Check L1 DB cache (via get-cached-with-ttl when TTL is known).
2. Load definition from in-process registry, fall back to repository.
3. Compile definition into {:sql-clauses [...] :predicates [...]}.
4. If :compose present, resolve composed segments recursively.
5. Phase 1 — SQL: query user IDs via IUserDataSource.query-users-sql.
6. Phase 2 — predicates: load-users for candidates, filter in-process.
7. Build SegmentResult.
8. Cache result when cache + TTL are configured.
9. Return result.
FC/IS boundary: this shell namespace is allowed to perform I/O.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |