diff --git a/modules/core/shared/src/main/scala/scaladex/core/service/SchedulerDatabase.scala b/modules/core/shared/src/main/scala/scaladex/core/service/SchedulerDatabase.scala index 1b356b6eb..cc7334536 100644 --- a/modules/core/shared/src/main/scala/scaladex/core/service/SchedulerDatabase.scala +++ b/modules/core/shared/src/main/scala/scaladex/core/service/SchedulerDatabase.scala @@ -28,9 +28,9 @@ trait SchedulerDatabase extends WebDatabase { def insertArtifacts(artifacts: Seq[Artifact]): Future[Unit] // for init process def insertDependencies(dependencies: Seq[ArtifactDependency]): Future[Unit] def updateArtifacts(artifacts: Seq[Artifact.Reference], newRef: Project.Reference): Future[Int] - def updateArtifactReleaseDate(reference: Artifact.Reference, releaseDate: Instant): Future[Int] + def updateArtifactReleaseDate(ref: Artifact.Reference, releaseDate: Instant): Future[Int] def getGroupIds(): Future[Seq[Artifact.GroupId]] def getArtifactIds(ref: Project.Reference): Future[Seq[(Artifact.GroupId, Artifact.ArtifactId)]] def getArtifactRefs(): Future[Seq[Artifact.Reference]] - def updateLatestVersion(ref: Artifact.Reference): Future[Unit] + def updateLatestVersion(ref: Project.Reference, artifact: Artifact.Reference): Future[Unit] } diff --git a/modules/core/shared/src/test/scala/scaladex/core/test/InMemoryDatabase.scala b/modules/core/shared/src/test/scala/scaladex/core/test/InMemoryDatabase.scala index 33887e9cc..e9bb8ad23 100644 --- a/modules/core/shared/src/test/scala/scaladex/core/test/InMemoryDatabase.scala +++ b/modules/core/shared/src/test/scala/scaladex/core/test/InMemoryDatabase.scala @@ -216,8 +216,8 @@ class InMemoryDatabase extends SchedulerDatabase { override def getArtifactIds(ref: Project.Reference): Future[Seq[(Artifact.GroupId, Artifact.ArtifactId)]] = Future.successful(getProjectArtifactsSync(ref).map(a => (a.groupId, a.artifactId)).distinct.toSeq) - override def updateLatestVersion(ref: Artifact.Reference): Future[Unit] = { - latestArtifacts += (ref.groupId, ref.artifactId) -> ref + override def updateLatestVersion(ref: Project.Reference, artifact: Artifact.Reference): Future[Unit] = { + latestArtifacts += (artifact.groupId, artifact.artifactId) -> artifact Future.unit } diff --git a/modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala b/modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala index 755bfff81..02aa6766c 100644 --- a/modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala +++ b/modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala @@ -5,16 +5,17 @@ import java.util.UUID import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future +import scala.concurrent.duration._ import cats.effect.IO +import com.github.blemale.scaffeine.AsyncLoadingCache +import com.github.blemale.scaffeine.Scaffeine import com.typesafe.scalalogging.LazyLogging import com.zaxxer.hikari.HikariDataSource import doobie.implicits._ import scaladex.core.model._ import scaladex.core.service.SchedulerDatabase import scaladex.infra.sql._ -import com.github.blemale.scaffeine.Scaffeine -import scala.concurrent.duration._ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) extends SchedulerDatabase with LazyLogging { private val flyway = DoobieUtils.flyway(datasource) @@ -127,8 +128,10 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten ): Future[Seq[Artifact]] = run(ArtifactTable.selectArtifactByProjectAndNameAndVersion.to[Seq](ref, name, version)) + private val projectLatestArtifactsCache: AsyncLoadingCache[Project.Reference, Seq[Artifact]] = + Scaffeine().buildAsyncFuture(ref => run(ArtifactTable.selectLatestArtifacts.to[Seq](ref))) override def getProjectLatestArtifacts(ref: Project.Reference): Future[Seq[Artifact]] = - run(ArtifactTable.selectLatestArtifacts.to[Seq](ref)) + projectLatestArtifactsCache.get(ref) override def getProjectDependencies(projectRef: Project.Reference): Future[Seq[ArtifactDependency]] = run(ArtifactDependencyTable.selectDependencyFromProject.to[Seq](projectRef)) @@ -145,9 +148,8 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten def countProjects(): Future[Long] = run(ProjectTable.countProjects.unique) - private val countArtifactsCache = Scaffeine() - .refreshAfterWrite(5.minutes) - .buildAsyncFuture[Unit, Long](_ => run(ArtifactTable.count.unique)) + private val countArtifactsCache: AsyncLoadingCache[Unit, Long] = + Scaffeine().refreshAfterWrite(5.minutes).buildAsyncFuture[Unit, Long](_ => run(ArtifactTable.count.unique)) override def countArtifacts(): Future[Long] = countArtifactsCache.get(()) def countDependencies(): Future[Long] = @@ -214,12 +216,12 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten override def deleteUser(userId: UUID): Future[Unit] = run(UserSessionsTable.deleteById.run(userId).map(_ => ())) - override def updateLatestVersion(ref: Artifact.Reference): Future[Unit] = { + override def updateLatestVersion(ref: Project.Reference, artifact: Artifact.Reference): Future[Unit] = { val transaction = for { - _ <- ArtifactTable.setLatestVersion.run(ref) - _ <- ArtifactTable.unsetOthersLatestVersion.run(ref) + _ <- ArtifactTable.setLatestVersion.run(artifact) + _ <- ArtifactTable.unsetOthersLatestVersion.run(artifact) } yield () - run(transaction) + run(transaction).map(_ => projectLatestArtifactsCache.underlying.synchronous().invalidate(ref)) } override def countVersions(ref: Project.Reference): Future[Long] = diff --git a/modules/server/src/main/scala/scaladex/server/service/ArtifactService.scala b/modules/server/src/main/scala/scaladex/server/service/ArtifactService.scala index a9dd278b9..2530812f6 100644 --- a/modules/server/src/main/scala/scaladex/server/service/ArtifactService.scala +++ b/modules/server/src/main/scala/scaladex/server/service/ArtifactService.scala @@ -32,7 +32,12 @@ class ArtifactService(database: SchedulerDatabase)(implicit ec: ExecutionContext project <- database.getProject(artifact.projectRef).map(_.get) _ <- database.insertArtifact(artifact) _ <- database.insertDependencies(dependencies) - _ <- updateLatestVersion(artifact.groupId, artifact.artifactId, project.settings.preferStableVersion) + _ <- updateLatestVersion( + project.reference, + artifact.groupId, + artifact.artifactId, + project.settings.preferStableVersion + ) } yield isNewProject } @@ -69,11 +74,12 @@ class ArtifactService(database: SchedulerDatabase)(implicit ec: ExecutionContext for { artifactIds <- database.getArtifactIds(ref) _ <- artifactIds.mapSync { - case (groupId, artifactId) => updateLatestVersion(groupId, artifactId, preferStableVersion) + case (groupId, artifactId) => updateLatestVersion(ref, groupId, artifactId, preferStableVersion) } } yield artifactIds.size def updateLatestVersion( + ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId, preferStableVersion: Boolean @@ -81,7 +87,7 @@ class ArtifactService(database: SchedulerDatabase)(implicit ec: ExecutionContext for { artifacts <- database.getArtifacts(groupId, artifactId) latestVersion = computeLatestVersion(artifacts.map(_.version), preferStableVersion) - _ <- database.updateLatestVersion(Artifact.Reference(groupId, artifactId, latestVersion)) + _ <- database.updateLatestVersion(ref, Artifact.Reference(groupId, artifactId, latestVersion)) } yield () def computeLatestVersion(versions: Seq[Version], preferStableVersion: Boolean): Version = {