Skip to content

Commit

Permalink
Fix kryo issues in native
Browse files Browse the repository at this point in the history
  • Loading branch information
awelless committed Oct 2, 2023
1 parent affd0d9 commit 31ec1f1
Show file tree
Hide file tree
Showing 20 changed files with 189 additions and 94 deletions.
4 changes: 2 additions & 2 deletions admin-console-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package io.mailit.admin.console.http.dto

import io.mailit.core.model.ApiKey
import io.quarkus.runtime.annotations.RegisterForReflection
import java.time.Instant

@RegisterForReflection
data class ApiKeyDto(
val id: String,
val name: String,
val createdAt: Instant,
val expiresAt: Instant,
)

@RegisterForReflection
data class ApiKeyTokenDto(val token: String)

data class CreateApiKeyDto(
val name: String,
val expirationDays: Int,
)

data class ApiKeyTokenDto(val token: String)

fun ApiKey.toDto() = ApiKeyDto(
id = id,
name = name,
Expand Down
3 changes: 3 additions & 0 deletions connector/http/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ info:
name: MIT
url: https://opensource.org/license/mit/
version: 0.2.0
servers:
- url: http://localhost:8080
description: Dev server
paths:
/api/connector/mail:
post:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface MailMessageService {

data class CreateMailCommand(
val text: String?,
val data: Map<String, Any?>?,
val data: Map<String, Any>?,
val subject: String?,
val emailFrom: String?,
val emailTo: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ data class MailMessage(
/**
* Data that is substituted in the template in [HtmlMailMessageType]
*/
val data: Map<String, Any?>?,
val data: Map<String, Any>?,

val subject: String?,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ interface TemplateProcessor {
/**
* Merges [HtmlMailMessageType.template] and [data]. Returns html message
*/
fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String
suspend fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String
}

class TemplateProcessorManager(
private val noneTemplateProcessor: NoneTemplateProcessor,
private val freemarkerTemplateProcessor: FreemarkerTemplateProcessor,
) : TemplateProcessor {

override fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String =
override suspend fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String =
when (mailMessageType.templateEngine) {
NONE -> noneTemplateProcessor.process(mailMessageType, data)
FREEMARKER -> freemarkerTemplateProcessor.process(mailMessageType, data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import freemarker.template.Configuration
import io.mailit.core.model.HtmlMailMessageType
import io.mailit.core.service.mail.sending.templates.TemplateProcessor
import java.io.StringWriter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class FreemarkerTemplateProcessor(
private val configuration: Configuration,
) : TemplateProcessor {

override fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String {
val template = configuration.getTemplate(mailMessageType.name)
override suspend fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String {
val template = withContext(Dispatchers.IO) { configuration.getTemplate(mailMessageType.name) }

val writer = StringWriter()
template.process(data, writer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import io.mailit.core.service.mail.sending.templates.TemplateProcessor
*/
class NoneTemplateProcessor : TemplateProcessor {

override fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String = mailMessageType.template.value
override suspend fun process(mailMessageType: HtmlMailMessageType, data: Map<String, Any?>): String = mailMessageType.template.value
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class MailFactory(
private const val MESSAGE_ID_HEADER = "Message-ID"
}

fun create(mailMessage: MailMessage): Mail {
suspend fun create(mailMessage: MailMessage): Mail {
val mail = when (val type = mailMessage.type) {
is PlainTextMailMessageType -> plainTextMessage(mailMessage)
is HtmlMailMessageType -> htmlMessage(mailMessage, type)
Expand All @@ -32,7 +32,7 @@ class MailFactory(
private fun plainTextMessage(mailMessage: MailMessage) =
Mail.withText(mailMessage.emailTo, mailMessage.subject, mailMessage.text)

private fun htmlMessage(mailMessage: MailMessage, mailMessageType: HtmlMailMessageType): Mail {
private suspend fun htmlMessage(mailMessage: MailMessage, mailMessageType: HtmlMailMessageType): Mail {
val htmlMessage = templateProcessor.process(
mailMessageType = mailMessageType,
data = mailMessage.data.orEmpty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import io.mailit.core.model.HtmlTemplateEngine.FREEMARKER
import io.mailit.test.assertHtmlEquals
import io.mailit.test.createHtmlMailMessageType
import io.mailit.test.readResource
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
Expand All @@ -32,7 +33,7 @@ open class FreemarkerTemplateProcessorTest {
}

@Test
fun `process valid template - creates html`() {
fun `process valid template - creates html`() = runTest {
// given
templateLoader.putTemplate(mailMessageType.name, FREEMARKER_TEST_TEMPLATE_PATH.readResource())

Expand Down Expand Up @@ -71,7 +72,7 @@ open class FreemarkerTemplateProcessorTest {
}

@Test
fun `process valid template with excess data - creates html`() {
fun `process valid template with excess data - creates html`() = runTest {
// given
templateLoader.putTemplate(mailMessageType.name, FREEMARKER_TEST_TEMPLATE_PATH.readResource())

Expand Down Expand Up @@ -112,7 +113,7 @@ open class FreemarkerTemplateProcessorTest {
}

@Test
fun `process valid template when some data is not present - throws exception`() {
fun `process valid template when some data is not present - throws exception`() = runTest {
// given
templateLoader.putTemplate(mailMessageType.name, FREEMARKER_TEST_TEMPLATE_PATH.readResource())

Expand All @@ -125,12 +126,12 @@ open class FreemarkerTemplateProcessorTest {
}

@Test
fun `template doesn't exist - throws exception`() {
fun `template doesn't exist - throws exception`() = runTest {
assertThrows<TemplateNotFoundException> { templateProcessor.process(mailMessageType, emptyMap()) }
}

@Test
fun `template is invalid - throws exception`() {
fun `template is invalid - throws exception`() = runTest {
// given
templateLoader.putTemplate(mailMessageType.name, FREEMARKER_INVALID_TEMPLATE_PATH.readResource())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import io.mailit.core.service.mail.sending.templates.TemplateProcessor
import io.mailit.test.createHtmlMailMessageType
import io.mailit.test.createMailMessage
import io.mailit.test.createPlainMailMessageType
import io.mockk.every
import io.mockk.coEvery
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.junit5.MockKExtension
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -26,7 +27,7 @@ class MailFactoryTest {
lateinit var mailFactory: MailFactory

@Test
fun create_plainTextMessage() {
fun create_plainTextMessage() = runTest {
// given
val plainMessageType = createPlainMailMessageType()
val message = createMailMessage(plainMessageType)
Expand All @@ -43,14 +44,14 @@ class MailFactoryTest {
}

@Test
fun create_htmlMessage() {
fun create_htmlMessage() = runTest {
// given
val htmlMessageType = createHtmlMailMessageType()
val message = createMailMessage(htmlMessageType)

val messageHtml = "<html><body> message </body></html>"

every { templateProcessor.process(htmlMessageType, message.data.orEmpty()) } returns messageHtml
coEvery { templateProcessor.process(htmlMessageType, message.data.orEmpty()) } returns messageHtml

// when
val actual = mailFactory.create(message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import io.restassured.module.kotlin.extensions.Given
import io.restassured.module.kotlin.extensions.Then
import io.restassured.module.kotlin.extensions.When
import jakarta.inject.Inject
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.jboss.resteasy.reactive.RestResponse.StatusCode.ACCEPTED
Expand Down Expand Up @@ -75,7 +75,11 @@ class HttpConnectorSecurityTest {

@Test
fun `sendMail with expired api key`() = runTest {
val expiredToken = apiKeyService.generate(CreateApiKeyCommand(name = "expired-api-key", expiration = Duration.ZERO))
val command = CreateApiKeyCommand(
name = "expired-api-key",
expiration = (-10).seconds, // Negative duration, so the expiration will be in the past.
)
val expiredToken = apiKeyService.generate(command)

Given {
contentType(JSON)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.esotericsoftware.kryo.serializers.CollectionSerializer
import com.esotericsoftware.kryo.serializers.DefaultArraySerializers
import com.esotericsoftware.kryo.serializers.DefaultSerializers
import com.esotericsoftware.kryo.serializers.MapSerializer
import io.mailit.persistence.common.serialization.KryoMailMessageDataSerializer
import io.mailit.persistence.common.serialization.kryo.KryoMailMessageDataSerializer
import io.quarkus.runtime.annotations.RegisterForReflection
import jakarta.inject.Singleton

Expand Down Expand Up @@ -52,7 +52,7 @@ import jakarta.inject.Singleton
DefaultSerializers.KryoSerializableSerializer::class,
],
)
class SerializationConfiguration {
internal class SerializationConfiguration {

@Singleton
fun kryoMailMessageDataSerializer() = KryoMailMessageDataSerializer()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.mailit.persistence.common.serialization

interface MailMessageDataSerializer {

fun write(data: Map<String, Any?>?): ByteArray
fun write(data: Map<String, Any>?): ByteArray?

fun read(bytes: ByteArray?): Map<String, Any?>?
fun read(bytes: ByteArray?): Map<String, Any>?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.mailit.persistence.common.serialization.kryo

import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output

internal object MailDataMapSerializer : Serializer<Map<String, Any>>() {

override fun write(kryo: Kryo, output: Output, map: Map<String, Any>) {
val size = map.size
output.writeVarInt(size, true)

map.forEach { (key, value) ->
output.writeString(key)
kryo.writeClassAndObject(output, value)
}
}

override fun read(kryo: Kryo, input: Input, type: Class<out Map<String, Any>>): Map<String, Any> {
val size = input.readVarInt(true)

val map = HashMap<String, Any>(size)

for (i in 1..size) {
val key = input.readString()
val value = kryo.readClassAndObject(input)
map[key] = value
}

return map
}
}

internal object MailDataCollectionSerializer : Serializer<Collection<Any>>() {

override fun write(kryo: Kryo, output: Output, collection: Collection<Any>) {
val size = collection.size
output.writeVarInt(size, true)

collection.forEach { kryo.writeClassAndObject(output, it) }
}

override fun read(kryo: Kryo, input: Input, type: Class<out Collection<Any>>): Collection<Any> {
val size = input.readVarInt(true)

val collection = ArrayList<Any>(size)

for (i in 1..size) {
collection += kryo.readClassAndObject(input)
}

return collection
}
}
Loading

0 comments on commit 31ec1f1

Please sign in to comment.