refactor(flagd): migrate JSONLogic evaluator to datalogic-rs v5 via C FFI#105
Open
shankar-gpio wants to merge 1 commit into
Open
refactor(flagd): migrate JSONLogic evaluator to datalogic-rs v5 via C FFI#105shankar-gpio wants to merge 1 commit into
shankar-gpio wants to merge 1 commit into
Conversation
f02a997 to
5169226
Compare
Contributor
There was a problem hiding this comment.
Code Review
This pull request replaces the custom C++ JsonLogic implementation with the datalogic-rs engine via a C FFI. The changes include removing the previous flagd_ops and json_logic source files, updating the Bazel build configuration to fetch platform-specific datalogic-rs binaries, and introducing the DatalogicEngine RAII wrapper. Feedback highlights a critical need to check for null pointers on the engine handle to prevent segmentation faults and suggests documenting the performance implications of serializing JSON to strings on every evaluation.
… FFI
Replaces the hand-written JSONLogic engine and four flagd-specific
operators (~1700 LOC across providers/flagd/src/evaluator/json_logic/,
flagd_ops.{cpp,h}, and murmur_hash/) with FFI calls into the
datalogic-rs v5 C ABI.
The flagd-specific operators (starts_with, ends_with, sem_ver,
fractional) are now native in datalogic-rs's `flagd` Cargo feature,
using the same MurmurHash3-x86-32 bucketing as the flagd reference
implementation. JSONLogic spec conformance is now maintained upstream
across all language bindings (.NET, JVM, Python, Node, PHP, Go, WASM,
C++).
Per-platform staticlibs are pulled in via http_archive against the
SHA-pinned v5.0.0 release tarballs (linux/darwin x amd64/arm64). The
thin DatalogicEngine C++ wrapper (~50 LOC) provides RAII over the C
engine handle and a single Apply(rule, data) entry point that
serializes via nlohmann::json and surfaces errors through datalogic's
thread-local last-error state.
The .bazelrc workaround for abseil discarded-section issues
(-Wl,--gc-sections) is gated behind build:linux since macOS ld64
rejects the flag.
How to test:
bazelisk test //providers/flagd/tests/...
All 7 flagd tests pass, including the unmodified 627-line
evaluator_test which is the end-to-end regression contract covering
targeting rules, fractional bucketing, sem_ver gates, variant
selection, and metadata enrichment.
Signed-off-by: shankar-gpio <shankar@goplasmatic.io>
5169226 to
ddaf818
Compare
Author
|
Thanks for the review! Addressed both points in the amended commit (
All 7 flagd tests still pass locally. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR
Replaces the hand-written JSONLogic engine and four flagd-specific operators (~1700 LOC across
providers/flagd/src/evaluator/json_logic/,flagd_ops.{cpp,h}, andmurmur_hash/) with FFI calls into the datalogic-rs v5 C ABI.The flagd-specific operators (
starts_with,ends_with,sem_ver,fractional) are now native in datalogic-rs'sflagdCargo feature, using the same MurmurHash3-x86-32 bucketing as the flagd reference implementation. JSONLogic spec conformance is now maintained upstream and shared with every other language binding (.NET, JVM, Python, Node, PHP, Go, WASM) so behaviour stays aligned across the OpenFeature ecosystem.What changed
Added
providers/flagd/src/evaluator/datalogic_engine.{h,cpp}— thin RAII wrapper (~50 LOC) over the datalogic-rs C engine handle; exposes oneApply(rule, data) → absl::StatusOr<nlohmann::json>entry point that serializes vianlohmann::json, callsdatalogic_engine_apply, and surfaces errors through datalogic's thread-local last-error state.providers/flagd/third_party/datalogic/BUILD.bazel— wraps the per-platform staticlibs as a singlecc_library :datalogic_cwithselect()over@platformsconstraints.providers/flagd/tests/evaluator/datalogic_engine_test.cpp— focused unit tests for the wrapper (var, starts_with, sem_ver, fractional stability, parse-error surfacing).Modified
MODULE.bazel— addsbazel_dep platforms, declareshttp_archivefor the fourgo-staticlib-<os>-<arch>.tar.gzartifacts from the v5.0.0 GitHub release (linux/darwin × amd64/arm64), SHA-pinned..bazelrc— gates the abseil-Wl,--gc-sectionsworkaround (and-fno-asynchronous-unwind-tables) behindbuild:linuxvia--enable_platform_specific_config. macOSld64rejects--gc-sections.providers/flagd/src/evaluator/evaluator.{h,cpp}— swaps thejson_logic::JsonLogicmember forDatalogicEngine; drops the fourRegisterOperationcalls (now native upstream).providers/flagd/src/evaluator/BUILD,providers/flagd/tests/evaluator/BUILD— refresh deps.Deleted (~1700 LOC)
providers/flagd/src/evaluator/json_logic/(whole directory, 7 source files + BUILD)providers/flagd/src/evaluator/flagd_ops.{cpp,h}providers/flagd/src/evaluator/murmur_hash/(whole directory, including the vendored MurmurHash3 from aappleby/smhasher)providers/flagd/tests/evaluator/json_logic/— JSONLogic spec tests, now maintained upstream incrates/datalogic-rs/tests/suites/providers/flagd/tests/evaluator/flagd_ops_test.cpp,flagd_fractional_op_test.cpp— covered upstream incrates/datalogic-rs/tests/suites/flagd/Design choices
datalogic_engine_applyper call) over compile-cache + session. Simpler code; the C ABI explicitly exposes the string-in/string-out form because Rust-native types can't cross FFI. Rule-compile cache and arena-reusingSessioncan be added behind the sameDatalogicEngineabstraction later if profiling motivates it.libdatalogic_c.aper platform. Self-contained, no runtimeLD_LIBRARY_PATH/rpath setup for downstream consumers.const char*) in and out.nlohmann::json::dump()/parse()round-trip is unavoidable across the boundary and matches the contract exactly.Related Issues
Supersedes the in-house implementation from #65 and #92. Closes the maintenance burden of:
evaluator.cpp:222)How to test
All 7 flagd tests pass — including the unmodified 627-line
evaluator_test, which is the end-to-end regression contract covering targeting rules, fractional bucketing, sem_ver gates, variant selection, and metadata enrichment:Verified on
darwin-arm64; CI will cover the other supported platforms.Platform coverage
Currently pulling staticlibs for: linux-amd64, linux-arm64, darwin-amd64, darwin-arm64. Windows is published upstream (the v5.0.0 release ships
go-staticlib-windows-{amd64,arm64}.tar.gz) and can be added to the Bazelselect()if/when the SDK targets Windows.