MemberJunction / MemberJunction/MJ

Scaled integration tests + performance baseline for cache-invalidation broadcast fan-out (mock browser endpoints)

Open
#4,301 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
2d 1h
Merged PRs (30d)
323

Description

## Why

#4250 documents that every entity save broadcasts one cache-invalidation message to every connected browser, with no grouping per unit of work — a bulk write like enabling field-level security (~84 permission rows on `MJ: Employees`) emits ~84 messages × N clients. The proposed fix is transaction-scoped batching of the transport. Before and after that lands, we need **numbers, not estimates**: at MJ's typical scale (hundreds to low thousands of connected clients) the current overhead may well be tolerable — which changes how aggressively #4250 needs to be scheduled — and once batching exists, its effect should be measurable, not asserted. Suggested by Amith in the design discussion around #4250.

## What

Additions to the deterministic/mutation integration suite (`@memberjunction/integration-test-suite`) that exercise the broadcast path at scale against a live MJAPI:

1. **Mock "browser" endpoints** — a fixture that opens N GraphQL `cacheInvalidation` subscriptions over WebSocket (N configurable; start with ~50–200 in CI, higher for local perf runs). Each mock client counts messages, bytes, and timestamps; none of them needs to be a real browser — the subscription contract is the surface under test.
2. **Bulk-write drivers** — trigger representative units of work and measure the fan-out:
- a multi-row entity-layer burst (the FLS flag flip is a ready-made ~84-row driver, or any `RunInEntityTransaction` loop);
- a `TransactionGroup` submit (the batched-dashboard shape);
- a single save (the baseline unit).
3. **Assertions + recorded metrics**:
- correctness invariants: every connected client receives every invalidation (today: N×rows messages; post-#4250: one batch per unit of work carrying all per-record payloads);
- performance recorded in `TestRun.ResultDetails` as trend data (messages/client, total bytes, wall time from first save to last delivery), the same visibility-not-gating posture as IT87's FLS21 refresh-cost check — no wall-clock pass/fail beyond generous sanity ceilings.
4. **Config kill-switch coverage** (once #4250's configuration option to disable browser broadcasting exists): with broadcasting off, clients receive nothing and reconverge via the smart cache checks — pin that the escape hatch actually disconnects the firehose without breaking convergence.

## Notes for implementation

- The suite already has the patterns to reuse: client-transport bundles gate on MJAPI liveness and skip-as-pass when it's down; secondary `GraphQLDataProvider` connections exist in the FLS client bundle (watch the hard-singleton trap documented there); mutation-gated tier for the write drivers.
- Related: #4250 (the batching design this measures), #3242 (unfiltered `RecordData` on the same surface — a batch message shape interacts with the permission-filtering redesign), #2125 (scoped notifications umbrella).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Contributor guide

Open the contributing guide

Research direction

Start in the deterministic/mutation integration suite in @memberjunction/integration-test-suite, reading the client-transport bundles, the FLS client bundle, and IT87's FLS21 refresh-cost check. Trace cacheInvalidation subscriptions, RunInEntityTransaction, TransactionGroup, and TestRun.ResultDetails against a live MJAPI. Done means scaled mock clients cover the listed write paths, record trend metrics without tight timing gates, and verify the broadcast kill-switch and reconvergence behavior once #4250's option exists.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql
Domain
api, backend, performance, testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.