Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply fix to exit updater if the mongodb is not present when the container starts #1327

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}
Loading