diff --git a/build.gradle.kts b/build.gradle.kts index e324753a..83910384 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -113,10 +113,6 @@ dependencies { compileOnly("io.swagger.core.v3:swagger-annotations:2.2.6") implementation("io.swagger.core.v3:swagger-models:2.2.6") implementation("org.jetbrains.exposed:exposed-java-time:$exposed_version") - implementation("org.jetbrains.exposed:spring-transaction:$exposed_version") - implementation("org.springframework.data:spring-data-commons") - implementation("org.springframework.boot:spring-boot-starter-jdbc") - implementation("org.springframework.boot:spring-boot-starter-data-jdbc") testImplementation("org.springframework.boot:spring-boot-test-autoconfigure") testImplementation("org.springframework.boot:spring-boot-starter-test") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") diff --git a/src/main/kotlin/dev/usbharu/hideout/SpringApplication.kt b/src/main/kotlin/dev/usbharu/hideout/SpringApplication.kt index d050b856..bbc2e3bd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/SpringApplication.kt +++ b/src/main/kotlin/dev/usbharu/hideout/SpringApplication.kt @@ -3,9 +3,11 @@ package dev.usbharu.hideout import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.context.properties.ConfigurationPropertiesScan import org.springframework.boot.runApplication +import org.springframework.cache.annotation.EnableCaching @SpringBootApplication @ConfigurationPropertiesScan +@EnableCaching class SpringApplication @Suppress("SpreadOperator") diff --git a/src/main/kotlin/dev/usbharu/hideout/config/HttpClientConfig.kt b/src/main/kotlin/dev/usbharu/hideout/config/HttpClientConfig.kt index 2110618d..454a4de6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/config/HttpClientConfig.kt +++ b/src/main/kotlin/dev/usbharu/hideout/config/HttpClientConfig.kt @@ -20,7 +20,8 @@ class HttpClientConfig { } install(Logging) { logger = Logger.DEFAULT - level = LogLevel.ALL + level = LogLevel.INFO + } expectSuccess = true } diff --git a/src/main/kotlin/dev/usbharu/hideout/controller/InboxControllerImpl.kt b/src/main/kotlin/dev/usbharu/hideout/controller/InboxControllerImpl.kt index d65560d0..a79ce5b0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/controller/InboxControllerImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/controller/InboxControllerImpl.kt @@ -2,6 +2,7 @@ package dev.usbharu.hideout.controller import dev.usbharu.hideout.service.ap.APService import kotlinx.coroutines.runBlocking +import org.slf4j.LoggerFactory import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody @@ -11,7 +12,12 @@ import org.springframework.web.bind.annotation.RestController class InboxControllerImpl(private val apService: APService) : InboxController { override fun inbox(@RequestBody string: String): ResponseEntity = runBlocking { val parseActivity = apService.parseActivity(string) + LOGGER.info("INBOX Processing Activity Type: {}", parseActivity) apService.processActivity(string, parseActivity) ResponseEntity(HttpStatus.ACCEPTED) } + + companion object { + val LOGGER = LoggerFactory.getLogger(InboxControllerImpl::class.java) + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonAppsApiController.kt b/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonAppsApiController.kt index 44d9582a..2b37eb9a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonAppsApiController.kt +++ b/src/main/kotlin/dev/usbharu/hideout/controller/mastodon/MastodonAppsApiController.kt @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.RequestParam @Controller class MastodonAppsApiController(private val appApiService: AppApiService) : AppApi { override fun apiV1AppsPost(appsRequest: AppsRequest): ResponseEntity = runBlocking { - println(appsRequest) ResponseEntity( appApiService.createApp(appsRequest), HttpStatus.OK diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserDetailsImpl.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserDetailsImpl.kt index 2a3c808c..6eb655bc 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserDetailsImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserDetailsImpl.kt @@ -51,7 +51,6 @@ class UserDetailsDeserializer : JsonDeserializer() { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): UserDetailsImpl { val mapper = p.codec as ObjectMapper val jsonNode: JsonNode = mapper.readTree(p) - println(jsonNode) val authorities: Set = mapper.convertValue( jsonNode["authorities"], SIMPLE_GRANTED_AUTHORITY_SET diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt index 80a282aa..482ef329 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt @@ -54,7 +54,6 @@ open class Object : JsonLd { class TypeSerializer : JsonSerializer>() { override fun serialize(value: List?, gen: JsonGenerator?, serializers: SerializerProvider?) { - println(value) if (value?.size == 1) { gen?.writeString(value[0]) } else { diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt index 72fabd37..c6a330c2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt @@ -34,7 +34,6 @@ class ObjectDeserializer : JsonDeserializer() { return when (activityType) { ExtendedActivityVocabulary.Follow -> { val readValue = p.codec.treeToValue(treeNode, Follow::class.java) - println(readValue) readValue } diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Timeline.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Timeline.kt index 64f450a8..e4aeabb6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Timeline.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/Timeline.kt @@ -1,7 +1,9 @@ package dev.usbharu.hideout.domain.model.hideout.entity import org.springframework.data.annotation.Id +import org.springframework.data.mongodb.core.mapping.Document +@Document data class Timeline( @Id val id: Long, diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt index bed7c761..01ed970e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt @@ -67,11 +67,9 @@ val httpSignaturePlugin: ClientPlugin = createClientP request.header("Date", format.format(Date())) request.header("Host", request.url.host) - println(request.bodyType) - println(request.bodyType?.type) if (request.bodyType?.type == String::class) { - println(body as String) - println("Digest !!") + body as String + // UserAuthService.sha256.reset() val digest = Base64.getEncoder().encodeToString(UserAuthServiceImpl.sha256.digest(body.toByteArray(Charsets.UTF_8))) diff --git a/src/main/kotlin/dev/usbharu/hideout/query/PostQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/query/PostQueryServiceImpl.kt index 8e8ead0b..dc3d3d9a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/query/PostQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/query/PostQueryServiceImpl.kt @@ -6,25 +6,24 @@ import dev.usbharu.hideout.repository.Posts import dev.usbharu.hideout.repository.PostsMedia import dev.usbharu.hideout.repository.toPost import dev.usbharu.hideout.util.singleOr -import org.jetbrains.exposed.sql.innerJoin import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @Repository class PostQueryServiceImpl : PostQueryService { override suspend fun findById(id: Long): Post = - Posts.innerJoin(PostsMedia, onColumn = { Posts.id }, otherColumn = { PostsMedia.postId }) + Posts.leftJoin(PostsMedia) .select { Posts.id eq id } .singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) }.toPost() override suspend fun findByUrl(url: String): Post = - Posts.innerJoin(PostsMedia, onColumn = { Posts.id }, otherColumn = { PostsMedia.postId }) + Posts.leftJoin(PostsMedia) .select { Posts.url eq url } .toPost() .singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) } override suspend fun findByApId(string: String): Post = - Posts.innerJoin(PostsMedia, onColumn = { Posts.id }, otherColumn = { PostsMedia.postId }) + Posts.leftJoin(PostsMedia) .select { Posts.apId eq string } .toPost() .singleOr { FailedToGetResourcesException("apId: $string is duplicate or does not exist.", it) } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index 400126ea..f179ce7f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -54,6 +54,12 @@ class PostRepositoryImpl(private val idGenerateService: IdGenerateService) : Pos it[apId] = post.apId } } + + + assert(Posts.select { Posts.id eq post.id }.singleOrNull() != null) { + "Faild to insert" + } + return post } @@ -109,5 +115,5 @@ fun ResultRow.toPost(): Post { fun Query.toPost(): List { return this.groupBy { it[Posts.id] } .map { it.value } - .map { it.first().toPost().copy(mediaIds = it.map { it[PostsMedia.mediaId] }) } + .map { it.first().toPost().copy(mediaIds = it.mapNotNull { it.getOrNull(PostsMedia.mediaId) }) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt index 5bfa479f..10fb3a2e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt @@ -14,8 +14,8 @@ class UserRepositoryImpl(private val idGenerateService: IdGenerateService) : UserRepository { override suspend fun save(user: User): User { - val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull() - if (singleOrNull == null) { + val singleOrNull = Users.select { Users.id eq user.id or (Users.url eq user.url) }.empty() + if (singleOrNull) { Users.insert { it[id] = user.id it[name] = user.name diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt index 089f8b50..c6173127 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt @@ -26,7 +26,7 @@ class APLikeServiceImpl( val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null") val content = like.content ?: throw IllegalActivityPubObjectException("content is null") like.`object` ?: throw IllegalActivityPubObjectException("object is null") - transaction.transaction(java.sql.Connection.TRANSACTION_SERIALIZABLE) { + transaction.transaction { val person = apUserService.fetchPersonWithEntity(actor) apNoteService.fetchNote(like.`object` ?: return@transaction) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt index 146a70de..b52f8eb3 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt @@ -226,8 +226,6 @@ class APServiceImpl( override suspend fun processActivity(job: JobContextWithProps, hideoutJob: HideoutJob) { logger.debug("processActivity: ${hideoutJob.name}") -// println(apReceiveFollowService::class.java) -// apReceiveFollowService.receiveFollowJob(job.props as JobProps) when (hideoutJob) { is ReceiveFollowJob -> { apReceiveFollowService.receiveFollowJob( diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/StatusesApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/StatusesApiService.kt index 039dfc2c..2baae425 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/StatusesApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/mastodon/StatusesApiService.kt @@ -39,7 +39,6 @@ class StatsesApiServiceImpl( statusesRequest: dev.usbharu.hideout.domain.model.mastodon.StatusesRequest, userId: Long ): Status = transaction.transaction { - println("Post status media ids " + statusesRequest.media_ids) val visibility = when (statusesRequest.visibility) { StatusesRequest.Visibility.public -> Visibility.PUBLIC StatusesRequest.Visibility.unlisted -> Visibility.UNLISTED diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/ExposedTransaction.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/ExposedTransaction.kt index 54252131..bcd95261 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/core/ExposedTransaction.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/ExposedTransaction.kt @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service @Service class ExposedTransaction : Transaction { override suspend fun transaction(block: suspend () -> T): T { - return newSuspendedTransaction(transactionIsolation = java.sql.Connection.TRANSACTION_SERIALIZABLE) { + return newSuspendedTransaction { block() } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/MdcXrequestIdFilter.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/MdcXrequestIdFilter.kt new file mode 100644 index 00000000..f3ecdcf6 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/MdcXrequestIdFilter.kt @@ -0,0 +1,27 @@ +package dev.usbharu.hideout.service.core + +import jakarta.servlet.Filter +import jakarta.servlet.FilterChain +import jakarta.servlet.ServletRequest +import jakarta.servlet.ServletResponse +import org.slf4j.MDC +import org.springframework.stereotype.Service +import java.util.* + +@Service +class MdcXrequestIdFilter : Filter { + override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain) { + val uuid = UUID.randomUUID() + try { + MDC.put(KEY, uuid.toString()) + chain.doFilter(request, response) + } finally { + MDC.remove(KEY) + } + + } + + companion object { + val KEY = "x-request-id" + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt index dbf30d9c..5b376c68 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt @@ -3,6 +3,7 @@ package dev.usbharu.hideout.service.post import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.entity.Post import dev.usbharu.hideout.exception.UserNotFoundException +import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.repository.PostRepository import dev.usbharu.hideout.repository.UserRepository import org.springframework.stereotype.Service @@ -13,7 +14,8 @@ import java.util.* class PostServiceImpl( private val postRepository: PostRepository, private val userRepository: UserRepository, - private val timelineService: TimelineService + private val timelineService: TimelineService, + private val postQueryService: PostQueryService ) : PostService { private val interceptors = Collections.synchronizedList(mutableListOf()) @@ -30,8 +32,13 @@ class PostServiceImpl( } private suspend fun internalCreate(post: Post, isLocal: Boolean): Post { - timelineService.publishTimeline(post, isLocal) - return postRepository.save(post) + val save = try { + postRepository.save(post) + } catch (e: Exception) { + postQueryService.findByApId(post.apId) + } + timelineService.publishTimeline(save, isLocal) + return save } private suspend fun internalCreate(post: PostCreateDto, isLocal: Boolean): Post { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt index 76fb4c1e..474fa736 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt @@ -64,7 +64,11 @@ class UserServiceImpl( publicKey = user.publicKey, createdAt = Instant.now() ) - return userRepository.save(userEntity) + return try { + userRepository.save(userEntity) + } catch (e: Exception) { + userQueryService.findByUrl(user.url) + } } // TODO APのフォロー処理を作る diff --git a/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt b/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt index 78d01376..c6c1bfe5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt +++ b/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt @@ -20,7 +20,6 @@ object HttpUtil { subType: String, parameter: String ): Boolean { - println("$contentType/$subType $parameter") if (contentType != "application") { return false } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 1b8d5251..565f4968 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,17 +1,16 @@ - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] %logger{36} - %msg%n - + - + - - +