-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
211 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...tlin/org/gitanimals/render/Application.kt → ...main/kotlin/org/gitanimals/Application.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
src/main/kotlin/org/gitanimals/star/controller/StargazerController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.gitanimals.star.controller | ||
|
||
import org.gitanimals.star.domain.StargazerService | ||
import org.springframework.web.bind.annotation.GetMapping | ||
import org.springframework.web.bind.annotation.PathVariable | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
class StargazerController( | ||
private val stargazerService: StargazerService, | ||
) { | ||
|
||
@GetMapping("/stargazers/{login}/press") | ||
fun isPressStar(@PathVariable("login") login: String): Map<String, Boolean> { | ||
val isPressStar = stargazerService.existsByLogin(login) | ||
|
||
return mapOf("isPressStar" to isPressStar) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.gitanimals.star.domain | ||
|
||
import jakarta.persistence.Column | ||
import jakarta.persistence.Entity | ||
import jakarta.persistence.Id | ||
|
||
@Entity | ||
class Stargazer( | ||
@Id | ||
@Column(name = "login") | ||
val login: String, | ||
) |
26 changes: 26 additions & 0 deletions
26
src/main/kotlin/org/gitanimals/star/domain/StargazerService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.gitanimals.star.domain | ||
|
||
import jakarta.persistence.EntityManager | ||
import org.springframework.cache.annotation.Cacheable | ||
import org.springframework.stereotype.Service | ||
import org.springframework.transaction.annotation.Transactional | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
class StargazerService( | ||
private val stargazersRepository: StargazersRepository, | ||
private val entityManager: EntityManager, | ||
) { | ||
|
||
@Cacheable(value = ["exists_by_login_cache"]) | ||
fun existsByLogin(login: String): Boolean = stargazersRepository.existsById(login) | ||
|
||
@Transactional | ||
fun updateAll(logins: List<String>) { | ||
stargazersRepository.deleteAllInBatch() | ||
|
||
logins.map { entityManager.persist(Stargazer(it)) } | ||
entityManager.flush() | ||
entityManager.clear() | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/kotlin/org/gitanimals/star/domain/StargazersRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.gitanimals.star.domain | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository | ||
|
||
interface StargazersRepository : JpaRepository<Stargazer, String> |
92 changes: 92 additions & 0 deletions
92
src/main/kotlin/org/gitanimals/star/infra/GithubStargazerApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package org.gitanimals.star.infra | ||
|
||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.core.io.ClassPathResource | ||
import org.springframework.http.HttpHeaders | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.client.RestClient | ||
import java.nio.charset.Charset | ||
|
||
@Component | ||
class GithubStargazerApi( | ||
@Value("\${github.token}") private val token: String, | ||
) { | ||
|
||
private val restClient = RestClient.create("https://api.github.com/graphql") | ||
|
||
fun getStargazers(): List<StargazersResponse> { | ||
val stargazers = mutableListOf(getStargazer("")) | ||
|
||
while (stargazers.last().pageInfo.hasNextPage) { | ||
val stargazer = getStargazer(stargazers.last().pageInfo.endCursor) | ||
stargazers.add(stargazer) | ||
} | ||
|
||
return stargazers | ||
} | ||
|
||
private fun getStargazer(endCursor: String): StargazersResponse { | ||
return restClient.post() | ||
.header(HttpHeaders.AUTHORIZATION, "Bearer $token") | ||
.body( | ||
mapOf( | ||
"query" to stargazerQuery.replaceFirst("*{endCursor}", endCursor) | ||
) | ||
).exchange { _, response -> | ||
assertIsSuccess(response) | ||
|
||
response.bodyTo(GithubStargazerGraphqlResponse::class.java)!! | ||
.data | ||
.repository | ||
.stargazers | ||
} | ||
} | ||
|
||
private fun assertIsSuccess(response: RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse) { | ||
require(response.statusCode.is2xxSuccessful) { | ||
"Bad request cause status : \"${response.statusText}\" message : \"${ | ||
response.bodyTo( | ||
String::class.java | ||
) | ||
}\"" | ||
} | ||
} | ||
|
||
companion object { | ||
private val stargazerQuery: String = | ||
ClassPathResource("github-graphql/stargazer.graphql") | ||
.getContentAsString(Charset.defaultCharset()) | ||
} | ||
} | ||
|
||
data class GithubStargazerGraphqlResponse( | ||
val data: Data, | ||
) { | ||
data class Data( | ||
val repository: Repository, | ||
) { | ||
data class Repository( | ||
val stargazers: StargazersResponse, | ||
) | ||
} | ||
} | ||
|
||
data class StargazersResponse( | ||
val edges: List<StarPushedPeople>, | ||
val pageInfo: PageInfo, | ||
) { | ||
|
||
data class StarPushedPeople( | ||
val starredAt: String, | ||
val node: Node, | ||
) { | ||
data class Node( | ||
val login: String, | ||
) | ||
} | ||
|
||
data class PageInfo( | ||
val endCursor: String, | ||
val hasNextPage: Boolean, | ||
) | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/kotlin/org/gitanimals/star/infra/StargazerBatchJob.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.gitanimals.star.infra | ||
|
||
import org.gitanimals.star.domain.StargazerService | ||
import org.springframework.boot.context.event.ApplicationStartedEvent | ||
import org.springframework.context.event.EventListener | ||
import org.springframework.scheduling.annotation.Scheduled | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class StargazerBatchJob( | ||
private val githubStargazerApi: GithubStargazerApi, | ||
private val stargazerService: StargazerService, | ||
) { | ||
|
||
@EventListener(ApplicationStartedEvent::class) | ||
fun initStargazer() { | ||
updateStargazer() | ||
} | ||
|
||
@Scheduled(cron = EVERY_DAY) | ||
fun updateStargazer() { | ||
val stargazers = githubStargazerApi.getStargazers() | ||
stargazerService.updateAll( | ||
stargazers.flatMap { stargazer -> | ||
stargazer.edges.map { edge -> | ||
edge.node.login | ||
} | ||
} | ||
) | ||
} | ||
|
||
|
||
companion object { | ||
private const val EVERY_DAY = "0 0 * * * ?" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
query { | ||
repository(owner: "git-goods", name: "gitanimals") { | ||
stargazers(first: 100, after: "*{endCursor}") { | ||
edges { | ||
starredAt | ||
node { | ||
login | ||
name | ||
url | ||
} | ||
} | ||
pageInfo { | ||
endCursor | ||
hasNextPage | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters