Skip to content

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

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#4
estebanzimanyi wants to merge 3 commits into
MobilityDB:mainfrom
estebanzimanyi:feat/jmeos-bridge-swap

Conversation

@estebanzimanyi
Copy link
Copy Markdown
Member

Introduces MEOSBridge as the runtime spatial-predicate surface for all BerlinMOD-9 × 3-form streaming cells. The bridge calls into MEOS via JMEOS#15's 1.4 regen (geog_dwithin over WGS84 geographies) when libmeos is loadable, and falls back to the pure-Java Haversine / SegmentDistance utilities when it is not. The mini-cluster local-test drivers (BerlinMODQ*LocalTest) set mobilityflink.meos.enabled=false at main() entry so they stay green without libmeos.so on the runtime path.

What lands

  • New flink-processor/src/main/java/berlinmod/MEOSBridge.java — the 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 BerlinMOD cells × spatial-predicate call sites now call MEOSBridge instead of Haversine / SegmentDistance directly. The pure-Java classes remain as the fallback implementation, not as the primary route.
  • JMEOS.jar updated to the JMEOS#15 regen branch artefact (478 305 bytes); this is the MEOS 1.4 regen build that exposes geog_dwithin / geom_in / geom_to_geog / edwithin_tgeo_geo / nad_tgeo_geo / tpoint_length.
  • AIS pipeline adapted to JMEOS 1.4: meos_initialize(String, error_handler_fn) is gone in the regen, replaced by no-arg meos_initialize() + separate meos_initialize_timezone(String) / meos_initialize_error_handler(Pointer) entry points. aisdata/Main.java and aisdata/TrajectoryWindowFunction.java updated accordingly.
  • All 9 BerlinMODQ*LocalTest drivers set mobilityflink.meos.enabled=false at main() entry so the mini-cluster runs are green without libmeos.so present.
  • target/ build artefacts gitignored.

Verified

  • mvn -q clean package -DskipTests — green on JDK 21.
  • BerlinMODQ1LocalTest — FINISHED.
  • BerlinMODQ3LocalTest — FINISHED (spatial-radius predicate).
  • BerlinMODQ5LocalTest — FINISHED (pair-meeting predicate).
  • BerlinMODQ8LocalTest — FINISHED (segment-distance predicate).

All four exercise the MEOSBridge fallback path. The MEOS-backed path is the same code with -Dmobilityflink.meos.enabled=true (default) and a loadable libmeos.so on the runtime classpath.

Dependency

This PR depends on the JMEOS.jar artefact produced by JMEOS#15's regen branch. The PR 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-q3-scaffold (PR feat(berlinmod): scaffold the full BerlinMOD-9 streaming-form parity matrix on MobilityFlink (27/27 cells) #3).

Sibling work: MobilityKafka gets the same bridge swap shape against the Kafka-Streams Processor API in a separate stacked PR.

Out of scope

  • Replacing MEOSBridge.distanceMetres's internal implementation with a direct geog_distance JMEOS call once that symbol is exposed (the predicate path is MEOS-backed; only the rarely-called raw-distance path stays Haversine for now).
  • A native libmeos.so install workflow for the mini-cluster — out of scope for this PR; the fallback path is the green-CI default.

Stacked on: #3

…matrix on MobilityFlink

All nine BerlinMOD reference queries × three streaming forms each
(continuous, windowed, snapshot) on MobilityFlink — the complete 27-cell
stream-layers parity-matrix row, locally verified end-to-end with no
external dependencies (no Kafka, no Docker, no MEOS native lib, no
JMEOS call).

Queries:

  Q1  which vehicles have appeared in the stream
  Q2  where is vehicle X at time T
  Q3  which vehicles within d of P at time T
  Q4  which vehicles entered region R, and when
  Q5  pairs of vehicles meeting near point P
  Q6  cumulative distance per vehicle
  Q7  first passage of vehicles through POIs
  Q8  vehicles close to a road segment
  Q9  distance between vehicles X and Y at time T

Each query has three form classes (Q<N>{Continuous,Windowed,Snapshot}Function)
and a companion BerlinMODQ<N>LocalTest driver running the three forms
through a Flink mini-cluster against a hardcoded synthetic corpus.

