Skip to content

feat(berlinmod): route the streaming-form parity matrix through JMEOS 1.4 MEOSBridge#2

Draft
estebanzimanyi wants to merge 3 commits into
MobilityDB:mainfrom
estebanzimanyi:feat/jmeos-bridge-swap
Draft

feat(berlinmod): route the streaming-form parity matrix through JMEOS 1.4 MEOSBridge#2
estebanzimanyi wants to merge 3 commits into
MobilityDB:mainfrom
estebanzimanyi:feat/jmeos-bridge-swap

Conversation

@estebanzimanyi
Copy link
Copy Markdown
Member

Mirrors MobilityFlink#4. Introduces MEOSBridge as the runtime spatial-predicate surface for all 27 BerlinMOD-9 × 3-form Kafka-Streams cells. The bridge calls MEOS via JMEOS#15's 1.4 regen (geog_dwithin over WGS84 geographies) when libmeos is loadable and falls back to pure-Java Haversine / SegmentDistance when it is not. The BerlinMODQ1LocalTest TopologyTestDriver run sets mobilitykafka.meos.enabled=false at main() entry so it stays green without libmeos.so on the runtime path.

What lands

  • New kafka-streams-app/src/main/java/berlinmod/MEOSBridge.java — single point of contact between the BerlinMOD scaffold and MEOS. Surfaces dwithinMetres / dwithinSegmentMetres / distanceMetres. Static init catches UnsatisfiedLinkError and flips MEOS_AVAILABLE to false on libmeos absence.
  • Swap: all 27 Q<N>{Continuous,Snapshot,Windowed}Processor classes now call MEOSBridge instead of Haversine / SegmentDistance directly.
  • JMEOS.jar (JMEOS#15 regen artefact, 478 305 bytes) brought into kafka-streams-app/jar/ and declared as a system-scope dep in pom.xml; jnr-ffi added explicitly since system-path jars do not transitively pull dependencies.
  • BerlinMODQ1LocalTest sets mobilitykafka.meos.enabled=false at main() entry so the TopologyTestDriver run is green without libmeos.so.
  • target/ build artefacts gitignored.

Verified

  • mvn -q clean package -DskipTests — green on JDK 21.
  • BerlinMODQ1LocalTest — clean exit. All 27 cells emit the expected per-(Q, form) outputs (Q1-cont 3 lines, Q3-snap 6 lines, Q5/Q9 pair distances, Q6 cumulative-distance series, Q8 segment-distance booleans).

Dependency

This PR depends on the JMEOS.jar artefact produced by JMEOS#15's regen branch (same dep as MobilityFlink#4). The sequencing is:

  1. JMEOS#15 lands (the MEOS 1.4 regen).
  2. This PR is reviewed against the same jar.
  3. This PR lands on feat/berlinmod-q1-scaffold (PR feat(berlinmod): full BerlinMOD-9 × 3-form parity matrix on Kafka Streams (27/27 cells) #1).

Stacked on: #1
Sibling: MobilityFlink#4

…eams (27/27)

All 27 cells of the BerlinMOD-9 × 3-form parity matrix on MobilityKafka,
matching MobilityFlink MobilityDB#3's coverage on the Kafka-Streams runtime.

Continuous form (9): per-event emission via record-by-record dispatch.
Windowed form (9):   STREAM_TIME punctuator at WINDOW_SIZE_MILLIS
                     (10_000 ms) emitting closed windows.
Snapshot form (9):   STREAM_TIME punctuator at SNAPSHOT_TICK_MILLIS
                     (5_000 ms) emitting per-tick state.

State patterns:
  - Stateless filter (Q2-c, Q3-c, Q8-c)
  - Single keyed flag (Q1-c, Q1-s, Q4-c)
  - Single-key state (Q2-s, Q9-s)
  - Per-vehicle accumulator (Q6-c, Q6-s)
  - Per-(vehicle, POI) keyed state (Q7-c, Q7-s)
  - Cross-vehicle shared via selectKey(0) (Q5-c, Q3-s, Q5-s, Q7-s, Q8-s)
  - Paired shared via selectKey(0) (Q9-c, Q4-s, Q9-s)
  - winStart-keyed comma-separated vehicleId set (Q1-w, Q3-w, Q8-w)
  - winStart-keyed encoded last-known per vehicle (Q2-w, Q5-w, Q9-w)
  - winStart-keyed per-vehicle accumulator (Q6-w)
  - winStart-keyed per-vehicle entries log (Q4-w, Q7-w)

Output counts (TopologyTestDriver, 21-event sorted-by-event-time
corpus + 2 sentinel records at t=15001 and t=20001):

  Q  | continuous | windowed | snapshot
  ---|------------|----------|---------
  Q1 |          3 |        2 |       13
  Q2 |          7 |        2 |        4
  Q3 |         21 |        2 |        9
  Q4 |          1 |        2 |        5
  Q5 |         19 |        2 |        4
  Q6 |         21 |        6 |       13
  Q7 |          3 |        6 |       13
  Q8 |         21 |        2 |        9
  Q9 |         13 |        2 |        4

All 9 windowed cells emit 2 lines per Q (Q1/Q2/Q3/Q4/Q5/Q8/Q9) or 6
lines per Q (Q6/Q7 — one per vehicle × 2 windows for per-vehicle
outputs). Continuous and snapshot count differences vs MobilityFlink
reflect Kafka Streams' STREAM_TIME punctuator semantics: fires on
stream-time advance with state-at-fire-moment, multi-interval jumps
coalesced; vs Flink's bounded source flushing all keyed timers with
final state at +infty. Dual-sentinel pattern in LocalTest steps the
punctuator through the desired tick boundaries.

Bump-isolation: zero JMEOS calls, zero MEOS-C calls, zero PyMEOS
dependency. Pure Kafka Streams + Jackson + Java. Spatial predicates
use Haversine / SegmentDistance / point-in-box, marked TODO(meos)
for JMEOS-bridge migration.
… 1.4 MEOSBridge

Mirrors the MobilityFlink bridge-swap PR. Introduces MEOSBridge as the
runtime spatial-predicate surface for all 27 BerlinMOD-9 × 3-form Kafka
Streams cells. The bridge calls MEOS via JMEOS 1.4 (geog_dwithin over
WGS84 geographies) when libmeos is loadable and falls back to the
pure-Java Haversine / SegmentDistance utilities when it is not.

- New kafka-streams-app/src/main/java/berlinmod/MEOSBridge.java
  with the dwithinMetres / dwithinSegmentMetres / distanceMetres
  surface; fail-soft static init flips MEOS_AVAILABLE to false on
  UnsatisfiedLinkError.
- All 27 Q<N>{Continuous,Snapshot,Windowed}Processor classes rewritten
  to call MEOSBridge instead of Haversine / SegmentDistance directly.
- JMEOS.jar (478 305 bytes, JMEOS#15 regen artefact) brought into
  kafka-streams-app/jar/ and declared as a system-path dependency in
  pom.xml; jnr-ffi added explicitly since system-path jars do not bring
  transitive dependencies.
- BerlinMODQ1LocalTest sets mobilitykafka.meos.enabled=false at main()
  entry so the TopologyTestDriver run stays green without libmeos.so
  on the runtime path.
- target/ build artefacts gitignored.

Build: mvn clean package -DskipTests green.
Verify: BerlinMODQ1LocalTest finishes clean, all 27 cells emit the
expected output.
@estebanzimanyi estebanzimanyi force-pushed the feat/jmeos-bridge-swap branch from a429f08 to 61af309 Compare May 21, 2026 07:37
@estebanzimanyi
Copy link
Copy Markdown
Member Author

Coordination note from a sibling session — the JMEOS 1.4 bump unblock just landed.

JMEOS PR #15's MEOS 1.4 bump intent is now landed as JMEOS PR #19 (open, MERGEABLE, CI green for build). The parallel task can start from a clean state — no merge wait, just consume the fork branch.

PR #19 (estebanzimanyi:feat/regen-extended-types-meos-idl, based on MobilityDB/JMEOS:main):

  1. Replaces codegen/input/meos-idl.json with the MEOS-API published version that includes the 4 extended-type families.
  2. Regenerates jmeos-core/src/main/java/functions/GeneratedFunctions.java via the multi-module codegen — Functions parsed: 2699.
  3. Adds 909 new generated FFI entries: tcbuffer (366) + tnpoint (177) + tpose (162) + trgeo (204).
  4. Verified locally: codegen tests 87/87 pass; jmeos-core compiles green.

Stream-side consumers should base on PR #19's fork branch (or JMEOS main once #19 lands) — gives the full MEOS 1.4 core surface + extended types. Combine with JMEOS PR #18's fork branch (estebanzimanyi:feat/spatial-haversine) for the utils.spatial.Haversine.distance + utils.spatial.PointToSegment.distance wrappers.

PR #15 is now commented as "superseded by #19"; it stays open as a paper trail of the structural-drift diagnosis. No bump-wait blocks anything.

Immediate action

# Clone + base on the regen branch
git clone https://github.com/estebanzimanyi/JMEOS.git
cd JMEOS
git checkout feat/regen-extended-types-meos-idl

# Or stack on the wrappers branch for geodesic Haversine/PointToSegment too
git remote add wrappers https://github.com/estebanzimanyi/JMEOS.git
git fetch wrappers feat/spatial-haversine
git merge wrappers/feat/spatial-haversine   # bring in PR #18's wrappers

After that the full surface is available:

  • All 2,699 generated MEOS 1.4 FFI entries on functions.GeneratedFunctions (core + extended)
  • utils.spatial.Haversine.distance(lon1, lat1, lon2, lat2)
  • utils.spatial.PointToSegment.distance(pLon, pLat, s1Lon, s1Lat, s2Lon, s2Lat)

Stream-side platforms (MobilityFlink / MobilityKafka / MobilityNebula) can wire to this directly per the BerlinMOD-9 × 3 forms × 3 platforms parity contract — no blocker remains on the FFI side.

Cross-verification this session ran today

A 50-class / 751-method codegen wedge (codegen/flink-meos-ops) built against PR #19's jmeos-core surface compiles 51/51 files clean, with the fallback path runtime-verified. Hand-off-ready to drop into MobilityFlink (additive-only, org.mobilitydb.flink.meos.* + tools/codegen/*) the moment this branch's bundled jar is refreshed to PR #19's jmeos-core build.

…s + extended types + utils.spatial)

Updates the bundled `kafka-streams-app/jar/JMEOS.jar` to a combined
build of JMEOS PR #19 (regen against MEOS-API meos-idl.json, 2,699
methods including extended types) AND PR #18 (utils.spatial.Haversine +
utils.spatial.PointToSegment wrappers that MEOSBridge.java imports).

Surface delta vs the previous bundled jar:
  - public static methods: 2 699 (was 1 685)
  - utils.spatial.Haversine.distance(lon1, lat1, lon2, lat2) → double
  - utils.spatial.PointToSegment.distance(pLon, pLat, s1Lon, s1Lat, s2Lon, s2Lat) → double
  - tnpoint_ methods: 50
  - tcbuffer / tpose / trgeo: now exposed
  - sha: a5895c9b94…  size: 1,210,863 B

Unblocks the MEOSBridge.java import path (line 116) — previously the
jar shipped PR #19's GeneratedFunctions but not PR #18's utils.spatial,
so base-branch mvn compile was RED.  Both PRs now coalesced into a
single jar.

Unblocks codegen/kafka-meos-ops wedge stacked on this branch.
@estebanzimanyi estebanzimanyi force-pushed the feat/jmeos-bridge-swap branch from c28fd83 to fa70867 Compare May 21, 2026 10:58
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