From b702023698e4b351d97ac590dc5cf9338d2c058f Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Wed, 1 Jan 2025 22:26:27 +0400 Subject: [PATCH 1/2] Add notes about thread-safety for public API --- README.md | 5 +++++ .../io/github/optimumcode/json/schema/AnnotationKey.kt | 2 +- .../io/github/optimumcode/json/schema/FormatValidator.kt | 5 ++++- .../io/github/optimumcode/json/schema/JsonSchemaLoader.kt | 8 ++++++++ .../io/github/optimumcode/json/schema/OutputCollector.kt | 4 +++- .../io/github/optimumcode/json/schema/ValidationOutput.kt | 2 +- .../json/schema/extension/ExternalAssertion.kt | 3 +++ .../io/github/optimumcode/json/schema/model/Model.kt | 2 ++ 8 files changed, 27 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 67f9a9a6..483f8e05 100644 --- a/README.md +++ b/README.md @@ -351,6 +351,11 @@ val valid = schema.validate(elementToValidate, errors::add) | | not | Supported | +## Thread safety + +All public API is thread-safe unless stated otherwise. +Please, read the documentation for each class/interface carefully before using an instance from different threads. + ## Format assertion The library supports `format` assertion. diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/AnnotationKey.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/AnnotationKey.kt index cd15b0d2..f6363346 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/AnnotationKey.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/AnnotationKey.kt @@ -14,7 +14,7 @@ import kotlin.reflect.KClass *} * ``` */ -public sealed class AnnotationKey private constructor( +public sealed class AnnotationKey( private val name: String, internal val type: KClass, ) { diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/FormatValidator.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/FormatValidator.kt index 6351a596..d74cbfbb 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/FormatValidator.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/FormatValidator.kt @@ -7,7 +7,10 @@ import kotlin.jvm.JvmStatic * The [FormatValidator] is used to check whether the [AbstractElement] matches the expected format. * If the [AbstractElement] is not of the required type * (e.g. validator expects string but the [AbstractElement] is an object) - * the validator **MUST** return [FormatValidator.Valid] result + * the validator **MUST** return [FormatValidator.Valid] result. + * + * If you create an implementation of [FormatValidator] that will be shared with others + * please make sure that it will be state-less since it might be invoked from different threads. */ @ExperimentalApi public interface FormatValidator { diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/JsonSchemaLoader.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/JsonSchemaLoader.kt index 06005cf3..ac248971 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/JsonSchemaLoader.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/JsonSchemaLoader.kt @@ -16,6 +16,9 @@ import io.github.optimumcode.json.schema.internal.wellknown.Draft7 import kotlinx.serialization.json.JsonElement import kotlin.jvm.JvmStatic +/** + * By default, implementations of [JsonSchemaLoader] are NOT thread-safe + */ @Suppress("detekt:TooManyFunctions") public interface JsonSchemaLoader { public fun registerWellKnown(draft: SchemaType): JsonSchemaLoader = @@ -119,6 +122,11 @@ public interface JsonSchemaLoader { ): JsonSchema public companion object { + /** + * Creates an instance of [JsonSchemaLoader]. + * + * @return implementation of [JsonSchemaLoader]. The implementation is **NOT thread-safe**. + */ @JvmStatic public fun create(): JsonSchemaLoader = SchemaLoader() } diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/OutputCollector.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/OutputCollector.kt index 32daeb1b..5acd758c 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/OutputCollector.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/OutputCollector.kt @@ -13,8 +13,10 @@ private val NO_TRANSFORMATION: OutputErrorTransformer<*> = { it } /** * Provides collectors' implementations for outputs * defined in [draft 2020-12](https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01#section-12.4) + * + * **The implementations of [OutputCollector] are NOT thread-safe**. */ -public sealed class OutputCollector private constructor( +public sealed class OutputCollector( parent: OutputCollector? = null, transformer: OutputErrorTransformer = NO_TRANSFORMATION, ) { diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/ValidationOutput.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/ValidationOutput.kt index 599af485..f618f117 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/ValidationOutput.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/ValidationOutput.kt @@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlin.jvm.JvmField -public sealed class ValidationOutput private constructor() { +public sealed class ValidationOutput { public abstract val valid: Boolean @Serializable diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertion.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertion.kt index 0785ea59..cfec4a6e 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertion.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertion.kt @@ -10,6 +10,9 @@ import kotlinx.serialization.json.JsonElement * This interface allows you to implement your own schema assertion. * This interface **does not** allow implementing custom applicators. * Only simple assertions (like: _format_, _type_) can be implemented. + * + * If you create an implementation of [ExternalAssertion] that will be shared with others + * please make sure that it will be state-less since it might be invoked from different threads. */ @Suppress("detekt:ForbiddenComment") @ExperimentalApi diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/model/Model.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/model/Model.kt index f97478df..6bd8acc4 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/model/Model.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/model/Model.kt @@ -7,6 +7,8 @@ import io.github.optimumcode.json.schema.ExperimentalApi * * [ObjectElement] - corresponds to a JSON/YAML object or [Map] * * [ArrayElement] - corresponds to a collection of [AbstractElement]s * * [PrimitiveElement] - corresponds to a scalar value (string, number, boolean) + * + * The implementations are NOT required to be thread-safe. */ @ExperimentalApi public sealed interface AbstractElement { From c67647493a6d27a33c0fc077b510d61b525c29bd Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Wed, 1 Jan 2025 22:27:47 +0400 Subject: [PATCH 2/2] Remove outdated comment --- .../json/schema/extension/ExternalAssertionFactory.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertionFactory.kt b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertionFactory.kt index efaf2e88..bbea7f63 100644 --- a/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertionFactory.kt +++ b/json-schema-validator/src/commonMain/kotlin/io/github/optimumcode/json/schema/extension/ExternalAssertionFactory.kt @@ -10,10 +10,6 @@ public interface ExternalAssertionFactory { * This keyword **must not** overlap with any existing keywords for existing drafts. * If keyword overlaps with any keyword for any existing draft and [IllegalStateException] will be thrown * when this factory is registered in [io.github.optimumcode.json.schema.JsonSchemaLoader]. - * - * NOTE: currently the library does not have **format** assertion implemented. But it will have. - * If you decide to implement it as an [ExternalAssertion] please be aware - * that one day this will cause an [IllegalStateException] as it was added to the library itself */ public val keywordName: String