Spatial predicates today are pure Java — Haversine distance for
point-to-point (Q3, Q5, Q6, Q9), point-in-box for region containment
(Q4), and a planar-projection point-to-line-segment distance (Q8). Each
spatial call site is marked TODO(meos) for migration to the JMEOS
bridge of the corresponding MEOS operator once the in-flight MEOS 1.4
bump signals settled (Q3 edwithin_tgeo_geo; Q4 STBox eintersects; Q5
NAD / edwithin_tgeo_tgeo; Q6 trajectory length; Q7 edwithin_tgeo_geo;
Q8 distance(tgeompoint, geometry(LINESTRING)); Q9 tdistance). Q1 and
Q2 have no spatial predicate.

State patterns exercised:
  - keyed simple flag (Q1)
  - keyed last-known position (Q2, Q8)
  - keyed transition + entry log (Q4)
  - keyed accumulator (Q6)
  - keyed first-passage map (Q7)
  - shared key-by-constant state (Q9 pair-wise, Q5 multi-pair MapState)

Verified output counts (see PR description for the exact-line excerpts):

  Q  | continuous | windowed | snapshot
  ---|------------|----------|---------
  Q1 |          3 |        2 |        9
  Q2 |          7 |        2 |        3
  Q3 |         21 |        2 |        6
  Q4 |          4 |        5 |        9
  Q5 |         14 |        2 |        3   (only pair (100,200) qualifies for our P + radii)
  Q6 |         21 |        6 |        9   (drift corpus; v100=601m, v200=300m, v300=1205m)
  Q7 |          3 |        6 |        9   (3 (vehicle, POI) first-passages; intra-window scope)
  Q8 |         21 |        2 |        6   (same shape as Q3 with segment-distance)
  Q9 |          7 |        2 |        3   (X=100, Y=200; distance 4124m = ~4.1km)

Build verification: mvn clean package green; all nine LocalTests run to
completion (Flink mini-cluster, parallelism=1) producing exactly the
expected output shapes.
… 1.4 MEOSBridge

Introduce MEOSBridge as the runtime spatial-predicate surface for all
BerlinMOD-9 × 3-form streaming cells. The bridge calls into 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 — the fallback path is what the BerlinMODQ*LocalTest
mini-cluster drivers exercise (system property mobilityflink.meos.enabled=false).

- New berlinmod/MEOSBridge.java with the dwithinMetres /
  dwithinSegmentMetres / distanceMetres surface and a fail-soft
  static init that flips MEOS_AVAILABLE to false on UnsatisfiedLinkError.
- All BerlinMOD-9 × 3-form spatial predicates rewritten to call
  MEOSBridge instead of Haversine / SegmentDistance directly. 27 cells,
  one bridge call surface, identical predicate semantics.
- JMEOS.jar updated to the JMEOS#15 regen branch artefact (478 305
  bytes); this is the JMEOS 1.4 regen build that exposes geog_dwithin /
  geom_in / geom_to_geog / edwithin_tgeo_geo / nad_tgeo_geo / tpoint_length.
- aisdata/Main.java and aisdata/TrajectoryWindowFunction.java adapted
  to the JMEOS 1.4 meos_initialize() / meos_initialize_timezone()
  split (the old two-arg meos_initialize(String, error_handler_fn)
  signature is gone in JMEOS#15).
- All nine BerlinMODQ*LocalTest mini-cluster drivers set
  mobilityflink.meos.enabled=false at main() entry so they remain
  green-CI without libmeos.so on the runtime path.
- target/ build artefacts gitignored.

The README's spatial-predicate paragraph is updated to describe the
MEOSBridge route as the production path; the TODO(meos) markers across
the BerlinMOD cells are gone.

Build: mvn clean package -DskipTests green.
Verify: BerlinMODQ{1,3,5,8}LocalTest all finish with FINISHED state
on the mini-cluster fallback path.
@estebanzimanyi estebanzimanyi force-pushed the feat/jmeos-bridge-swap branch from a77ad8d to cf22d65 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 `flink-processor/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 built by:

    mvn -pl codegen,jmeos-core compile -Dmaven.test.skip=true
    cd jmeos-core/target/classes && jar cf JMEOS.jar .

Unblocks codegen/flink-meos-ops wedge stacked on this branch.
@estebanzimanyi estebanzimanyi force-pushed the feat/jmeos-bridge-swap branch from 0a57c07 to 6676bbb 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