mirror of https://github.com/usbharu/Hideout.git
wip
This commit is contained in:
parent
75f60a7a62
commit
997e28bdf6
|
@ -17,14 +17,15 @@
|
|||
package dev.usbharu.hideout.core.domain.event.actor
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor2
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventBody
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
||||
|
||||
class ActorDomainEventFactory(private val actor: Actor2) {
|
||||
fun createEvent(actorEvent: ActorEvent): DomainEvent {
|
||||
return DomainEvent.create(
|
||||
actorEvent.eventName,
|
||||
ActorEventBody(actor)
|
||||
ActorEventBody(actor),
|
||||
actorEvent.collectable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +36,7 @@ class ActorEventBody(actor: Actor2) : DomainEventBody(
|
|||
)
|
||||
)
|
||||
|
||||
enum class ActorEvent(val eventName: String) {
|
||||
enum class ActorEvent(val eventName: String, val collectable: Boolean = true) {
|
||||
update("ActorUpdate"),
|
||||
delete("ActorDelete"),
|
||||
checkUpdate("ActorCheckUpdate"),
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package dev.usbharu.hideout.core.domain.event.actorinstancerelationship
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.actorinstancerelationship.ActorInstanceRelationship
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventBody
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
||||
|
||||
class ActorInstanceRelationshipDomainEventFactory(private val actorInstanceRelationship: ActorInstanceRelationship) {
|
||||
fun createEvent(actorInstanceRelationshipEvent: ActorInstanceRelationshipEvent): DomainEvent {
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package dev.usbharu.hideout.core.domain.event.instance
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.instance.Instance
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventBody
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
||||
|
||||
class InstanceEventFactory(private val instance: Instance) {
|
||||
fun createEvent(event: InstanceEvent): DomainEvent {
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package dev.usbharu.hideout.core.domain.event.post
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.post.Post2
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventBody
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
||||
|
||||
class PostDomainEventFactory(private val post: Post2) {
|
||||
fun createEvent(postEvent: PostEvent): DomainEvent {
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.springframework.stereotype.Component
|
|||
import java.time.Instant
|
||||
import kotlin.math.max
|
||||
|
||||
@Deprecated("Actor2を使う")
|
||||
data class Actor private constructor(
|
||||
@get:NotNull
|
||||
@get:Positive
|
||||
|
|
|
@ -20,7 +20,7 @@ import dev.usbharu.hideout.core.domain.event.actor.ActorDomainEventFactory
|
|||
import dev.usbharu.hideout.core.domain.event.actor.ActorEvent.*
|
||||
import dev.usbharu.hideout.core.domain.model.instance.InstanceId
|
||||
import dev.usbharu.hideout.core.domain.model.shared.Domain
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
|
||||
import java.net.URI
|
||||
import java.time.Instant
|
||||
|
||||
|
@ -99,7 +99,7 @@ class Actor2 private constructor(
|
|||
}
|
||||
|
||||
abstract class Actor2Factory {
|
||||
protected suspend fun create(
|
||||
protected suspend fun internalCreate(
|
||||
id: ActorId,
|
||||
name: ActorName,
|
||||
domain: Domain,
|
||||
|
|
|
@ -18,6 +18,9 @@ package dev.usbharu.hideout.core.domain.model.actor
|
|||
|
||||
@JvmInline
|
||||
value class ActorId(val id: Long) {
|
||||
init {
|
||||
require(0 <= id)
|
||||
}
|
||||
companion object {
|
||||
val ghost = ActorId(0L)
|
||||
}
|
||||
|
|
|
@ -17,4 +17,8 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
@JvmInline
|
||||
value class ActorName(val name: String)
|
||||
value class ActorName(val name: String) {
|
||||
init {
|
||||
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
@JvmInline
|
||||
value class ActorPostsCount(private val postsCount: Long) {
|
||||
value class ActorPostsCount(private val postsCount: Int) {
|
||||
init {
|
||||
require(0 <= this.postsCount) { "Posts count must be greater than 0" }
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import dev.usbharu.hideout.core.domain.event.actorinstancerelationship.ActorInst
|
|||
import dev.usbharu.hideout.core.domain.event.actorinstancerelationship.ActorInstanceRelationshipEvent.*
|
||||
import dev.usbharu.hideout.core.domain.model.actor.ActorId
|
||||
import dev.usbharu.hideout.core.domain.model.instance.InstanceId
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
|
||||
|
||||
data class ActorInstanceRelationship(
|
||||
val actorId: ActorId,
|
||||
|
|
|
@ -18,7 +18,7 @@ package dev.usbharu.hideout.core.domain.model.instance
|
|||
|
||||
import dev.usbharu.hideout.core.domain.event.instance.InstanceEvent
|
||||
import dev.usbharu.hideout.core.domain.event.instance.InstanceEventFactory
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
|
||||
import java.net.URI
|
||||
import java.time.Instant
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.hibernate.validator.constraints.URL
|
|||
import org.springframework.stereotype.Component
|
||||
import java.time.Instant
|
||||
|
||||
@Deprecated("Post2を使う")
|
||||
data class Post private constructor(
|
||||
@get:Positive
|
||||
val id: Long,
|
||||
|
|
|
@ -20,7 +20,7 @@ import dev.usbharu.hideout.core.domain.event.post.PostDomainEventFactory
|
|||
import dev.usbharu.hideout.core.domain.event.post.PostEvent
|
||||
import dev.usbharu.hideout.core.domain.model.actor.ActorId
|
||||
import dev.usbharu.hideout.core.domain.model.media.MediaId
|
||||
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
|
||||
import java.net.URI
|
||||
import java.time.Instant
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2024 usbharu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.usbharu.hideout.core.domain.model.shared.domainevent
|
||||
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
|
||||
data class DomainEvent(
|
||||
private val id: String,
|
||||
private val name: String,
|
||||
private val occurredOn: Instant,
|
||||
private val body: DomainEventBody,
|
||||
) {
|
||||
companion object {
|
||||
fun create(name: String, body: DomainEventBody): DomainEvent {
|
||||
return DomainEvent(UUID.randomUUID().toString(), name, Instant.now(), body)
|
||||
}
|
||||
|
||||
fun reconstruct(id: String, name: String, occurredOn: Instant, body: DomainEventBody): DomainEvent {
|
||||
return DomainEvent(id, name, occurredOn, body)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,14 +17,14 @@
|
|||
package dev.usbharu.hideout.core.domain.service.actor
|
||||
|
||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor2
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface IRemoteActorCheckDomainService {
|
||||
fun isRemoteActor(actor: Actor): Boolean
|
||||
fun isRemoteActor(actor: Actor2): Boolean
|
||||
}
|
||||
|
||||
@Service
|
||||
class RemoteActorCheckDomainService(private val applicationConfig: ApplicationConfig) : IRemoteActorCheckDomainService {
|
||||
override fun isRemoteActor(actor: Actor): Boolean = actor.domain == applicationConfig.url.host
|
||||
override fun isRemoteActor(actor: Actor2): Boolean = actor.domain.domain == applicationConfig.url.host
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2024 usbharu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.usbharu.hideout.core.domain.shared.domainevent
|
||||
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* エンティティで発生したドメインイベント
|
||||
*
|
||||
* @property id ID
|
||||
* @property name ドメインイベント名
|
||||
* @property occurredOn 発生時刻
|
||||
* @property body ドメインイベントのボディ
|
||||
* @property collectable trueで同じドメインイベント名でをまとめる
|
||||
*/
|
||||
data class DomainEvent(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val occurredOn: Instant,
|
||||
val body: DomainEventBody,
|
||||
val collectable: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
fun create(name: String, body: DomainEventBody, collectable: Boolean = false): DomainEvent {
|
||||
return DomainEvent(UUID.randomUUID().toString(), name, Instant.now(), body, collectable)
|
||||
}
|
||||
|
||||
fun reconstruct(
|
||||
id: String,
|
||||
name: String,
|
||||
occurredOn: Instant,
|
||||
body: DomainEventBody,
|
||||
collectable: Boolean
|
||||
): DomainEvent {
|
||||
return DomainEvent(id, name, occurredOn, body, collectable)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.usbharu.hideout.core.domain.model.shared.domainevent
|
||||
package dev.usbharu.hideout.core.domain.shared.domainevent
|
||||
|
||||
abstract class DomainEventBody(val map: Map<String, Any>) {
|
||||
fun toMap(): Map<String, Any> {
|
|
@ -0,0 +1,5 @@
|
|||
package dev.usbharu.hideout.core.domain.shared.domainevent
|
||||
|
||||
interface DomainEventPublisher {
|
||||
suspend fun publishEvent(domainEvent: DomainEvent)
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.usbharu.hideout.core.domain.model.shared.domainevent
|
||||
package dev.usbharu.hideout.core.domain.shared.domainevent
|
||||
|
||||
abstract class DomainEventStorable {
|
||||
private val domainEvents: MutableList<DomainEvent> = mutableListOf()
|
|
@ -0,0 +1,7 @@
|
|||
package dev.usbharu.hideout.core.domain.shared.domainevent
|
||||
|
||||
interface DomainEventSubscriber {
|
||||
fun subscribe(eventName: String, domainEventConsumer: DomainEventConsumer)
|
||||
}
|
||||
|
||||
typealias DomainEventConsumer = (DomainEvent) -> Unit
|
|
@ -0,0 +1,22 @@
|
|||
package dev.usbharu.hideout.core.domain.shared.repository
|
||||
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventPublisher
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface DomainEventPublishableRepository<T : DomainEventStorable> {
|
||||
val domainEventPublisher: DomainEventPublisher
|
||||
suspend fun update(entity: T) {
|
||||
entity.getDomainEvents().distinctBy {
|
||||
if (it.collectable) {
|
||||
it.name
|
||||
} else {
|
||||
it.id
|
||||
}
|
||||
}.forEach {
|
||||
domainEventPublisher.publishEvent(it)
|
||||
}
|
||||
entity.clearDomainEvents()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dev.usbharu.hideout.core.infrastructure.exposedrepository
|
||||
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor2
|
||||
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
|
||||
import dev.usbharu.hideout.core.domain.model.actor.ActorId
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventPublisher
|
||||
import dev.usbharu.hideout.core.domain.shared.repository.DomainEventPublishableRepository
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
class ExposedActor2Repository(override val domainEventPublisher: DomainEventPublisher) : AbstractRepository(),
|
||||
DomainEventPublishableRepository<Actor2>, Actor2Repository {
|
||||
override val logger: Logger
|
||||
get() = Companion.logger
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(ExposedActor2Repository::class.java)
|
||||
}
|
||||
|
||||
override suspend fun save(actor: Actor2): Actor2 {
|
||||
query {
|
||||
|
||||
}
|
||||
update(actor)
|
||||
return actor
|
||||
}
|
||||
|
||||
override suspend fun delete(actor: Actor2) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findById(id: ActorId): Actor2? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ class Actor2FactoryImpl(
|
|||
): Actor2 {
|
||||
val actorName = ActorName(name)
|
||||
val userUrl = "${applicationConfig.url}/users/${actorName.name}"
|
||||
return super.create(
|
||||
return super.internalCreate(
|
||||
id = ActorId(idGenerateService.generateId()),
|
||||
name = actorName,
|
||||
domain = Domain(applicationConfig.url.host),
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class Actor2Test {
|
||||
@Test
|
||||
fun alsoKnownAsに自分自身が含まれてはいけない() {
|
||||
TestActor2Factory.create()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
class ActorDescriptionTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ActorIdTest {
|
||||
@Test
|
||||
fun idを負の数にすることはできない() {
|
||||
org.junit.jupiter.api.assertThrows<IllegalArgumentException> {
|
||||
ActorId(-1)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
class ActorPublicKeyTest
|
|
@ -0,0 +1,5 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
class ActorScreenNameTest {
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package dev.usbharu.hideout.core.domain.model.actor
|
||||
|
||||
import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService
|
||||
import dev.usbharu.hideout.core.domain.model.instance.InstanceId
|
||||
import dev.usbharu.hideout.core.domain.model.shared.Domain
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.net.URI
|
||||
import java.time.Instant
|
||||
|
||||
object TestActor2Factory : Actor2.Actor2Factory() {
|
||||
private val idGenerateService = TwitterSnowflakeIdGenerateService
|
||||
|
||||
fun create(
|
||||
id: Long = generateId(),
|
||||
actorName: String = "test-$id",
|
||||
domain: String = "example.com",
|
||||
actorScreenName: String = actorName,
|
||||
description: String = "test description",
|
||||
inbox: URI = URI.create("https://example.com/$id/inbox"),
|
||||
outbox: URI = URI.create("https://example.com/$id/outbox"),
|
||||
uri: URI = URI.create("https://example.com/$id"),
|
||||
publicKey: ActorPublicKey,
|
||||
privateKey: ActorPrivateKey?,
|
||||
createdAt: Instant = Instant.now(),
|
||||
keyId: String = "https://example.com/$id#key-id",
|
||||
followersEndpoint: URI = URI.create("https://example.com/$id/followers"),
|
||||
followingEndpoint: URI = URI.create("https://example.com/$id/following"),
|
||||
instanceId: Long = 1L,
|
||||
locked: Boolean = false,
|
||||
followersCount: Int = 0,
|
||||
followingCount: Int = 0,
|
||||
postCount: Int = 0,
|
||||
lastPostDate: Instant? = null,
|
||||
suspend: Boolean = false
|
||||
): Actor2 {
|
||||
return runBlocking {
|
||||
super.internalCreate(
|
||||
id = ActorId(id),
|
||||
name = ActorName(actorName),
|
||||
domain = Domain(domain),
|
||||
screenName = TestActorScreenNameFactory.create(actorScreenName),
|
||||
description = TestActorDescriptionFactory.create(description),
|
||||
inbox = inbox,
|
||||
outbox = outbox,
|
||||
url = uri,
|
||||
publicKey = publicKey,
|
||||
privateKey = privateKey,
|
||||
createdAt = createdAt,
|
||||
keyId = ActorKeyId(keyId),
|
||||
followersEndpoint = followersEndpoint,
|
||||
followingEndpoint = followingEndpoint,
|
||||
InstanceId(instanceId),
|
||||
locked,
|
||||
followersCount = ActorRelationshipCount(followersCount),
|
||||
followingCount = ActorRelationshipCount(followingCount),
|
||||
postsCount = ActorPostsCount(postCount),
|
||||
lastPostDate = lastPostDate,
|
||||
suspend = suspend
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateId(): Long = runBlocking {
|
||||
idGenerateService.generateId()
|
||||
}
|
||||
}
|
||||
|
||||
object TestActorScreenNameFactory : ActorScreenName.ActorScreenNameFactory() {
|
||||
fun create(name: String): ActorScreenName {
|
||||
return runBlocking {
|
||||
super.create(name, emptyList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TestActorDescriptionFactory : ActorDescription.ActorDescriptionFactory() {
|
||||
fun create(description: String): ActorDescription {
|
||||
return runBlocking {
|
||||
super.create(description, emptyList())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package dev.usbharu.hideout.core.domain.service.actor
|
||||
|
||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.net.URI
|
||||
|
||||
class RemoteActorCheckDomainServiceTest {
|
||||
@Test
|
||||
fun リモートのドメインならtrueを返す() {
|
||||
val actor =
|
||||
|
||||
RemoteActorCheckDomainService(ApplicationConfig(URI.create("https://example.com").toURL())).isRemoteActor()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue