0.7.0-SNAPSHOT: migration to kotlin 2.2.21, upgrade dependencies, IOS/MacOS compatibility for broken kotlin.time/kotlinx.datetime

This commit is contained in:
Sergey Chernov 2025-12-17 10:07:02 +01:00
parent bc46e11158
commit 7cec803174
11 changed files with 37 additions and 28 deletions

3
.idea/misc.xml generated
View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View File

@ -1,5 +1,8 @@
# Kiloparsec # Kiloparsec
> 0.7.0-SNAPSHOT is recommended for newer builds; due to extremely poor Kotlin time migration architecture, on Apple targets it is the only working version.
__Recommended version is `0.6.8`: to keep the code compatible with current and further versions we __Recommended version is `0.6.8`: to keep the code compatible with current and further versions we
ask to upgrade to `0.4.2` at least.__ Starting from this version some package names are changed for ask to upgrade to `0.4.2` at least.__ Starting from this version some package names are changed for
better clarity and fast UDP endpoints are added. better clarity and fast UDP endpoints are added.

View File

@ -11,15 +11,15 @@
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins { plugins {
kotlin("multiplatform") version "2.1.21" kotlin("multiplatform") version "2.2.21"
id("org.jetbrains.kotlin.plugin.serialization") version "2.1.21" id("org.jetbrains.kotlin.plugin.serialization") version "2.2.21"
id("com.android.library") version "8.5.2" apply true id("com.android.library") version "8.7.2" apply true
`maven-publish` `maven-publish`
id("org.jetbrains.dokka") version "1.9.20" id("org.jetbrains.dokka") version "1.9.20"
} }
group = "net.sergeych" group = "net.sergeych"
version = "0.6.10-SNAPSHOT" version = "0.7.0-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()
@ -30,11 +30,10 @@ repositories {
} }
kotlin { kotlin {
jvmToolchain(17) jvmToolchain(21)
jvm() jvm()
js { js {
browser { browser()
}
nodejs() nodejs()
} }
linuxX64() linuxX64()
@ -61,14 +60,16 @@ kotlin {
languageSettings.optIn("kotlinx.serialization.ExperimentalSerializationApi") languageSettings.optIn("kotlinx.serialization.ExperimentalSerializationApi")
languageSettings.optIn("kotlinx.coroutines.ExperimentalCoroutinesApi") languageSettings.optIn("kotlinx.coroutines.ExperimentalCoroutinesApi")
languageSettings.optIn("kotlin.ExperimentalUnsignedTypes") languageSettings.optIn("kotlin.ExperimentalUnsignedTypes")
languageSettings.optIn("kotlin.time.ExperimentalTime")
} }
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
api("io.ktor:ktor-client-core:$ktor_version") api("io.ktor:ktor-client-core:$ktor_version")
api("net.sergeych:crypto2:0.8.4") api("net.sergeych:crypto2:0.9.0")
} }
} }
val androidMain by getting { val androidMain by getting {
@ -85,8 +86,8 @@ kotlin {
val commonTest by getting { val commonTest by getting {
dependencies { dependencies {
implementation(kotlin("test")) implementation(kotlin("test"))
implementation("org.slf4j:slf4j-simple:2.0.9") implementation("org.slf4j:slf4j-simple:2.0.17")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.1") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2")
} }
} }
val ktorSocketTest by creating { val ktorSocketTest by creating {

View File

@ -11,5 +11,10 @@
kotlin.code.style=official kotlin.code.style=official
kotlin.mpp.applyDefaultHierarchyTemplate=false kotlin.mpp.applyDefaultHierarchyTemplate=false
kotlin.daemon.jvmargs=-Xmx2048m kotlin.daemon.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
kotlin.native.ignoreDisabledTargets=true kotlin.native.ignoreDisabledTargets=true
org.gradle.parallel=true
org.gradle.configuration-cache=true
org.gradle.caching=true

View File

@ -10,6 +10,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -15,12 +15,11 @@ import kotlinx.serialization.Serializable
import net.sergeych.bintools.toDataSource import net.sergeych.bintools.toDataSource
import net.sergeych.bipack.BipackDecoder import net.sergeych.bipack.BipackDecoder
import net.sergeych.bipack.BipackEncoder import net.sergeych.bipack.BipackEncoder
import net.sergeych.kiloparsec.Command.Call
import net.sergeych.kiloparsec.Command.Companion.unpackCall import net.sergeych.kiloparsec.Command.Companion.unpackCall
import net.sergeych.utools.unpack import net.sergeych.utools.unpack
/** /**
* Typesafe command definition. Command is a universal entity in Divan: it is used * Typesafe command definition. Command is a universal entity in kiloparsec (and also diwan): it is used
* in node-2-node protocols and client API, and most importantly in calling smart contract * in node-2-node protocols and client API, and most importantly in calling smart contract
* methods. This is essentially a Kotlin binding to typesafe serialize command calls and * methods. This is essentially a Kotlin binding to typesafe serialize command calls and
* deserialize results. * deserialize results.

View File

@ -27,13 +27,12 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.serializer import kotlinx.serialization.serializer
import net.sergeych.bipack.Unsigned import net.sergeych.bipack.Unsigned
import net.sergeych.crypto2.toDump import net.sergeych.crypto2.toDump
import net.sergeych.kiloparsec.Transport.Device
import net.sergeych.mp_logger.* import net.sergeych.mp_logger.*
import net.sergeych.utools.pack import net.sergeych.utools.pack
import net.sergeych.utools.unpack import net.sergeych.utools.unpack
/** /**
* Divan channel that operates some block [Device] exporting a given [localInterface] * Kiloparsec channel that operates some block [Device] exporting a given [localInterface]
* to remote callers. [LocalInterface] allows session managing, transmitting exceptions * to remote callers. [LocalInterface] allows session managing, transmitting exceptions
* in a scure and multiplatform way and provide local command execution (typed RPC) * in a scure and multiplatform way and provide local command execution (typed RPC)
*/ */
@ -251,7 +250,7 @@ class Transport<S>(
} catch (cce: LocalInterface.BreakConnectionException) { } catch (cce: LocalInterface.BreakConnectionException) {
info { "closing connection by local request ($cce)" } info { "closing connection by local request ($cce)" }
device.close() device.close()
} catch (t: RemoteInterface.ClosedException) { } catch (_: RemoteInterface.ClosedException) {
// it is ok: we just exit the coroutine normally // it is ok: we just exit the coroutine normally
// and mark we're closing // and mark we're closing
isClosed = true isClosed = true

View File

@ -9,7 +9,6 @@
*/ */
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import net.sergeych.bipack.BipackEncoder import net.sergeych.bipack.BipackEncoder
import net.sergeych.crypto2.initCrypto import net.sergeych.crypto2.initCrypto
import net.sergeych.kiloparsec.KiloParams import net.sergeych.kiloparsec.KiloParams
@ -21,6 +20,7 @@ import kotlin.test.Test
import kotlin.test.assertContentEquals import kotlin.test.assertContentEquals
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.microseconds import kotlin.time.Duration.Companion.microseconds
import kotlin.time.Instant
class PackTest { class PackTest {
inline fun <reified T>check(x: T?) { inline fun <reified T>check(x: T?) {

View File

@ -76,7 +76,8 @@ class TransportTest {
"p2: $it" "p2: $it"
} }
on(cmdSlow) { on(cmdSlow) {
delay(100) // the problem: runTest() breaks delays so it is not enough
for( i in 0..10000) delay(1)
"done" "done"
} }
} }

View File

@ -22,11 +22,11 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.datetime.Clock
import net.sergeych.kiloparsec.* import net.sergeych.kiloparsec.*
import net.sergeych.mp_logger.* import net.sergeych.mp_logger.*
import net.sergeych.mp_tools.globalLaunch import net.sergeych.mp_tools.globalLaunch
import net.sergeych.tools.AtomicCounter import net.sergeych.tools.AtomicCounter
import kotlin.time.Clock
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
private val logCounter = AtomicCounter(0) private val logCounter = AtomicCounter(0)
@ -140,7 +140,7 @@ private fun inetTransportDevice(
sockInput.readFully(data, 0, size) sockInput.readFully(data, 0, size)
inputBlocks.send(data.toUByteArray()) inputBlocks.send(data.toUByteArray())
} }
} catch (e: ClosedReceiveChannelException) { } catch (_: ClosedReceiveChannelException) {
log.error { "closed receive channel " } log.error { "closed receive channel " }
stop() stop()
break break

View File

@ -19,13 +19,13 @@ import kotlinx.coroutines.channels.ClosedSendChannelException
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import net.sergeych.kiloparsec.SyncValue import net.sergeych.kiloparsec.SyncValue
import net.sergeych.mp_logger.Log import net.sergeych.mp_logger.Log
import net.sergeych.mp_logger.Loggable import net.sergeych.mp_logger.Loggable
import net.sergeych.mp_logger.debug import net.sergeych.mp_logger.debug
import net.sergeych.mp_logger.exception import net.sergeych.mp_logger.exception
import net.sergeych.mp_tools.globalLaunch import net.sergeych.mp_tools.globalLaunch
import kotlin.time.Clock
import kotlin.time.Duration import kotlin.time.Duration
/** /**
@ -171,10 +171,10 @@ internal class UdpSocketTransport(
while (!isClosed) { while (!isClosed) {
try { try {
server.sendBlock(UdpBlock.Data(outputDataBlocks.receive()), socketAddress) server.sendBlock(UdpBlock.Data(outputDataBlocks.receive()), socketAddress)
} catch (e: CancellationException) { } catch (_: CancellationException) {
// this is ok // this is ok
break break
} catch (e: ClosedReceiveChannelException) { } catch (_: ClosedReceiveChannelException) {
debug { "input channel is closed, closing" } debug { "input channel is closed, closing" }
close() close()
break break