Skip to content

Commit

Permalink
Added solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
svtk committed Dec 29, 2020
1 parent 3f40c75 commit 06b24a7
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 16 deletions.
11 changes: 11 additions & 0 deletions src/contributors/GitHubService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ interface GitHubService {
@Path("owner") owner: String,
@Path("repo") repo: String
): Call<List<User>>

@GET("orgs/{org}/repos?per_page=100")
suspend fun getOrgRepos(
@Path("org") org: String
): Response<List<Repo>>

@GET("repos/{owner}/{repo}/contributors?per_page=100")
suspend fun getRepoContributors(
@Path("owner") owner: String,
@Path("repo") repo: String
): Response<List<User>>
}

@Serializable
Expand Down
4 changes: 3 additions & 1 deletion src/tasks/Aggregation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ TODO: Write aggregation code.
You can use 'Navigate | Test' menu action (note the shortcut) to navigate to the test.
*/
fun List<User>.aggregate(): List<User> =
this
groupBy { it.login }
.map { (login, group) -> User(login, group.sumBy { it.contributions }) }
.sortedByDescending { it.contributions }
2 changes: 1 addition & 1 deletion src/tasks/Request2Background.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import kotlin.concurrent.thread

fun loadContributorsBackground(service: GitHubService, req: RequestData, updateResults: (List<User>) -> Unit) {
thread {
loadContributorsBlocking(service, req)
updateResults(loadContributorsBlocking(service, req))
}
}
8 changes: 5 additions & 3 deletions src/tasks/Request3Callbacks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ fun loadContributorsCallbacks(service: GitHubService, req: RequestData, updateRe
service.getOrgReposCall(req.org).onResponse { responseRepos ->
logRepos(req, responseRepos)
val repos = responseRepos.bodyList()
val allUsers = mutableListOf<User>()
val allUsers = Collections.synchronizedList(mutableListOf<User>())
val numberOfProcessed = AtomicInteger(0)
for (repo in repos) {
service.getRepoContributorsCall(req.org, repo.name).onResponse { responseUsers ->
logUsers(repo, responseUsers)
val users = responseUsers.bodyList()
allUsers += users
if (numberOfProcessed.incrementAndGet() == repos.size) {
updateResults(allUsers.aggregate())
}
}
}
// TODO: Why this code doesn't work? How to fix that?
updateResults(allUsers.aggregate())
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/tasks/Request4Suspend.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@ package tasks
import contributors.*

suspend fun loadContributorsSuspend(service: GitHubService, req: RequestData): List<User> {
TODO()
val repos = service
.getOrgRepos(req.org)
.also { logRepos(req, it) }
.bodyList()

return repos.flatMap { repo ->
service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()
}.aggregate()
}
14 changes: 13 additions & 1 deletion src/tasks/Request5Concurrent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,17 @@ import contributors.*
import kotlinx.coroutines.*

suspend fun loadContributorsConcurrent(service: GitHubService, req: RequestData): List<User> = coroutineScope {
TODO()
val repos = service
.getOrgRepos(req.org)
.also { logRepos(req, it) }
.bodyList()

val deferreds: List<Deferred<List<User>>> = repos.map { repo ->
async {
service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()
}
}
deferreds.awaitAll().flatten().aggregate()
}
16 changes: 15 additions & 1 deletion src/tasks/Request5NotCancellable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,19 @@ import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext

suspend fun loadContributorsNotCancellable(service: GitHubService, req: RequestData): List<User> {
TODO()
val repos = service
.getOrgRepos(req.org)
.also { logRepos(req, it) }
.bodyList()

val deferreds: List<Deferred<List<User>>> = repos.map { repo ->
GlobalScope.async(Dispatchers.Default) {
log("starting loading for ${repo.name}")
delay(3000)
service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()
}
}
return deferreds.awaitAll().flatten().aggregate()
}
15 changes: 14 additions & 1 deletion src/tasks/Request6Progress.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,18 @@ suspend fun loadContributorsProgress(
req: RequestData,
updateResults: suspend (List<User>, completed: Boolean) -> Unit
) {
TODO()
val repos = service
.getOrgRepos(req.org)
.also { logRepos(req, it) }
.bodyList()

var allUsers = emptyList<User>()
for ((index, repo) in repos.withIndex()) {
val users = service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()

allUsers = (allUsers + users).aggregate()
updateResults(allUsers, index == repos.lastIndex)
}
}
23 changes: 20 additions & 3 deletions src/tasks/Request7Channels.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,25 @@ suspend fun loadContributorsChannels(
service: GitHubService,
req: RequestData,
updateResults: suspend (List<User>, completed: Boolean) -> Unit
) {
coroutineScope {
TODO()
) = coroutineScope {
val repos = service
.getOrgRepos(req.org)
.also { logRepos(req, it) }
.bodyList()

val channel = Channel<List<User>>()
for (repo in repos) {
launch {
val users = service.getRepoContributors(req.org, repo.name)
.also { logUsers(repo, it) }
.bodyList()
channel.send(users)
}
}
var allUsers = emptyList<User>()
repeat(repos.size) {
val users = channel.receive()
allUsers = (allUsers + users).aggregate()
updateResults(allUsers, it == repos.lastIndex)
}
}
4 changes: 0 additions & 4 deletions test/contributors/MockGithubService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ object MockGithubService : GitHubService {
return Calls.response(reposMap.getValue(repo).users)
}

/*
// Uncomment the following implementations after adding these methods to GitHubService:
override suspend fun getOrgRepos(org: String): Response<List<Repo>> {
delay(reposDelay)
return Response.success(repos)
Expand All @@ -27,5 +24,4 @@ object MockGithubService : GitHubService {
delay(testRepo.delay)
return Response.success(testRepo.users)
}
*/
}

0 comments on commit 06b24a7

Please sign in to comment.