Skip to content

Commit

Permalink
Merge pull request #1327 from johnoliver/fix-mongo-issue-2
Browse files Browse the repository at this point in the history
Apply fix to exit updater if the mongodb is not present when the container starts
  • Loading branch information
karianna authored Jan 15, 2025
2 parents 9b2fd0d + b9931b1 commit df17cfe
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ interface APIDataStore {
fun getReleaseInfo(): ReleaseInfo
fun loadDataFromDb(forceUpdate: Boolean): AdoptRepos
fun getUpdateInfo(): UpdatedInfo
suspend fun isConnectedToDb(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ open class APIDataStoreImpl : APIDataStore {
return updatedAt
}

override suspend fun isConnectedToDb(): Boolean {
return dataStore.isConnected()
}

// open for
override fun getAdoptRepos(): AdoptRepos {
return binaryRepos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ interface ApiPersistence {
suspend fun hasReleaseNotesForGithubId(gitHubId: GitHubId): Boolean
suspend fun putReleaseNote(releaseNotes: ReleaseNotes)
suspend fun getReleaseNotes(vendor: Vendor, releaseName: String): ReleaseNotes?
suspend fun isConnected(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ open class MongoApiPersistence @Inject constructor(mongoClient: MongoClient) : M
private val releaseInfoCollection: MongoCollection<ReleaseInfo> = createCollection(mongoClient.getDatabase(), RELEASE_INFO_DB)
private val updateTimeCollection: MongoCollection<UpdatedInfo> = createCollection(mongoClient.getDatabase(), UPDATE_TIME_DB)
private val githubReleaseNotesCollection: MongoCollection<ReleaseNotes> = createCollection(mongoClient.getDatabase(), GH_RELEASE_NOTES)
private val client: MongoClient = mongoClient

companion object {
@JvmStatic
Expand Down Expand Up @@ -218,5 +219,9 @@ open class MongoApiPersistence @Inject constructor(mongoClient: MongoClient) : M
.firstOrNull()
}

override suspend fun isConnected(): Boolean {
return client.getDatabase().runCommand(Document("serverStatus", 1)).getDouble("uptime") >= 0
}

private fun matchGithubId(gitHubId: GitHubId) = Document("gitHubId.id", gitHubId.id)
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,8 @@ open class ApiDataStoreStub : APIDataStore {
123
)
}

override suspend fun isConnectedToDb(): Boolean {
return true
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package net.adoptium.api.v3

import com.mongodb.MongoException
import io.quarkus.arc.profile.UnlessBuildProfile
import io.quarkus.runtime.Quarkus
import io.quarkus.runtime.Startup
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
Expand All @@ -12,8 +14,8 @@ import kotlinx.coroutines.sync.withLock
import net.adoptium.api.v3.config.APIConfig
import net.adoptium.api.v3.dataSources.APIDataStore
import net.adoptium.api.v3.dataSources.ReleaseVersionResolver
import net.adoptium.api.v3.dataSources.UpdaterJsonMapper
import net.adoptium.api.v3.dataSources.UpdatableVersionSupplier
import net.adoptium.api.v3.dataSources.UpdaterJsonMapper
import net.adoptium.api.v3.dataSources.models.AdoptRepos
import net.adoptium.api.v3.dataSources.persitence.ApiPersistence
import net.adoptium.api.v3.models.Release
Expand All @@ -29,6 +31,7 @@ import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.concurrent.timerTask
import kotlin.system.exitProcess

@UnlessBuildProfile("test")
@ApplicationScoped
Expand Down Expand Up @@ -205,15 +208,21 @@ class V3Updater @Inject constructor(
}

fun run(instantFullUpdate: Boolean) {
val executor = Executors.newScheduledThreadPool(2)
assertConnectedToDb()

val executor = Executors.newScheduledThreadPool(2)

val delay = if (instantFullUpdate) 0L else 1L

var repo: AdoptRepos = try {
apiDataStore.loadDataFromDb(true)
} catch (e: java.lang.Exception) {
LOGGER.error("Failed to load db", e)
if (e is MongoException) {
LOGGER.error("Failed to connect to db, exiting")
Quarkus.asyncExit(2)
Quarkus.waitForExit()
}
AdoptRepos(emptyList())
}

Expand All @@ -236,6 +245,23 @@ class V3Updater @Inject constructor(
)
}

private fun assertConnectedToDb() {
val connected = try {
runBlocking {
return@runBlocking apiDataStore.isConnectedToDb()
}
} catch (e: java.lang.Exception) {
LOGGER.error("Failed to load db", e)
false
}

if (!connected) {
LOGGER.error("Failed to connect to db, exiting process")
Quarkus.asyncExit(2)
Quarkus.waitForExit()
}
}

private fun fullUpdate(currentRepo: AdoptRepos, releasesOnly: Boolean): AdoptRepos? {
// Must catch errors or may kill the scheduler
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package net.adoptium.api

import net.adoptium.api.v3.ReleaseIncludeFilter
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.quarkus.runtime.ApplicationLifecycleManager
import io.quarkus.runtime.Quarkus
import kotlinx.coroutines.runBlocking
import net.adoptium.api.v3.ReleaseFilterType
import net.adoptium.api.v3.ReleaseIncludeFilter
import net.adoptium.api.v3.TimeSource
import net.adoptium.api.v3.V3Updater
import net.adoptium.api.v3.dataSources.APIDataStore
import net.adoptium.api.v3.dataSources.models.AdoptRepos
import net.adoptium.api.v3.models.ReleaseType
import net.adoptium.api.v3.models.Vendor
Expand All @@ -13,6 +20,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledIfSystemProperty
import org.slf4j.LoggerFactory
import java.util.concurrent.atomic.AtomicBoolean

class V3UpdaterTest {

Expand All @@ -21,6 +29,34 @@ class V3UpdaterTest {
private val LOGGER = LoggerFactory.getLogger(this::class.java)
}

@Test
fun `exit is called when db not present`() {
runBlocking {
val apiDataStore: APIDataStore = mockk()
coEvery { apiDataStore.isConnectedToDb() } returns false

mockkStatic(Quarkus::class)
val called = AtomicBoolean(false)
every { Quarkus.asyncExit(any()) } answers {
called.set(true)
ApplicationLifecycleManager.exit(2)
}

val updater = V3Updater(
mockk(),
apiDataStore,
mockk(),
mockk(),
mockk(),
mockk(),
mockk()
)

updater.run(true)
assertTrue(called.get())
}
}

@Test
fun `checksum works`() {
runBlocking {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,8 @@ open class InMemoryApiPersistence @Inject constructor(var repos: AdoptRepos) : A
.filter { it.vendor == vendor }
.firstOrNull { it.release_name == releaseName }
}

override suspend fun isConnected(): Boolean {
return true
}
}

0 comments on commit df17cfe

Please sign in to comment.