Skip to content

fix: emit prerequisite events deepest-first - #55

Merged
tanderson-ld merged 2 commits into
mainfrom
ta/SDK-2745-event-order
Jul 23, 2026
Merged

fix: emit prerequisite events deepest-first#55
tanderson-ld merged 2 commits into
mainfrom
ta/SDK-2745-event-order

Conversation

@tanderson-ld

@tanderson-ld tanderson-ld commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Aligns Roku's prerequisite event emission order with the rest of the LaunchDarkly SDK family. variationDetail in LaunchDarklyClient.brs now emits the current flag's feature event after the recursive prerequisite walk instead of before it. For a flag A with prerequisite B, events now land as [B, A] (matching every other client and server SDK) rather than [A, B].

Tracker: SDK-2745. Stacked on #54.

Motivation

A survey during the cycle-detection work in #54 found that Roku was the only outlier across all client SDKs (.NET, JS, Flutter, Android, iOS, C++) and every server SDK (Go, .NET, JS, Java, Python, Ruby, C++) — all of which emit prerequisite events before the parent's event. LaunchDarkly's event ingestion does not depend on intra-batch ordering, so the pre-existing behavior wasn't a functional bug, but the divergence is a cross-SDK anomaly worth correcting.

Changes

  • rawsrc/LaunchDarklyClient.brs: move the handleEventsForEval(launchDarklyLocalState) call to after the prerequisite recursion block.
  • src/test/source/tests/Test__Client.brs: update the four cycle-detection tests to expect deepest-first ordering (e.g., [flagB, flagA] for a two-cycle evaluating A).

Test plan

  • Unit tests pass on a Roku Express device (all TestSuite__Client cases, including the five CycleDetection_* tests).
  • SDK contract tests pass against the harness: 784 total, 30 skipped, 754 ran, all passed. This includes every events/summary events/prerequisites/handles cycles/* and events/prerequisite events handle cycles/* case.
  • Ordering change is confirmed on device: two-cycle now emits [B, A].

Note

Low Risk
Single reorder of event emission in variationDetail; flag evaluation and cycle detection are untouched, and ingestion does not rely on intra-batch event order.

Overview
variationDetail in LaunchDarklyClient.brs now calls handleEventsForEval after walking prerequisites instead of before. Prerequisite feature events are emitted deepest-first (e.g. B then A when A depends on B), matching other LaunchDarkly client and server SDKs; Roku had been parent-first.

The four CycleDetection_* tests in Test__Client.brs were updated to assert the new event key order for two-cycles, three-cycles, and the diamond graph (including duplicate D events on separate paths). Evaluation values and cycle-guard behavior are unchanged.

Reviewed by Cursor Bugbot for commit 3de34ff. Bugbot is set up for automated code reviews on this repo. Configure here.

Move the current flag's handleEventsForEval call to after the recursive
prerequisite walk in variationDetail. This aligns the Roku client SDK
with the other client SDKs (.NET, JS, Flutter, Android, iOS, C++) and
every server SDK (Go, .NET, JS, Java, Python, Ruby, C++), all of which
emit prerequisite feature events before the parent's event.

Prior to this change, evaluating flagA with prereq flagB emitted
[flagA, flagB]. It now emits [flagB, flagA], matching the cross-SDK
convention. Individual events are self-describing and LD's event
ingestion does not depend on intra-batch ordering, so this is a
correctness-for-parity change rather than a functional bug fix.

Also updates the four cycle-detection tests in Test__Client.brs to
assert deepest-first ordering.
@tanderson-ld
tanderson-ld requested a review from a team as a code owner July 22, 2026 21:02
Base automatically changed from ta/SDK-2710-cycle-detection to main July 23, 2026 19:49
Reconciles the deepest-first prereq-event ordering with the
LaunchDarklyClientSharedPrivateFunctions encapsulation that landed in main.

# Conflicts:
#	rawsrc/LaunchDarklyClient.brs
@tanderson-ld
tanderson-ld merged commit 3fe85d1 into main Jul 23, 2026
6 checks passed
@tanderson-ld
tanderson-ld deleted the ta/SDK-2745-event-order branch July 23, 2026 20:04
tanderson-ld added a commit that referenced this pull request Jul 23, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.4.1](2.4.0...2.4.1)
(2026-07-23)


### Bug Fixes

* add defensive cycle guard to prerequisite evaluation
([ceab01d](ceab01d))
* add defensive cycle guard to prerequisite evaluation
([#54](#54))
([d4d325f](d4d325f))
* emit prerequisite events deepest-first
([d729aa7](d729aa7))
* emit prerequisite events deepest-first
([#55](#55))
([3fe85d1](3fe85d1))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Diff is only version manifest and changelog; no runtime code changes
in this PR.
> 
> **Overview**
> **Release 2.4.1** — bumps the package version in
`.release-please-manifest.json` from **2.4.0** to **2.4.1** and adds the
**2.4.1** section to `CHANGELOG.md` (Release Please).
> 
> The changelog records two prerequisite-evaluation fixes already landed
on main: a **cycle guard** so cyclic prerequisite graphs stop recursing
instead of running without bound, and **deepest-first** ordering when
emitting prerequisite feature events (aligned with client contract
expectations).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
b6d0e87. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants