M25 · Build the core everywhere Kotlin does - #64
Merged
Conversation
kdrant-core now compiles for the JVM, for JS, and for nine Kotlin/Native targets. What made that a two-file change rather than a rewrite is the transport seam: the models, the DSLs, the error hierarchy and the client logic never knew there was a wire, so moving them into commonMain was a git mv and the compiler had nothing to complain about. The issue named four things to fix. Two of them were already gone. java.util.UUID and java.time.Instant do not appear in the core at all: a point id is a ULong or a string, and a datetime bound is the RFC 3339 text Qdrant parses, so neither ever needed a JVM type. Saying so is more useful than quietly not doing it. The third was real and is the one declaration this migration had to split. Only the JVM publishes an IO dispatcher, which is the right default for a client that blocks on a socket rather than on a CPU. Kotlin/Native has one and the coroutines library still keeps it internal; Kotlin/JS has a single-threaded runtime and nothing to move off it. Both get Default, and the KDoc says which reason applies where. Passing your own dispatcher works as it always did. The fourth, parameterising the Ktor engine per target, is not here and should not be: Ktor CIO and grpc-java are both JVM-only, so the engines stay JVM-only and a multiplatform consumer shares its models and its query building and supplies its own transport. Publishing a common engine would mean picking a Ktor engine per target and testing it there, which is its own piece of work and not what this milestone's exit criterion asks for. The exit criterion is met on both halves. commonMain builds for every target, which is the compiler's own proof that no java.* survives on the common path. And the JVM api dump is unchanged byte for byte, so the artifact stays source-compatible. The artifact layout does change, and that is the reason this is 2.0 rather than a minor. kdrant-core carries Gradle module metadata now and the JVM classes live in kdrant-core-jvm. Gradle reads the metadata and resolves the variant, so a Gradle build sees nothing; Maven does not, and a Maven build naming kdrant-core would get no classes. The BOM constrains both, and STABILITY.md says so where a reader will look. Three build surfaces move with it. Releases are built on macOS, because no Linux host compiles the Apple targets and one that skipped them would publish a release quietly missing its iOS klibs. CI gains a macOS job for the same reason: without it that break would first be seen at release. And the javadoc jar holds Dokka's HTML, because the Dokka Javadoc generator refuses a multiplatform project outright and Maven Central asks for a jar rather than for Javadoc. The existing eighty tests stay on the JVM, where JUnit 5 and kotest-property live. Rewriting them to kotlin.test would run the same assertions in more places against platform-independent code. What runs everywhere instead is a suite aimed at what could actually differ: the hand-written serializers, a point id above Long.MAX, an integer payload value above 2^53 where a JS number would lose it, and the config's own validation.
Dependency review failed the multiplatform branch on a high-severity advisory in brace-expansion, reached through kotlin-js-store/yarn.lock — the lockfile the Kotlin/JS target's Karma and webpack test tooling needs. Nothing published contains that package, so the finding could have been suppressed. It is a better question than that. kdrant-core on JS is models, a DSL and a transport interface with no implementation behind it: Ktor CIO and grpc-java are both JVM-only, so there is nothing on that target to send a request with. The target was carrying the repository's only npm dependency graph in exchange for a library nobody can currently use. The eight native targets stay, and they are the ones the migration was for: an Android application and an iOS application sharing their models and their query building. One line brings JS back the day someone writes an engine for it.
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.
Closes #23. #63 is merged and this branch carries it, so the diff below is the multiplatform work alone.
kdrant-corenow compiles for the JVM and for eight Kotlin/Native targets:iosArm64,iosSimulatorArm64,iosX64,macosArm64,macosX64,linuxArm64,linuxX64,mingwX64. What madethat a two-file change rather than a rewrite is the transport seam: the models, DSLs, error hierarchy
and client logic never knew there was a wire, so moving them into
commonMainwas agit mvand thecompiler had nothing to say.
Kotlin/JS was added and then dropped. Dependency review failed the branch on a high-severity
advisory in
brace-expansion, reached through theyarn.lockthat the JS target's Karma and webpacktest tooling needs. Nothing published contains that package, so the finding could have been suppressed.
It is a better question than that:
kdrant-coreon JS is models, a DSL and a transport interface withno implementation behind it, because Ktor CIO and grpc-java are both JVM-only. The target was carrying
the repository's only npm dependency graph in exchange for a library nobody can currently use. One line
brings it back the day someone writes a JS engine.
Against the exit criterion — "kdrant-core builds for commonMain with no
java.*on the commonpath, and the JVM artifact stays source-compatible":
commonMaincompiles for all nine targets. That is the compiler's own proof aboutjava.*; there isnothing to grep for.
apiCheckreports no diff.Two of the four items in the issue were already done.
java.util.UUIDandjava.time.Instantdonot appear in the core at all — a point id is a
ULongor a string, and a datetime bound is the RFC3339 text Qdrant parses — so neither ever needed a JVM type.
The third was real and is the one declaration this migration had to split. Only the JVM publishes an
IO dispatcher, which is the right default for a client that blocks on a socket rather than a CPU.
Kotlin/Native has one that the coroutines library still keeps internal, so it gets
Dispatchers.Defaultand the KDoc says why. Passing your own dispatcher works as before.
The fourth is deliberately not here. "The Ktor engine parameterised per target" would mean picking
and testing a Ktor engine per platform. The engines stay JVM-only; a multiplatform consumer shares its
models and query building and supplies its own transport. That is its own piece of work, and the exit
criterion is about the core.
The artifact layout changes, and it is why this is 2.0 and not a minor.
kdrant-corenow carriesGradle module metadata and the JVM classes live in
kdrant-core-jvm. A Gradle build resolves thevariant from the same coordinate and sees nothing; a Maven build naming
kdrant-coregets no classes.The BOM constrains both and
STABILITY.mdsays so.Three build surfaces move with it.
macos-latest. No Linux host compiles the Apple targets, and one that skipped themwould publish a release quietly missing its iOS klibs. The linked-artifacts step also learns that the
JVM jar is now
kdrant-core-jvm-<version>.jar, which it would otherwise fail to find.Apple targetsjob on macOS, for the same reason: without it an iOS break is first seenat release.
kdrant-core's-javadoc.jarholds Dokka HTML. The Dokka Javadoc generator refuses a multiplatformproject outright, and Maven Central asks for a jar rather than for Javadoc.
Tests. The existing eighty stay on the JVM, where JUnit 5 and kotest-property live; rewriting them
to
kotlin.testwould run the same assertions in more places against platform-independent code. Whatruns everywhere instead is a
commonTestsuite aimed at what could actually differ: the hand-writtenserializers, a point id above
Long.MAX_VALUE, an integer payload value above 2^53, and the config'svalidation. Verified locally on the JVM,
linuxX64,macosArm64andiosSimulatorArm64.