Skip to content

Commit

Permalink
Merge pull request #20 from Lukinhasssss/feature/video-rest-client
Browse files Browse the repository at this point in the history
Automated PR from feature/video-rest-client
  • Loading branch information
Lukinhasssss committed May 28, 2024
2 parents 01218a3 + b1afcbf commit bf57d7c
Show file tree
Hide file tree
Showing 21 changed files with 507 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.lukinhasssss.catalogo.infrastructure.category

import com.lukinhasssss.catalogo.domain.category.Category

interface CategoryGateway {
interface CategoryClient {

fun categoryOfId(categoryId: String?): Category?
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import org.springframework.web.client.RestClient

@Component
@CacheConfig(cacheNames = ["admin-categories"])
class CategoryRestGateway(
class CategoryRestClient(
@Categories private val restClient: RestClient,
private val getClientCredentials: GetClientCredentials
) : CategoryGateway, HttpClient {
) : CategoryClient, HttpClient {

companion object {
const val NAMESPACE = "categories"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Categories
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Genres
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Keycloak
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Videos
import com.lukinhasssss.catalogo.infrastructure.configuration.properties.RestClientProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
Expand Down Expand Up @@ -55,6 +56,11 @@ class RestClientConfig {
@Genres
fun genreRestClientProperties() = RestClientProperties()

@Bean
@ConfigurationProperties(prefix = "rest-client.videos")
@Videos
fun videoRestClientProperties() = RestClientProperties()

@Bean
@Keycloak
fun keycloakHttpClient(
Expand All @@ -75,4 +81,11 @@ class RestClientConfig {
@Genres properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)

@Bean
@Videos
fun videoHttpClient(
@Videos properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.lukinhasssss.catalogo.infrastructure.configuration.annotations

import org.springframework.beans.factory.annotation.Qualifier

@Qualifier("Video")
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
annotation class Videos
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ package com.lukinhasssss.catalogo.infrastructure.genre

import com.lukinhasssss.catalogo.infrastructure.genre.models.GenreDTO

fun interface GenreGateway {
fun interface GenreClient {
fun genreOfId(genreId: String?): GenreDTO?
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import org.springframework.web.client.RestClient

@Component
@CacheConfig(cacheNames = ["admin-genres"])
class GenreRestGateway(
class GenreRestClient(
@Genres private val restClient: RestClient,
private val getClientCredentials: GetClientCredentials
) : GenreGateway, HttpClient {
) : GenreClient, HttpClient {

companion object {
const val NAMESPACE = "genres"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.lukinhasssss.catalogo.infrastructure.kafka
import com.fasterxml.jackson.core.type.TypeReference
import com.lukinhasssss.catalogo.application.category.delete.DeleteCategoryUseCase
import com.lukinhasssss.catalogo.application.category.save.SaveCategoryUseCase
import com.lukinhasssss.catalogo.infrastructure.category.CategoryGateway
import com.lukinhasssss.catalogo.infrastructure.category.CategoryClient
import com.lukinhasssss.catalogo.infrastructure.category.models.CategoryEvent
import com.lukinhasssss.catalogo.infrastructure.configuration.json.Json
import com.lukinhasssss.catalogo.infrastructure.kafka.models.connect.MessageValue
Expand All @@ -21,7 +21,7 @@ import org.springframework.stereotype.Component

@Component
class CategoryListener(
private val categoryGateway: CategoryGateway,
private val categoryClient: CategoryClient,
private val saveCategoryUseCase: SaveCategoryUseCase,
private val deleteCategoryUseCase: DeleteCategoryUseCase
) {
Expand Down Expand Up @@ -52,7 +52,7 @@ class CategoryListener(
if (Operation.isDelete(operation)) {
deleteCategoryUseCase.execute(messagePayload.before?.id)
} else {
categoryGateway.categoryOfId(messagePayload.after?.id).let {
categoryClient.categoryOfId(messagePayload.after?.id).let {
saveCategoryUseCase.execute(it)
}
}
Expand All @@ -68,7 +68,7 @@ class CategoryListener(
if (Operation.isDelete(operation)) {
deleteCategoryUseCase.execute(messagePayload.before?.id)
} else {
categoryGateway.categoryOfId(messagePayload.after?.id).let {
categoryClient.categoryOfId(messagePayload.after?.id).let {
saveCategoryUseCase.execute(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.type.TypeReference
import com.lukinhasssss.catalogo.application.genre.delete.DeleteGenreUseCase
import com.lukinhasssss.catalogo.application.genre.save.SaveGenreUseCase
import com.lukinhasssss.catalogo.infrastructure.configuration.json.Json
import com.lukinhasssss.catalogo.infrastructure.genre.GenreGateway
import com.lukinhasssss.catalogo.infrastructure.genre.GenreClient
import com.lukinhasssss.catalogo.infrastructure.genre.models.GenreEvent
import com.lukinhasssss.catalogo.infrastructure.kafka.models.connect.MessageValue
import com.lukinhasssss.catalogo.infrastructure.kafka.models.connect.Operation
Expand All @@ -21,7 +21,7 @@ import org.springframework.stereotype.Component

@Component
class GenreListener(
private val genreGateway: GenreGateway,
private val genreClient: GenreClient,
private val saveGenreUseCase: SaveGenreUseCase,
private val deleteGenreUseCase: DeleteGenreUseCase
) {
Expand Down Expand Up @@ -52,7 +52,7 @@ class GenreListener(
if (Operation.isDelete(operation)) {
deleteGenreUseCase.execute(DeleteGenreUseCase.Input(messagePayload.before?.id))
} else {
genreGateway.genreOfId(messagePayload.after?.id)?.run {
genreClient.genreOfId(messagePayload.after?.id)?.run {
val input = SaveGenreUseCase.Input(id, name, isActive, categoriesId, createdAt, updatedAt, deletedAt)
saveGenreUseCase.execute(input)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.lukinhasssss.catalogo.infrastructure.video

import com.lukinhasssss.catalogo.infrastructure.video.models.VideoDTO

fun interface VideoClient {
fun videoOfId(videoId: String?): VideoDTO?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.lukinhasssss.catalogo.infrastructure.video

import com.lukinhasssss.catalogo.infrastructure.authentication.GetClientCredentials
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Videos
import com.lukinhasssss.catalogo.infrastructure.utils.HttpClient
import com.lukinhasssss.catalogo.infrastructure.video.models.VideoDTO
import io.github.resilience4j.bulkhead.annotation.Bulkhead
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker
import io.github.resilience4j.retry.annotation.Retry
import org.springframework.cache.annotation.CacheConfig
import org.springframework.cache.annotation.Cacheable
import org.springframework.http.HttpHeaders
import org.springframework.stereotype.Component
import org.springframework.web.client.RestClient

private const val VIDEO_CACHE_NAME = "admin-videos"
private const val VIDEO_CACHE_KEY = "#videoId"

@Component
@CacheConfig(cacheNames = [VIDEO_CACHE_NAME])
class VideoRestClient(
@Videos private val restClient: RestClient,
private val getClientCredentials: GetClientCredentials
) : VideoClient, HttpClient {

companion object {
const val NAMESPACE = "videos"
}

override fun namespace(): String = NAMESPACE

// Resilience4j default order: Bulkhead -> TimeLimiter -> RateLimiter -> CircuitBreaker -> Retry
@Retry(name = NAMESPACE)
@Bulkhead(name = NAMESPACE)
@CircuitBreaker(name = NAMESPACE)
@Cacheable(key = VIDEO_CACHE_KEY, unless = "#result == null")
override fun videoOfId(videoId: String?): VideoDTO? = doGet(videoId) {
getClientCredentials.retrieve().let { token ->
restClient.get()
.uri("/{id}", videoId)
.header(HttpHeaders.AUTHORIZATION, "Bearer $token")
.retrieve()
.onStatus(isNotFound(), notFoundHandler(videoId))
.onStatus(is5xx(), serverErrorHandler(videoId))
.body(VideoDTO::class.java)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.lukinhasssss.catalogo.infrastructure.video.models

data class VideoDTO(
val id: String,
val title: String,
val description: String,
val yearLaunched: Int,
val rating: String,
val duration: Double,
val opened: Boolean,
val published: Boolean,
val banner: String? = null,
val thumbnail: String? = null,
val thumbnailHalf: String? = null,
val trailer: String? = null,
val video: String? = null,
val categoriesId: Set<String>,
val castMembersId: Set<String>,
val genresId: Set<String>,
val createdAt: String,
val updatedAt: String
)
11 changes: 10 additions & 1 deletion infrastructure/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cache:
type: cache2k
names: admin-categories, admin-genres
names: admin-categories, admin-genres, admin-videos
max-entries: 200
ttl: 60 # seconds

Expand Down Expand Up @@ -51,6 +51,9 @@ rest-client:
genres:
base-url: ${rest-client.base-url}/api/genres
read-timeout: 1_000
videos:
base-url: ${rest-client.base-url}/api/videos
read-timeout: 1_000

logging:
level:
Expand Down Expand Up @@ -106,6 +109,8 @@ resilience4j.bulkhead:
baseConfig: default
genres:
baseConfig: default
videos:
baseConfig: default

resilience4j.retry:
configs:
Expand All @@ -128,6 +133,8 @@ resilience4j.retry:
baseConfig: default
genres:
baseConfig: default
videos:
baseConfig: default

resilience4j.circuitbreaker:
configs:
Expand Down Expand Up @@ -157,6 +164,8 @@ resilience4j.circuitbreaker:
baseConfig: default
genres:
baseConfig: default
videos:
baseConfig: default

management:
info:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package com.lukinhasssss.catalogo

import com.fasterxml.jackson.databind.ObjectMapper
import com.github.tomakehurst.wiremock.client.WireMock
import com.lukinhasssss.catalogo.infrastructure.category.CategoryRestGateway
import com.lukinhasssss.catalogo.infrastructure.category.CategoryRestClient
import com.lukinhasssss.catalogo.infrastructure.configuration.WebServerConfig
import com.lukinhasssss.catalogo.infrastructure.genre.GenreRestGateway
import com.lukinhasssss.catalogo.infrastructure.genre.GenreRestClient
import com.lukinhasssss.catalogo.infrastructure.video.VideoRestClient
import io.github.resilience4j.bulkhead.BulkheadRegistry
import io.github.resilience4j.circuitbreaker.CircuitBreaker
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry
Expand All @@ -28,8 +29,9 @@ import kotlin.test.assertEquals
abstract class AbstractRestClientTest {

companion object {
const val CATEGORY = CategoryRestGateway.NAMESPACE
const val GENRE = GenreRestGateway.NAMESPACE
const val CATEGORY = CategoryRestClient.NAMESPACE
const val GENRE = GenreRestClient.NAMESPACE
const val VIDEO = VideoRestClient.NAMESPACE
}

@Autowired
Expand All @@ -51,6 +53,7 @@ abstract class AbstractRestClientTest {
resetAllCaches()
listOf(CATEGORY).forEach { resetFaultTolerance(it) }
listOf(GENRE).forEach { resetFaultTolerance(it) }
listOf(VIDEO).forEach { resetFaultTolerance(it) }
}

fun cache(name: String) = cacheManager.getCache(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.lukinhasssss.catalogo
import com.lukinhasssss.catalogo.infrastructure.castmember.persistence.CastMemberRepository
import com.lukinhasssss.catalogo.infrastructure.category.persistence.CategoryRepository
import com.lukinhasssss.catalogo.infrastructure.genre.persistence.GenreRepository
import com.lukinhasssss.catalogo.infrastructure.video.persistence.VideoRepository
import io.mockk.mockk
import org.springframework.context.annotation.Bean

Expand All @@ -16,4 +17,7 @@ class IntegrationTestConfiguration {

@Bean
fun genreRepository() = mockk<GenreRepository>()

@Bean
fun videoRepository() = mockk<VideoRepository>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import org.springframework.http.MediaType
import kotlin.test.assertEquals
import kotlin.test.assertNull

class CategoryRestGatewayTest : AbstractRestClientTest() {
class CategoryRestClientTest : AbstractRestClientTest() {

@Autowired
lateinit var target: CategoryRestGateway
lateinit var target: CategoryRestClient

@SpykBean
lateinit var credentialsManager: ClientCredentialsManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import org.springframework.http.MediaType
import kotlin.test.assertEquals
import kotlin.test.assertNull

class GenreRestGatewayTest : AbstractRestClientTest() {
class GenreRestClientTest : AbstractRestClientTest() {

@Autowired
lateinit var target: GenreRestGateway
lateinit var target: GenreRestClient

@SpykBean
lateinit var credentialsManager: ClientCredentialsManager
Expand Down
Loading

0 comments on commit bf57d7c

Please sign in to comment.