Skip to content

Keep MR_Init backward compatible so one master serves every RTS line - #121

Closed
gabsow wants to merge 1 commit into
RedisGears:masterfrom
gabsow:tom.gabsow/mr-init-backcompat
Closed

Keep MR_Init backward compatible so one master serves every RTS line#121
gabsow wants to merge 1 commit into
RedisGears:masterfrom
gabsow:tom.gabsow/mr-init-backcompat

Conversation

@gabsow

@gabsow gabsow commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Competing with #120 — pick one, not both

Two ways to get the MOD-16600 fix (#116) onto the RTS 8.8 line:

I opened #120 first; Tom pushed back on adding a release branch, and he's right that this is the better shape if it holds. It does.

The compatibility surface is exactly one function

RTS 8.8 references 39 MR_* symbols; 32 are declared in our headers. Diffing every one of those declarations between a37b672 (what RTS 8.8/8.6/8.4 pin) and c6a5ed62 (master):

CHANGED MR_Init
   old: LIBMR_API int MR_Init(RedisModuleCtx*, size_t numThreads, char *password);
   new: LIBMR_API int MR_Init(RedisModuleCtx*, size_t numThreads, char *password, bool topologyEvents);

changed: 1   removed: 0

That is the whole break. MR_ClusterInit also gained the flag but is not LIBMR_API and no consumer calls it. MR_BuildCluster, MR_UpdateClusterTopologyIfNeeded*, MR_ClusterGetPassword and MR_UpdateClusterTopology were added, and additions don't break anyone.

The change

MR_Init goes back to three arguments; the new capability becomes MR_InitWithTopologyEvents. Old consumers build unchanged, new ones opt in by name. rust_api's mr_init keeps its signature and binds the new symbol, so the bindgen-generated bindings and tests/mr_test_module are untouched.

Why the topology-event code is safe to ship to 8.8

Not just "disabled" — unreachable. Redis on that line does not emit the notification at all; the Enterprise cluster plugin says so on startup:

ClusterPlugin: Failed to load symbol: "clusterNotifyTopologyChanged",
               assuming this an old redis version w/out ASM

(from the RE 8.8 shard log in RED-211253). With no event: MR_TopologyEventSeen stays false, the RedisModule_Assert(!MR_TopologyEventSeen) in both CLUSTERSET paths holds, and MR_UpdateClusterTopology() is only ever called by a consumer that registered a handler. The three-argument MR_Init makes that explicit by never setting the flag.

Verification

  • make libmr builds; nm shows both MR_Init and MR_InitWithTopologyEvents exported from src/libmr.a.
  • A translation unit calling the three-argument MR_Init exactly as RTS 8.8 does (src/libmr_integration.c:1025) compiles with 0 errors — RTS 8.8 needs no source change.
  • A translation unit calling MR_InitWithTopologyEvents compiles with 0 errors.

What I have not verified, and would want to before 8.8 actually adopts master

If the TLS change is unacceptable for 8.8, #120 is still the safer route and this PR should be closed. If it's fine, merge this, close #120, and delete the 8.8 branch I created there.

RTS side

RTS master's call site moves to MR_InitWithTopologyEvents (one line). RTS 8.8/8.6/8.4 change nothing but the submodule pin. I'll open those once we've picked a direction.


Note

Low Risk
Localized API split with backward-compatible MR_Init; default remains no topology events, matching pre-change behavior for existing consumers.

Overview
Restores ABI compatibility for consumers (e.g. RedisTimeSeries 8.8) that still call the original three-argument MR_Init(ctx, numThreads, password) after master had added a fourth topologyEvents parameter.

The four-argument behavior moves to MR_InitWithTopologyEvents, which performs the real initialization (including MR_ClusterInit(..., topologyEvents)). MR_Init is a thin wrapper that calls it with topologyEvents=false, so legacy binaries keep working without recompiling and topology-event paths stay off unless a consumer explicitly opts in and drives MR_UpdateClusterTopology().

mr.h documents both entry points. rust_api’s mr_init now binds MR_InitWithTopologyEvents instead of MR_Init, preserving the Rust API’s topology_events flag without changing bindgen call sites beyond the symbol name.

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

MR_Init gained a topologyEvents parameter, which is the only reason
RedisTimeSeries 8.8 (and 8.6 / 8.4) cannot build against master: they call the
three-argument form at src/libmr_integration.c:1025. Of the 39 MR_* symbols
RTS 8.8 references, 32 are declared in our headers and MR_Init is the only one
whose declaration changed; nothing was removed.

So restore MR_Init to its pre-topology-events signature and move the new
capability to MR_InitWithTopologyEvents. Old consumers build unchanged, new
consumers opt in by name.

On 8.8 and older the topology-event paths are not merely disabled, they are
unreachable: redis there does not emit the notification at all, which the
Enterprise cluster plugin reports as

    ClusterPlugin: Failed to load symbol: "clusterNotifyTopologyChanged",
                   assuming this an old redis version w/out ASM

With no event, MR_TopologyEventSeen stays false, the
RedisModule_Assert(!MR_TopologyEventSeen) in the CLUSTERSET paths holds, and
MR_UpdateClusterTopology() is only ever called by a consumer that registers a
handler. The three-argument MR_Init makes that explicit by never enabling the
flag.

Why this matters: without it, shipping a LibMR fix to the 8.8 line means either
a maintenance branch plus a cherry-pick per fix (see RedisGears#120) or dragging the whole
topology-events feature onto a release branch. With it, RTS 8.8 just bumps
deps/LibMR to master.

Verified:
- make libmr builds; nm shows both MR_Init and MR_InitWithTopologyEvents exported.
- A translation unit calling the three-argument MR_Init, exactly as RTS 8.8 does,
  compiles with no errors -- i.e. RTS 8.8 needs no source change.
- A translation unit calling MR_InitWithTopologyEvents compiles with no errors.
- rust_api's mr_init keeps its signature and now binds the new symbol, so the
  bindgen-generated bindings and tests/mr_test_module are unaffected.

Not verified here: a full RTS 8.8 build against master, and whether the other
commits master carries since a37b672 are all acceptable on 8.8 -- RedisGears#104 and RedisGears#108
look wanted, RedisGears#117/RedisGears#119 are topology-event adjustments and therefore inert, but
RedisGears#111/RedisGears#115 change the inter-shard TLS gate and deserve a look before 8.8 adopts
master.
@gabsow

gabsow commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Closing — Tom's suggestion is simpler and I'd rather not grow the public API to solve it.

Instead of adding a second init entry point here, RTS 8.8 / 8.6 / 8.4 just pass topologyEvents = false at their existing call site (src/libmr_integration.c:1025) in the same commit that bumps deps/LibMR. Those branches have to be touched for the pin bump anyway, so the marginal cost is one argument, and the call site becomes self-documenting about topology events being off on that line.

Checked that false is a faithful "old behaviour" rather than an assumption: the entire diff of MR_ClusterInit between a37b672 and c6a5ed62 is one line —

+ clusterCtx.topologyEvents = topologyEvents;

No conditional registration, no behaviour branch. Every clusterCtx.topologyEvents gate therefore takes the same path a37b672 took. And on 8.8 the paths are unreachable regardless: redis there never emits the notification (ClusterPlugin: Failed to load symbol: "clusterNotifyTopologyChanged").

So no LibMR change is needed for compatibility at all. #120 (the 8.8 maintenance branch) is closing for the same reason.

@gabsow gabsow closed this Aug 6, 2026
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.

1 participant